summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorniklas <niklas@openbsd.org>1998-02-14 19:08:25 +0000
committerniklas <niklas@openbsd.org>1998-02-14 19:08:25 +0000
commita99aa1a38ff3444f676c378556b69a735fb2cd8d (patch)
tree3a1b58fe86f8fd6afa59a0cc1c654c6b3667bd73
parentno, i guess that was not in 2.2 (diff)
downloadwireguard-openbsd-a99aa1a38ff3444f676c378556b69a735fb2cd8d.tar.xz
wireguard-openbsd-a99aa1a38ff3444f676c378556b69a735fb2cd8d.zip
*** empty log message ***
-rw-r--r--gnu/usr.bin/gcc/BUGS2
-rw-r--r--gnu/usr.bin/gcc/COPYING7
-rw-r--r--gnu/usr.bin/gcc/ChangeLog.92
-rw-r--r--gnu/usr.bin/gcc/ORDERS6494
-rw-r--r--gnu/usr.bin/gcc/README2
-rw-r--r--gnu/usr.bin/gcc/README.X112
-rw-r--r--gnu/usr.bin/gcc/SERVICE1492
-rw-r--r--gnu/usr.bin/gcc/alloca.c16
-rw-r--r--gnu/usr.bin/gcc/basic-block.h91
-rw-r--r--gnu/usr.bin/gcc/bc-emit.c127
-rw-r--r--gnu/usr.bin/gcc/bc-optab.c33
-rw-r--r--gnu/usr.bin/gcc/bi-arity.c13
-rw-r--r--gnu/usr.bin/gcc/bi-lexer.c6
-rw-r--r--gnu/usr.bin/gcc/bi-opcode.c13
-rw-r--r--gnu/usr.bin/gcc/bi-opname.c13
-rw-r--r--gnu/usr.bin/gcc/build-make5
-rw-r--r--gnu/usr.bin/gcc/bytecode.h3
-rw-r--r--gnu/usr.bin/gcc/c-aux-info.c76
-rw-r--r--gnu/usr.bin/gcc/c-common.c513
-rw-r--r--gnu/usr.bin/gcc/c-decl.c791
-rw-r--r--gnu/usr.bin/gcc/c-gperf.h226
-rw-r--r--gnu/usr.bin/gcc/c-iterate.c51
-rw-r--r--gnu/usr.bin/gcc/c-lang.c8
-rw-r--r--gnu/usr.bin/gcc/c-lex.c569
-rw-r--r--gnu/usr.bin/gcc/c-pragma.c9
-rw-r--r--gnu/usr.bin/gcc/c-tree.h47
-rw-r--r--gnu/usr.bin/gcc/caller-save.c48
-rw-r--r--gnu/usr.bin/gcc/cccp.121
-rw-r--r--gnu/usr.bin/gcc/cccp.c2797
-rw-r--r--gnu/usr.bin/gcc/cexp.y614
-rw-r--r--gnu/usr.bin/gcc/conditions.h2
-rw-r--r--gnu/usr.bin/gcc/config/1750a/1750a.c287
-rw-r--r--gnu/usr.bin/gcc/config/1750a/1750a.h172
-rw-r--r--gnu/usr.bin/gcc/config/1750a/1750a.md584
-rw-r--r--gnu/usr.bin/gcc/config/1750a/ms1750.inc44
-rw-r--r--gnu/usr.bin/gcc/config/a29k/a29k.c67
-rw-r--r--gnu/usr.bin/gcc/config/a29k/a29k.h39
-rw-r--r--gnu/usr.bin/gcc/config/a29k/t-vx29k2
-rw-r--r--gnu/usr.bin/gcc/config/a29k/unix.h7
-rw-r--r--gnu/usr.bin/gcc/config/a29k/vx29k.h11
-rw-r--r--gnu/usr.bin/gcc/config/alpha/config-nt.sed6
-rw-r--r--gnu/usr.bin/gcc/config/alpha/osf12.h10
-rw-r--r--gnu/usr.bin/gcc/config/alpha/win-nt.h12
-rw-r--r--gnu/usr.bin/gcc/config/alpha/xm-winnt.h5
-rw-r--r--gnu/usr.bin/gcc/config/arm/arm.c3320
-rw-r--r--gnu/usr.bin/gcc/config/arm/arm.h1159
-rw-r--r--gnu/usr.bin/gcc/config/arm/lib1funcs.asm1872
-rw-r--r--gnu/usr.bin/gcc/config/arm/riscix.h28
-rw-r--r--gnu/usr.bin/gcc/config/arm/riscix1-1.h19
-rw-r--r--gnu/usr.bin/gcc/config/arm/semi.h18
-rw-r--r--gnu/usr.bin/gcc/config/arm/t-semi37
-rw-r--r--gnu/usr.bin/gcc/config/arm/xm-arm.h6
-rw-r--r--gnu/usr.bin/gcc/config/clipper/clipper.c42
-rw-r--r--gnu/usr.bin/gcc/config/clipper/clipper.h5
-rw-r--r--gnu/usr.bin/gcc/config/clipper/clipper.md43
-rw-r--r--gnu/usr.bin/gcc/config/clipper/clix.h8
-rw-r--r--gnu/usr.bin/gcc/config/clipper/xm-clix.h9
-rw-r--r--gnu/usr.bin/gcc/config/convex/convex.c10
-rw-r--r--gnu/usr.bin/gcc/config/convex/convex.h51
-rw-r--r--gnu/usr.bin/gcc/config/convex/xm-convex.h7
-rw-r--r--gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.c4
-rw-r--r--gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.h41
-rw-r--r--gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.md6
-rw-r--r--gnu/usr.bin/gcc/config/elxsi/elxsi.c4
-rw-r--r--gnu/usr.bin/gcc/config/elxsi/elxsi.h32
-rw-r--r--gnu/usr.bin/gcc/config/fp-bit.c87
-rw-r--r--gnu/usr.bin/gcc/config/fx80/fx80.c4
-rw-r--r--gnu/usr.bin/gcc/config/fx80/fx80.h10
-rw-r--r--gnu/usr.bin/gcc/config/fx80/fx80.md119
-rw-r--r--gnu/usr.bin/gcc/config/gmicro/gmicro.c4
-rw-r--r--gnu/usr.bin/gcc/config/gmicro/gmicro.h26
-rw-r--r--gnu/usr.bin/gcc/config/gmicro/gmicro.md68
-rw-r--r--gnu/usr.bin/gcc/config/gnu.h4
-rw-r--r--gnu/usr.bin/gcc/config/h8300/h8300.c1785
-rw-r--r--gnu/usr.bin/gcc/config/h8300/h8300.h310
-rw-r--r--gnu/usr.bin/gcc/config/h8300/h8300.md2215
-rw-r--r--gnu/usr.bin/gcc/config/h8300/lib1funcs.asm88
-rw-r--r--gnu/usr.bin/gcc/config/h8300/t-h83006
-rw-r--r--gnu/usr.bin/gcc/config/i370/i370.md57
-rw-r--r--gnu/usr.bin/gcc/config/i386/386bsd.h5
-rw-r--r--gnu/usr.bin/gcc/config/i386/aix386ng.h13
-rw-r--r--gnu/usr.bin/gcc/config/i386/att.h21
-rw-r--r--gnu/usr.bin/gcc/config/i386/bsd.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/bsd386.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/gas.h27
-rw-r--r--gnu/usr.bin/gcc/config/i386/gnu.h12
-rw-r--r--gnu/usr.bin/gcc/config/i386/go32.h37
-rw-r--r--gnu/usr.bin/gcc/config/i386/i386.c2440
-rw-r--r--gnu/usr.bin/gcc/config/i386/i386.h1135
-rw-r--r--gnu/usr.bin/gcc/config/i386/i386.md3190
-rw-r--r--gnu/usr.bin/gcc/config/i386/isc.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/linux-aout.h17
-rw-r--r--gnu/usr.bin/gcc/config/i386/linux-oldld.h18
-rw-r--r--gnu/usr.bin/gcc/config/i386/linux.h51
-rw-r--r--gnu/usr.bin/gcc/config/i386/lynx.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/next.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/osfelf.h4
-rw-r--r--gnu/usr.bin/gcc/config/i386/osfrose.h23
-rw-r--r--gnu/usr.bin/gcc/config/i386/sco.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/sco4.h6
-rw-r--r--gnu/usr.bin/gcc/config/i386/sco4dbx.h6
-rw-r--r--gnu/usr.bin/gcc/config/i386/scodbx.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/seq-gas.h4
-rw-r--r--gnu/usr.bin/gcc/config/i386/seq-sysv3.h14
-rw-r--r--gnu/usr.bin/gcc/config/i386/sol2.h36
-rw-r--r--gnu/usr.bin/gcc/config/i386/sun386.h7
-rw-r--r--gnu/usr.bin/gcc/config/i386/svr3.ifile5
-rw-r--r--gnu/usr.bin/gcc/config/i386/svr3dbx.h11
-rw-r--r--gnu/usr.bin/gcc/config/i386/svr3gas.h18
-rw-r--r--gnu/usr.bin/gcc/config/i386/svr3z.ifile5
-rw-r--r--gnu/usr.bin/gcc/config/i386/sysv3.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/sysv4.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/t-crtpic1
-rw-r--r--gnu/usr.bin/gcc/config/i386/t-next3
-rw-r--r--gnu/usr.bin/gcc/config/i386/t-sol216
-rw-r--r--gnu/usr.bin/gcc/config/i386/t-winnt6
-rw-r--r--gnu/usr.bin/gcc/config/i386/unix.h49
-rw-r--r--gnu/usr.bin/gcc/config/i386/winnt.c49
-rw-r--r--gnu/usr.bin/gcc/config/i386/x-osfrose9
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-aix.h8
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-bsd386.h3
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-dos.h6
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-linux.h4
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-os2.h10
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-osf.h10
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-sco.h3
-rw-r--r--gnu/usr.bin/gcc/config/i386/xm-sun.h6
-rw-r--r--gnu/usr.bin/gcc/config/i860/bsd-gas.h2
-rw-r--r--gnu/usr.bin/gcc/config/i860/bsd.h2
-rw-r--r--gnu/usr.bin/gcc/config/i860/fx2800.h32
-rw-r--r--gnu/usr.bin/gcc/config/i860/i860.c5
-rw-r--r--gnu/usr.bin/gcc/config/i860/i860.h14
-rw-r--r--gnu/usr.bin/gcc/config/i860/i860.md17
-rw-r--r--gnu/usr.bin/gcc/config/i860/mach.h2
-rw-r--r--gnu/usr.bin/gcc/config/i860/paragon.h23
-rw-r--r--gnu/usr.bin/gcc/config/i860/sysv3.h8
-rw-r--r--gnu/usr.bin/gcc/config/i860/sysv4.h23
-rw-r--r--gnu/usr.bin/gcc/config/i960/i960-coff.h10
-rw-r--r--gnu/usr.bin/gcc/config/i960/i960.c67
-rw-r--r--gnu/usr.bin/gcc/config/i960/i960.h91
-rw-r--r--gnu/usr.bin/gcc/config/i960/i960.md184
-rw-r--r--gnu/usr.bin/gcc/config/i960/t-960bare12
-rw-r--r--gnu/usr.bin/gcc/config/i960/t-vxworks96014
-rw-r--r--gnu/usr.bin/gcc/config/i960/vx960-coff.h22
-rw-r--r--gnu/usr.bin/gcc/config/i960/vx960.h9
-rw-r--r--gnu/usr.bin/gcc/config/linux-aout.h13
-rw-r--r--gnu/usr.bin/gcc/config/linux.h63
-rw-r--r--gnu/usr.bin/gcc/config/lynx.h5
-rw-r--r--gnu/usr.bin/gcc/config/m68k/3b1.h10
-rw-r--r--gnu/usr.bin/gcc/config/m68k/altos3068.h10
-rw-r--r--gnu/usr.bin/gcc/config/m68k/apollo68.h21
-rw-r--r--gnu/usr.bin/gcc/config/m68k/ccur-GAS.h7
-rw-r--r--gnu/usr.bin/gcc/config/m68k/coff.h39
-rw-r--r--gnu/usr.bin/gcc/config/m68k/crds.h40
-rw-r--r--gnu/usr.bin/gcc/config/m68k/dpx2.h6
-rw-r--r--gnu/usr.bin/gcc/config/m68k/hp320.h69
-rw-r--r--gnu/usr.bin/gcc/config/m68k/hp3bsd.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/hp3bsd44.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/isi-nfp.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/isi.h6
-rw-r--r--gnu/usr.bin/gcc/config/m68k/lb1sf68.asm1306
-rw-r--r--gnu/usr.bin/gcc/config/m68k/linux-aout.h12
-rw-r--r--gnu/usr.bin/gcc/config/m68k/linux.h154
-rw-r--r--gnu/usr.bin/gcc/config/m68k/lynx-ng.h4
-rw-r--r--gnu/usr.bin/gcc/config/m68k/lynx.h4
-rw-r--r--gnu/usr.bin/gcc/config/m68k/m68k-aout.h17
-rw-r--r--gnu/usr.bin/gcc/config/m68k/m68k-none.h209
-rw-r--r--gnu/usr.bin/gcc/config/m68k/m68k.c887
-rw-r--r--gnu/usr.bin/gcc/config/m68k/m68kemb.h14
-rw-r--r--gnu/usr.bin/gcc/config/m68k/m68kv4.h54
-rw-r--r--gnu/usr.bin/gcc/config/m68k/mot3300.h302
-rw-r--r--gnu/usr.bin/gcc/config/m68k/news.h68
-rw-r--r--gnu/usr.bin/gcc/config/m68k/newsgas.h12
-rw-r--r--gnu/usr.bin/gcc/config/m68k/next.h32
-rw-r--r--gnu/usr.bin/gcc/config/m68k/pbb.h14
-rw-r--r--gnu/usr.bin/gcc/config/m68k/plexus.h41
-rw-r--r--gnu/usr.bin/gcc/config/m68k/sgs.h6
-rw-r--r--gnu/usr.bin/gcc/config/m68k/sun2o4.h10
-rw-r--r--gnu/usr.bin/gcc/config/m68k/sun3.h25
-rw-r--r--gnu/usr.bin/gcc/config/m68k/sun3mach.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/sun3n.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/sun3n3.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/sun3o3.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/t-linux16
-rw-r--r--gnu/usr.bin/gcc/config/m68k/t-m68kbare3
-rw-r--r--gnu/usr.bin/gcc/config/m68k/t-next2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/t-vxworks682
-rw-r--r--gnu/usr.bin/gcc/config/m68k/tower-as.h49
-rw-r--r--gnu/usr.bin/gcc/config/m68k/tower.h40
-rw-r--r--gnu/usr.bin/gcc/config/m68k/vxm68k.h63
-rw-r--r--gnu/usr.bin/gcc/config/m68k/x-hp3bsd443
-rw-r--r--gnu/usr.bin/gcc/config/m68k/x-mot33004
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-3b1.h6
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-altos3068.h4
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-amix.h4
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-atari.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-crds.h7
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-hp320.h6
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-linux.h2
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-m68kv.h6
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-mot3300.h19
-rw-r--r--gnu/usr.bin/gcc/config/m68k/xm-plexus.h7
-rw-r--r--gnu/usr.bin/gcc/config/m88k/dgux.h72
-rw-r--r--gnu/usr.bin/gcc/config/m88k/dguxbcs.h31
-rw-r--r--gnu/usr.bin/gcc/config/m88k/dolph.h13
-rw-r--r--gnu/usr.bin/gcc/config/m88k/luna.h4
-rw-r--r--gnu/usr.bin/gcc/config/m88k/m88k-coff.h8
-rw-r--r--gnu/usr.bin/gcc/config/m88k/m88k.c112
-rw-r--r--gnu/usr.bin/gcc/config/m88k/m88k.h34
-rw-r--r--gnu/usr.bin/gcc/config/m88k/m88k.md38
-rw-r--r--gnu/usr.bin/gcc/config/m88k/sysv3.h13
-rw-r--r--gnu/usr.bin/gcc/config/m88k/t-dgux3
-rw-r--r--gnu/usr.bin/gcc/config/m88k/x-dgux10
-rw-r--r--gnu/usr.bin/gcc/config/m88k/x-dguxbcs8
-rw-r--r--gnu/usr.bin/gcc/config/m88k/xm-m88k.h15
-rw-r--r--gnu/usr.bin/gcc/config/m88k/xm-sysv3.h6
-rw-r--r--gnu/usr.bin/gcc/config/mips/abi64.h235
-rw-r--r--gnu/usr.bin/gcc/config/mips/dec-bsd.h32
-rw-r--r--gnu/usr.bin/gcc/config/mips/dec-osf1.h17
-rw-r--r--gnu/usr.bin/gcc/config/mips/elf.h9
-rw-r--r--gnu/usr.bin/gcc/config/mips/elf64.h38
-rw-r--r--gnu/usr.bin/gcc/config/mips/gnu.h28
-rw-r--r--gnu/usr.bin/gcc/config/mips/iris3.h26
-rw-r--r--gnu/usr.bin/gcc/config/mips/iris4loser.h40
-rw-r--r--gnu/usr.bin/gcc/config/mips/iris5.h45
-rw-r--r--gnu/usr.bin/gcc/config/mips/iris6.h477
-rw-r--r--gnu/usr.bin/gcc/config/mips/mips.h683
-rw-r--r--gnu/usr.bin/gcc/config/mips/mips.md1852
-rw-r--r--gnu/usr.bin/gcc/config/mips/netbsd.h56
-rw-r--r--gnu/usr.bin/gcc/config/mips/news4.h6
-rw-r--r--gnu/usr.bin/gcc/config/mips/osfrose.h58
-rw-r--r--gnu/usr.bin/gcc/config/mips/t-ecoff8
-rw-r--r--gnu/usr.bin/gcc/config/mips/t-iris611
-rw-r--r--gnu/usr.bin/gcc/config/mips/ultrix.h12
-rw-r--r--gnu/usr.bin/gcc/config/mips/x-iris8
-rw-r--r--gnu/usr.bin/gcc/config/mips/x-iris38
-rw-r--r--gnu/usr.bin/gcc/config/mips/x-iris611
-rw-r--r--gnu/usr.bin/gcc/config/mips/x-netbsd3
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-iris3.h5
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-iris4.h5
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-iris5.h10
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-iris6.h12
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-mips.h8
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-news.h2
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-sysv.h10
-rw-r--r--gnu/usr.bin/gcc/config/mips/xm-sysv4.h8
-rw-r--r--gnu/usr.bin/gcc/config/msdos/configur.bat6
-rw-r--r--gnu/usr.bin/gcc/config/nextstep.c48
-rw-r--r--gnu/usr.bin/gcc/config/nextstep.h75
-rw-r--r--gnu/usr.bin/gcc/config/ns32k/ns32k.c37
-rw-r--r--gnu/usr.bin/gcc/config/ns32k/ns32k.h12
-rw-r--r--gnu/usr.bin/gcc/config/ns32k/ns32k.md165
-rw-r--r--gnu/usr.bin/gcc/config/ns32k/tek6000.h6
-rw-r--r--gnu/usr.bin/gcc/config/ns32k/xm-genix.h4
-rw-r--r--gnu/usr.bin/gcc/config/pa/lib2funcs.asm13
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa-hiux.h5
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa-hpux.h21
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa-hpux7.h14
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa-hpux9.h16
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa-oldas.h10
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa-osf.h11
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa.c3021
-rw-r--r--gnu/usr.bin/gcc/config/pa/pa.md2130
-rw-r--r--gnu/usr.bin/gcc/config/pa/t-pa16
-rw-r--r--gnu/usr.bin/gcc/config/pa/x-pa2
-rw-r--r--gnu/usr.bin/gcc/config/pa/x-pa-hpux3
-rw-r--r--gnu/usr.bin/gcc/config/pa/xm-pa.h5
-rw-r--r--gnu/usr.bin/gcc/config/pa/xm-pahpux.h9
-rw-r--r--gnu/usr.bin/gcc/config/pdp11/2bsd.h4
-rw-r--r--gnu/usr.bin/gcc/config/pdp11/pdp11.c11
-rw-r--r--gnu/usr.bin/gcc/config/pdp11/pdp11.h18
-rw-r--r--gnu/usr.bin/gcc/config/pdp11/pdp11.md24
-rw-r--r--gnu/usr.bin/gcc/config/pyr/pyr.c4
-rw-r--r--gnu/usr.bin/gcc/config/pyr/pyr.h11
-rw-r--r--gnu/usr.bin/gcc/config/pyr/pyr.md6
-rw-r--r--gnu/usr.bin/gcc/config/romp/romp.c6
-rw-r--r--gnu/usr.bin/gcc/config/romp/romp.h15
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/aix31.h11
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/aix3newas.h42
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/aix41.h89
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/eabi-ctors.c44
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/eabi.asm852
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/eabi.h97
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/eabiaix.h50
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/eabile.h52
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/eabilesim.h52
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/eabisim.h54
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/lynx.h5
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/mach.h1
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/netware.h13
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/powerpc.h50
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/rs6000.h1281
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/sysv4.h1365
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/sysv4le.h46
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/t-newas30
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/t-ppc29
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/t-ppcgas46
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/x-rs60001
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/xm-rs6000.h4
-rw-r--r--gnu/usr.bin/gcc/config/rs6000/xm-sysv4.h17
-rw-r--r--gnu/usr.bin/gcc/config/sh/lib1funcs.asm452
-rw-r--r--gnu/usr.bin/gcc/config/sh/sh.c3326
-rw-r--r--gnu/usr.bin/gcc/config/sh/sh.h854
-rw-r--r--gnu/usr.bin/gcc/config/sh/sh.md1954
-rw-r--r--gnu/usr.bin/gcc/config/sh/t-sh4
-rw-r--r--gnu/usr.bin/gcc/config/sh/xm-sh.h6
-rw-r--r--gnu/usr.bin/gcc/config/sparc/gmon-sol2.c37
-rw-r--r--gnu/usr.bin/gcc/config/sparc/lb1spc.asm20
-rw-r--r--gnu/usr.bin/gcc/config/sparc/lite.h6
-rw-r--r--gnu/usr.bin/gcc/config/sparc/litecoff.h46
-rw-r--r--gnu/usr.bin/gcc/config/sparc/lynx-ng.h2
-rw-r--r--gnu/usr.bin/gcc/config/sparc/lynx.h4
-rw-r--r--gnu/usr.bin/gcc/config/sparc/pbd.h16
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sol2.h91
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sp64-aout.h35
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sp64-elf.h90
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sparc.c2341
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sparc.md2510
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sun4o3.h2
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sunos4.h7
-rw-r--r--gnu/usr.bin/gcc/config/sparc/sysv4.h91
-rw-r--r--gnu/usr.bin/gcc/config/sparc/t-sol224
-rw-r--r--gnu/usr.bin/gcc/config/sparc/t-sp641
-rw-r--r--gnu/usr.bin/gcc/config/sparc/t-sparcbare8
-rw-r--r--gnu/usr.bin/gcc/config/sparc/t-sparclite6
-rw-r--r--gnu/usr.bin/gcc/config/sparc/t-sunos401
-rw-r--r--gnu/usr.bin/gcc/config/sparc/t-sunos4111
-rw-r--r--gnu/usr.bin/gcc/config/sparc/t-vxsparc2
-rw-r--r--gnu/usr.bin/gcc/config/sparc/vxsparc.h11
-rw-r--r--gnu/usr.bin/gcc/config/sparc/xm-pbd.h3
-rw-r--r--gnu/usr.bin/gcc/config/sparc/xm-sol2.h6
-rw-r--r--gnu/usr.bin/gcc/config/sparc/xm-sparc.h2
-rw-r--r--gnu/usr.bin/gcc/config/spur/spur.c3
-rw-r--r--gnu/usr.bin/gcc/config/spur/spur.h10
-rw-r--r--gnu/usr.bin/gcc/config/svr3.h36
-rw-r--r--gnu/usr.bin/gcc/config/t-libc-ok1
-rw-r--r--gnu/usr.bin/gcc/config/tahoe/tahoe.c7
-rw-r--r--gnu/usr.bin/gcc/config/tahoe/tahoe.h9
-rw-r--r--gnu/usr.bin/gcc/config/tahoe/tahoe.md22
-rw-r--r--gnu/usr.bin/gcc/config/vax/netbsd.h5
-rw-r--r--gnu/usr.bin/gcc/config/vax/ultrix.h5
-rw-r--r--gnu/usr.bin/gcc/config/vax/vax.c7
-rw-r--r--gnu/usr.bin/gcc/config/vax/vaxv.h4
-rw-r--r--gnu/usr.bin/gcc/config/vax/vms.h54
-rw-r--r--gnu/usr.bin/gcc/config/vax/xm-vaxv.h6
-rw-r--r--gnu/usr.bin/gcc/config/vax/xm-vms.h62
-rw-r--r--gnu/usr.bin/gcc/config/we32k/we32k.c4
-rw-r--r--gnu/usr.bin/gcc/config/we32k/we32k.h10
-rw-r--r--gnu/usr.bin/gcc/config/we32k/xm-we32k.h9
-rw-r--r--gnu/usr.bin/gcc/config/winnt/config-nt.bat15
-rw-r--r--gnu/usr.bin/gcc/config/winnt/win-nt.h6
-rw-r--r--gnu/usr.bin/gcc/config/winnt/xm-winnt.h8
-rw-r--r--gnu/usr.bin/gcc/config/xm-gnu.h5
-rw-r--r--gnu/usr.bin/gcc/config/xm-linux.h17
-rw-r--r--gnu/usr.bin/gcc/config/xm-svr3.h10
-rw-r--r--gnu/usr.bin/gcc/config/xm-svr4.h12
-rw-r--r--gnu/usr.bin/gcc/convert.c11
-rw-r--r--gnu/usr.bin/gcc/cp/ChangeLog12685
-rw-r--r--gnu/usr.bin/gcc/cp/Make-lang.in137
-rw-r--r--gnu/usr.bin/gcc/cp/call.c4153
-rw-r--r--gnu/usr.bin/gcc/cp/class.c2026
-rw-r--r--gnu/usr.bin/gcc/cp/class.h4
-rw-r--r--gnu/usr.bin/gcc/cp/config-lang.in6
-rw-r--r--gnu/usr.bin/gcc/cp/cp-tree.h849
-rw-r--r--gnu/usr.bin/gcc/cp/cvt.c854
-rw-r--r--gnu/usr.bin/gcc/cp/decl.c5849
-rw-r--r--gnu/usr.bin/gcc/cp/decl.h2
-rw-r--r--gnu/usr.bin/gcc/cp/errfn.c15
-rw-r--r--gnu/usr.bin/gcc/cp/error.c490
-rw-r--r--gnu/usr.bin/gcc/cp/except.c1734
-rw-r--r--gnu/usr.bin/gcc/cp/expr.c151
-rw-r--r--gnu/usr.bin/gcc/cp/gxx.gperf20
-rw-r--r--gnu/usr.bin/gcc/cp/gxxint.texi462
-rw-r--r--gnu/usr.bin/gcc/cp/hash.h226
-rw-r--r--gnu/usr.bin/gcc/cp/init.c1994
-rw-r--r--gnu/usr.bin/gcc/cp/input.c69
-rw-r--r--gnu/usr.bin/gcc/cp/lang-options.h20
-rw-r--r--gnu/usr.bin/gcc/cp/lang-specs.h11
-rw-r--r--gnu/usr.bin/gcc/cp/lex.h18
-rw-r--r--gnu/usr.bin/gcc/cp/method.c1385
-rw-r--r--gnu/usr.bin/gcc/cp/parse.y2907
-rw-r--r--gnu/usr.bin/gcc/cp/pt.c4728
-rw-r--r--gnu/usr.bin/gcc/cp/ptree.c7
-rw-r--r--gnu/usr.bin/gcc/cp/repo.c133
-rw-r--r--gnu/usr.bin/gcc/cp/search.c1021
-rw-r--r--gnu/usr.bin/gcc/cp/sig.c126
-rw-r--r--gnu/usr.bin/gcc/cp/spew.c184
-rw-r--r--gnu/usr.bin/gcc/cp/tree.c1047
-rw-r--r--gnu/usr.bin/gcc/cp/typeck.c3192
-rw-r--r--gnu/usr.bin/gcc/cp/typeck2.c291
-rw-r--r--gnu/usr.bin/gcc/cp/xref.c69
-rw-r--r--gnu/usr.bin/gcc/cplus-dem.c1396
-rw-r--r--gnu/usr.bin/gcc/cpp.texi134
-rw-r--r--gnu/usr.bin/gcc/cppalloc.c23
-rw-r--r--gnu/usr.bin/gcc/cpperror.c28
-rw-r--r--gnu/usr.bin/gcc/cppexp.c151
-rw-r--r--gnu/usr.bin/gcc/cpphash.c72
-rw-r--r--gnu/usr.bin/gcc/cpphash.h2
-rw-r--r--gnu/usr.bin/gcc/cpplib.c1137
-rw-r--r--gnu/usr.bin/gcc/cpplib.h126
-rw-r--r--gnu/usr.bin/gcc/cppmain.c30
-rw-r--r--gnu/usr.bin/gcc/cross-make3
-rw-r--r--gnu/usr.bin/gcc/crtstuff.c142
-rw-r--r--gnu/usr.bin/gcc/dbxout.c465
-rw-r--r--gnu/usr.bin/gcc/defaults.h32
-rw-r--r--gnu/usr.bin/gcc/demangle.h30
-rw-r--r--gnu/usr.bin/gcc/doschk.c8
-rw-r--r--gnu/usr.bin/gcc/dwarf.h6
-rw-r--r--gnu/usr.bin/gcc/dwarfout.c1154
-rw-r--r--gnu/usr.bin/gcc/emit-rtl.c400
-rw-r--r--gnu/usr.bin/gcc/enquire.c115
-rw-r--r--gnu/usr.bin/gcc/explow.c239
-rw-r--r--gnu/usr.bin/gcc/expr.h147
-rw-r--r--gnu/usr.bin/gcc/extend.texi753
-rw-r--r--gnu/usr.bin/gcc/final.c549
-rw-r--r--gnu/usr.bin/gcc/fixinc.ptx70
-rw-r--r--gnu/usr.bin/gcc/fixinc.sco79
-rw-r--r--gnu/usr.bin/gcc/fixinc.svr4133
-rw-r--r--gnu/usr.bin/gcc/fixproto17
-rw-r--r--gnu/usr.bin/gcc/floatlib.c259
-rw-r--r--gnu/usr.bin/gcc/flow.c935
-rw-r--r--gnu/usr.bin/gcc/function.c1125
-rw-r--r--gnu/usr.bin/gcc/function.h45
-rw-r--r--gnu/usr.bin/gcc/gbl-ctors.h12
-rw-r--r--gnu/usr.bin/gcc/gcc.164
-rw-r--r--gnu/usr.bin/gcc/gcc.cps3776
-rw-r--r--gnu/usr.bin/gcc/gen-protos.c215
-rw-r--r--gnu/usr.bin/gcc/genattr.c10
-rw-r--r--gnu/usr.bin/gcc/genattrtab.c170
-rw-r--r--gnu/usr.bin/gcc/genconfig.c6
-rw-r--r--gnu/usr.bin/gcc/genemit.c7
-rw-r--r--gnu/usr.bin/gcc/genextract.c16
-rw-r--r--gnu/usr.bin/gcc/genflags.c5
-rw-r--r--gnu/usr.bin/gcc/genmultilib114
-rw-r--r--gnu/usr.bin/gcc/genopinit.c18
-rw-r--r--gnu/usr.bin/gcc/genoutput.c20
-rw-r--r--gnu/usr.bin/gcc/genpeep.c7
-rw-r--r--gnu/usr.bin/gcc/genrecog.c20
-rw-r--r--gnu/usr.bin/gcc/getopt.c323
-rw-r--r--gnu/usr.bin/gcc/getopt.h12
-rw-r--r--gnu/usr.bin/gcc/getopt1.c25
-rw-r--r--gnu/usr.bin/gcc/getpwd.c16
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-alpha.h31
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-clipper.h3
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-h8300.h9
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-i860.h3
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-i960.h3
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-m88k.h3
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-mips.h174
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-pa.h5
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-ppc.h115
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-sparc.h120
-rw-r--r--gnu/usr.bin/gcc/ginclude/va-spur.h3
-rw-r--r--gnu/usr.bin/gcc/ginclude/varargs.h64
-rw-r--r--gnu/usr.bin/gcc/global.c126
-rw-r--r--gnu/usr.bin/gcc/gmon.c21
-rw-r--r--gnu/usr.bin/gcc/gsyms.h12
-rw-r--r--gnu/usr.bin/gcc/halfpic.c12
-rw-r--r--gnu/usr.bin/gcc/halfpic.h24
-rw-r--r--gnu/usr.bin/gcc/hard-reg-set.h199
-rw-r--r--gnu/usr.bin/gcc/input.h4
-rw-r--r--gnu/usr.bin/gcc/integrate.c485
-rw-r--r--gnu/usr.bin/gcc/integrate.h6
-rw-r--r--gnu/usr.bin/gcc/jump.c414
-rw-r--r--gnu/usr.bin/gcc/libgcc1-test.c3
-rw-r--r--gnu/usr.bin/gcc/libgcc2.c1919
-rw-r--r--gnu/usr.bin/gcc/listing6
-rw-r--r--gnu/usr.bin/gcc/longlong.h683
-rw-r--r--gnu/usr.bin/gcc/machmode.def4
-rw-r--r--gnu/usr.bin/gcc/machmode.h98
-rw-r--r--gnu/usr.bin/gcc/make-cc1.com161
-rw-r--r--gnu/usr.bin/gcc/make-cccp.com128
-rw-r--r--gnu/usr.bin/gcc/make-gcc.com77
-rw-r--r--gnu/usr.bin/gcc/make-l2.com91
-rw-r--r--gnu/usr.bin/gcc/md.texi228
-rw-r--r--gnu/usr.bin/gcc/mips-tdump.c130
-rw-r--r--gnu/usr.bin/gcc/mips-tfile.c383
-rw-r--r--gnu/usr.bin/gcc/objc/NXConstStr.h6
-rw-r--r--gnu/usr.bin/gcc/objc/NXConstStr.m6
-rw-r--r--gnu/usr.bin/gcc/objc/Object.m8
-rw-r--r--gnu/usr.bin/gcc/objc/archive.c197
-rw-r--r--gnu/usr.bin/gcc/objc/class.c45
-rw-r--r--gnu/usr.bin/gcc/objc/encoding.c24
-rw-r--r--gnu/usr.bin/gcc/objc/encoding.h4
-rw-r--r--gnu/usr.bin/gcc/objc/hash.h6
-rw-r--r--gnu/usr.bin/gcc/objc/init.c533
-rw-r--r--gnu/usr.bin/gcc/objc/makefile.dos8
-rw-r--r--gnu/usr.bin/gcc/objc/misc.c130
-rw-r--r--gnu/usr.bin/gcc/objc/objc-api.h143
-rw-r--r--gnu/usr.bin/gcc/objc/objc.h12
-rw-r--r--gnu/usr.bin/gcc/objc/objects.c14
-rw-r--r--gnu/usr.bin/gcc/objc/runtime.h32
-rw-r--r--gnu/usr.bin/gcc/objc/sarray.c339
-rw-r--r--gnu/usr.bin/gcc/objc/sarray.h23
-rw-r--r--gnu/usr.bin/gcc/objc/selector.c191
-rw-r--r--gnu/usr.bin/gcc/objc/sendmsg.c298
-rw-r--r--gnu/usr.bin/gcc/obstack.c199
-rw-r--r--gnu/usr.bin/gcc/obstack.h256
-rw-r--r--gnu/usr.bin/gcc/optabs.c198
-rw-r--r--gnu/usr.bin/gcc/output.h43
-rw-r--r--gnu/usr.bin/gcc/print-rtl.c56
-rw-r--r--gnu/usr.bin/gcc/print-tree.c83
-rw-r--r--gnu/usr.bin/gcc/protoize.c265
-rw-r--r--gnu/usr.bin/gcc/recog.c72
-rw-r--r--gnu/usr.bin/gcc/recog.h85
-rw-r--r--gnu/usr.bin/gcc/reg-stack.c434
-rw-r--r--gnu/usr.bin/gcc/regclass.c230
-rw-r--r--gnu/usr.bin/gcc/regs.h70
-rw-r--r--gnu/usr.bin/gcc/reload.h20
-rw-r--r--gnu/usr.bin/gcc/reload1.c2112
-rw-r--r--gnu/usr.bin/gcc/reorg.c474
-rw-r--r--gnu/usr.bin/gcc/rtl.c38
-rw-r--r--gnu/usr.bin/gcc/rtl.def18
-rw-r--r--gnu/usr.bin/gcc/rtl.texi63
-rw-r--r--gnu/usr.bin/gcc/rtlanal.c172
-rw-r--r--gnu/usr.bin/gcc/scan-decls.c24
-rw-r--r--gnu/usr.bin/gcc/scan.c2
-rw-r--r--gnu/usr.bin/gcc/scan.h14
-rw-r--r--gnu/usr.bin/gcc/sdbout.c161
-rw-r--r--gnu/usr.bin/gcc/stmt.c1236
-rw-r--r--gnu/usr.bin/gcc/stupid.c87
-rw-r--r--gnu/usr.bin/gcc/sys-protos.h21
-rw-r--r--gnu/usr.bin/gcc/sys-types.h1
-rw-r--r--gnu/usr.bin/gcc/texinfo.tex1947
-rw-r--r--gnu/usr.bin/gcc/tm.texi1120
-rw-r--r--gnu/usr.bin/gcc/tree.def116
-rw-r--r--gnu/usr.bin/gcc/tree.h340
-rw-r--r--gnu/usr.bin/gcc/varasm.c1225
-rw-r--r--gnu/usr.bin/gcc/vmsconfig.com108
-rw-r--r--gnu/usr.bin/gcc/xcoffout.c19
-rw-r--r--gnu/usr.bin/gcc/xcoffout.h24
531 files changed, 92509 insertions, 52911 deletions
diff --git a/gnu/usr.bin/gcc/BUGS b/gnu/usr.bin/gcc/BUGS
index dc023cffc51..33c9386cae1 100644
--- a/gnu/usr.bin/gcc/BUGS
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/COPYING b/gnu/usr.bin/gcc/COPYING
index 916d1f0f284..60549be514a 100644
--- a/gnu/usr.bin/gcc/COPYING
+++ b/gnu/usr.bin/gcc/COPYING
@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -279,7 +279,7 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
- Appendix: How to Apply These Terms to Your New Programs
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -305,7 +305,8 @@ the "copyright" line and a pointer to where the full notice is found.
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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
Also add information on how to contact you by electronic and paper mail.
diff --git a/gnu/usr.bin/gcc/ChangeLog.9 b/gnu/usr.bin/gcc/ChangeLog.9
index 9cd8cdfe1a1..6b18fc9580f 100644
--- a/gnu/usr.bin/gcc/ChangeLog.9
+++ b/gnu/usr.bin/gcc/ChangeLog.9
@@ -1273,7 +1273,7 @@ Fri Jan 20 20:11:17 1995 Jim Wilson <wilson@cygnus.com>
* integrate.c (save_for_inline_copying): Add comment that
nonlocal_label list should be updated if it ever can be nonzero.
- * sdbout.c (syms.h): Don't include under Linux.
+ * sdbout.c (syms.h): Don't include under Linux-based GNU systems.
* loop.c (scan_loop): For the replace_rtx call, copy the rtx that is
being substituted in before the call.
diff --git a/gnu/usr.bin/gcc/ORDERS b/gnu/usr.bin/gcc/ORDERS
index 665c26df4ca..fb5790701db 100644
--- a/gnu/usr.bin/gcc/ORDERS
+++ b/gnu/usr.bin/gcc/ORDERS
@@ -1,164 +1,186 @@
The actual order form follows the descriptions of media contents.
-Most of this file is excerpted from the draft of the June 1995 GNU's Bulletin.
-The Order Form itself is accurate, but the information in the other articles
-is not completely updated. You can ask gnu@prep.ai.mit.edu for the complete
-June, 1995 Order From to get up-to-date information.
+Most of this file is excerpted from the July 1997 GNU's Bulletin.
Please send suggestions for improvements to gnu@prep.ai.mit.edu or the postal
address at the end of the order form. Thank You.
----------------------------------------------------------------------
+-----------------------------------------------------------------------------
+
+FSF Order Form with Descriptions July, 1997
+
-FSF Order Form with Descriptions preliminary, June 1995
+Free Software Foundation, Inc. Telephone: +1-617-542-5942
+59 Temple Place - Suite 330 Fax: (including Japan) +1-617-542-2652
+Boston, MA 02111-1307 Electronic Mail: `gnu@prep.ai.mit.edu'
+USA World Wide Web: http://www.gnu.ai.mit.edu
+
+-----------------------------------------------------------------------------
-Free Software Foundation, Inc. Telephone: +1-617-542-5942
-59 Temple Place - Suite 330 Fax: (including Japan) +1-617-542-2652
-Boston, MA 02111-1307 Free Dial Fax (in Japan):
-USA 0031-13-2473 (KDD)
-Electronic mail: `gnu@prep.ai.mit.edu' 0066-3382-0158 (IDC)
-
There are some sections (e.g. ``Forthcoming GNUs'' and ``How to Get GNU
Software'') which are not in this Order Form file. If you wish to see them,
-ask gnu@prep.ai.mit.edu for the complete June, 1995 GNU's Bulletin.
+ask gnu@prep.ai.mit.edu for the complete July, 1997 GNU's Bulletin.
+
Table of Contents
-----------------
+ New European Distributor
Donations Translate Into Free Software
Cygnus Matches Donations!
Free Software Redistributors Donate
Help from Free Software Companies
- (not included) Major Changes in GNU Software and Documentation (not
- included as it was not done when this file was assembled).
+ Major Changes in GNU Software and Documentation
+ The Deluxe Distribution
GNU Documentation
- GNU Software (not completely up to date)
- Program/Package Cross Reference (not completely up to date)
- Tapes
- Languages Tape (version numbers not completely up to date)
- Lisps and Emacs Tape (version numbers not completely up to date)
- Utilities Tape (version numbers not completely up to date)
- Scheme Tape
- X11 Tapes
- Berkeley 4.4BSD-Lite Tape
- VMS Emacs and VMS Compiler Tapes
+ GNU Software
+
+ Program/Package Cross Reference
CD-ROMs
Pricing of the GNU CD-ROMs
- MS-DOS CD-ROM
- Debian GNU/Linux CD-ROM
- Compiler Tools Binaries CD-ROM
+ What Do the Different Prices Mean?
+ Why Is There an Individual Price?
+ Is There a Maximum Price?
+ January 1997 Compiler Tools Binaries CD-ROM
Source Code CD-ROMs
- June 1995 Source Code CD-ROM (version numbers not completely up
- to date)
- May 1994 Source Code CD-ROM
- November 1993 Source Code CD-ROM
- MS-DOS Diskettes
- DJGPP Diskettes (version numbers not completely up to date)
- Emacs Diskettes (version numbers not completely up to date)
- Selected Utilities Diskettes (not completely up to date)
- Windows Diskette
- Tape & CD-ROM Subscription Service
- The Deluxe Distribution
+ July 1997 Source Code CD-ROMs
+ January 1997 Source Code CD-ROMs
+ CD-ROM Subscription Service
FSF T-shirt
Free Software Foundation Order Form
+-----------------------------------------------------------------------------
-Donations Translate Into Free Software
-**************************************
-
-If you appreciate Emacs, GNU CC, Ghostscript, and other free software, you
-may wish to help us make sure there is more in the future--remember,
-*donations translate into more free software!*
-Your donation to us is tax-deductible in the United States. We gladly accept
-*any* currency, although the U.S. dollar is the most convenient.
-m{No Value For "ergegrafkludge"} If your employer has a matching gifts
-program for charitable donations, please arrange to: add the FSF to the list
-of organizations for your employer's matching gifts program; and have your
-donation matched (note *Note Cygnus Matches Donations!::), if you do not
-know, please ask your personnel department. Circle amount you are donating,
-cut out this form, and send it with your donation to:
- Free Software Foundation
- 59 Temple Place -- Suite 330
- Boston, MA 02111-1307
- USA
- $500 $250 $100 $50 other $________
+New European Distributor
+************************
- Other currency:________
+The Free Software Foundation now has a European distribution agent: GNU
+Distribution Europe, Belgium.
+Users in European Community countries can order GNU manuals, CD-ROMs and
+T-shirts through this distribution agent, and get a lower overall price (due
+to reduced shipping costs) and quicker delivery.
-You can charge a donation to any of Carte Blanche, Diner's Club, JCB,
-Mastercard, Visa, or American Express. Charges may also be faxed to
-+1-617-492-9057. Individuals in Japan who are unable to place international
-calls may use the "free dial" numbers: 0031-13-2473 (KDD) and
-0066-3382-0158 (IDC).
+Write to GNU Distribution Europe--Belgium, Sportstaat 28, 9000 Gent, Belgium;
+Fax: +32-9-2224976; Phone: +32-9-2227542; Email:
+`europe-order@gnu.ai.mit.edu'.
- Card type: __________________ Expiration Date: _____________
- Account Number: _____________________________________________
+Donations Translate Into Free Software
+**************************************
- Cardholder's Signature: _____________________________________
+If you appreciate Emacs, GNU CC, Ghostscript, and other free software, you
+may wish to help us make sure there is more in the future--remember,
+*donations translate into more free software!*
- Name: _______________________________________________________
+Your donation to us is tax-deductible in the United States. We gladly accept
+*any* currency, although the U.S. dollar is the most convenient.
- Street Address: _____________________________________________
+If your employer has a matching gifts program for charitable donations,
+please arrange to: add the FSF to the list of organizations for your
+employer's matching gifts program; and have your donation matched (note *Note
+Cygnus Matches Donations!::). If you do not know, please ask your personnel
+department.
- City/State/Province: ________________________________________
+Circle amount you are donating, cut out this form, and send it with your
+donation to:
- Zip Code/Postal Code/Country: _______________________________
+ Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330
+ Boston, MA 02111-1307
+ USA
+ $500 $250 $100 $50 Other $_____ Other currency:_____
+You can charge a donation to any of Carte Blanche, Diner's Club, JCB,
+MasterCard, Visa, or American Express. Charges may also be faxed to
++1-617-542-2652.
+
+ Card type: __________________ Expiration Date: _____________
+
+ Account Number: _____________________________________________
+
+ Cardholder's Signature: _____________________________________
+
+ Name: _______________________________________________________
+
+ Street Address: _____________________________________________
+
+ City/State/Province: ________________________________________
+
+ Zip Code/Postal Code/Country: _______________________________
+
+ Telephone Number: ___________________________________________
+
+ Email Address: ______________________________________________
+
+
Cygnus Matches Donations!
*************************
-To encourage cash donations to the Free Software Foundation, Cygnus Support
-will continue to contribute corporate funds to FSF to accompany gifts by its
-employees, and by its customers and their employees.
+To encourage cash donations to the Free Software Foundation, Cygnus Solutions
+will continue to contribute corporate funds to the FSF to accompany gifts by
+its employees, and by its customers and their employees.
Donations payable to the Free Software Foundation should be sent by eligible
-persons to Cygnus Support, which will add its gifts and forward the total to
-the FSF each quarter. The FSF will provide the contributor with a receipt to
-recognize the contribution (which is tax-deductible on U.S. tax returns).
-For more information, please contact Cygnus:
- Cygnus Support
- 1937 Landings Drive
- Mountain View, CA 94043
- USA
+persons to Cygnus Solutions, which will add its gifts and forward the total
+to the FSF each quarter. The FSF will provide the contributor with a receipt
+to recognize the contribution (which is tax-deductible on U.S. tax returns).
+To see if your employer is a Cygnus customer, or for more information,
+please contact Cygnus:
+
+ Cygnus Solutions
+ 1325 Chesapeake Terrace
+ Sunnyvale, CA 94089
+ USA
+
+ Telephone: +1 408 542 9600
+ +1 800 Cygnus1 (-294-6871)
+ Fax: +1 408 542 9700
+ Electronic-Mail: `info@cygnus.com'
+ FTP: `ftp.cygnus.com'
+
+
+
+Free Software Redistributors Donate
+***********************************
- Telephone: 415-903-1400
- +1-800-Cygnus1 (-294-6871)
- Fax: 415-903-0122
- Electronic-Mail: `info@cygnus.com'
- FTP: `ftp.cygnus.com'
- WWW: `http://www.cygnus.com/'
+The French redistributor PACT has agreed to donate $1.00 for each GNU/Linux
+CD that they sell.
+Red Hat Software has agreed to donate $1.00 to the FSF for every copy of Red
+Hat Archives sold. They have also added a GNU logo to the back of that CD
+with the words "Supports the Free Software Foundation".
+The SNOW 2.1 CD producers added the words "Includes $5 donation to the FSF"
+to the front of their CD. Potential buyers will know just how much of the
+price is for the FSF & how much is for the redistributor.
-Free Software Redistributors Donate
-***********************************
+The Sun Users Group Deutschland has made it even clearer: their CD says,
+"Price 90 DM, + 12 DM donation to the FSF." We thank them for their
+contribution to our efforts.
-by Richard Stallman
+Kyoto Micro Computer of Japan regularly gives us 10% of their GNU-related
+sales.
-The Sun Users Group Deutschland and ASCII Corporation (Japan) have added
-donations to the FSF to the price of their next CD-ROM of GNU software.
-Potential purchasers will know precisely how much of the price is for the FSF
-and how much is for the redistributor.
+Mr. Hiroshi, Mr. Kojima, and the other authors of the `Linux Primer' in Japan
+have donated money from the sales of their book.
-Austin Code Works, a redistributor of free software, is supporting free
-software development by giving the FSF 20% of the selling price for the GNU
-software packages they produce and sell. The producers of the SNOW 2.1 CD
-added the words "Includes $5 donation to the FSF" to the front of their CD.
-Walnut Creek CDROM and Info Magic, two more free software redistributors, are
-also giving us a percentage of their selling price. CQ Publishing made a
-large donation from the sales of their book about GAWK in Japanese.
+Infomagic has continued to make sizable donations to the FSF.
+
+At the request of author Arnold Robbins, Specialized Systems Consultants, Inc.
+continues to donate 3% of their profits from selling `Effective AWK
+Programming'. We would also like to acknowledge the many SSC authors who
+have donated their royalties and fees to the FSF.
In the long run, the success of free software depends on how much new free
software people develop. Free software distribution offers an opportunity to
@@ -166,7 +188,7 @@ raise funds for such development in an ethical way. These redistributors
have made use of the opportunity. Many others let it go to waste.
You can help promote free software development by convincing for-a-fee
-redistributors to contribute--either by doing development themselves, or by
+redistributors to contribute--either by doing development themselves or by
donating to development organizations (the FSF and others).
The way to convince distributors to contribute is to demand and expect this
@@ -184,17 +206,17 @@ as profit.
Also, press developers for firm information about what kind of development
they do or support. Some kinds make much more long-term difference than
-others. For example, maintaining a separate version of a GNU program
+others. For example, maintaining a separate version of a GNU program
contributes very little; maintaining a program on behalf of the GNU Project
contributes much. Easy new ports contribute little, since someone else would
surely do them; difficult ports such as adding a new CPU to the GNU compiler
-contribute more; major new features and programs contribute the most.
+or Mach contribute more; major new features & programs contribute the most.
By establishing the idea that supporting further development is "the proper
thing to do" when distributing free software for a fee, we can assure a
steady flow of resources for making more free software.
-
+
Help from Free Software Companies
*********************************
@@ -206,3359 +228,3706 @@ themselves for general use. By basing your decision partially on this
factor, you can help encourage those who profit from free software to
contribute to its growth.
-These free software support companies regularly donate a part of their income
-to the Free Software Foundation to support the development of new GNU
-programs. Listing them here is our way of thanking them. Wingnut has made a
-pledge to donate 10% of their income to the FSF, and has also purchased
-several Deluxe Distribution packages in Japan. (Wingnut is SRA's special GNU
-support group). Also see *Note Cygnus Matches Donations!::.
+Wingnut (SRA's special GNU support group) supports the FSF by purchasing
+Deluxe Distribution packages on a regular basis. In this way they transfer
+10% of their income to the FSF. Listing them here is our way of thanking
+them.
+
+ Wingnut Project
+ Software Research Associates, Inc.
+ 1-1-1 Hirakawa-cho, Chiyoda-ku
+ Tokyo 102, Japan
+
+ Phone: (+81-3)3234-2611
+ Fax: (+81-3)3942-5174
+ E-mail: `info-wingnut@sra.co.jp'
+ WWW: `http://www.sra.co.jp/public/sra/product/wingnut/'
+
+
+
+Major Changes in GNU Software and Documentation
+***********************************************
+
+ * Hurd Progress (Also *note What Is the Hurd::.)
+
+ We have made three test releases of the Hurd, the most recent being 0.2.
+ The Hurd is currently much more reliable than previously, and various
+ utilities and file system translators, such as an FTP file system, have
+ been written that take advantage of the Hurd's unique design.
+
+ One way for people to help out is to compile and run as much third-party
+ free software as they can; in this way we can find bugs and deficiencies
+ with some rapidity. Volunteers with a PC are therefore eagerly sought to
+ get the 0.2 release and compile their favorite Unix programs and games.
+
+ Daily snapshots of the Hurd sources are now available for those that
+ want to see the latest (non-stable) version; see the Hurd page on the
+ FSF Web site, `http://www.gnu.ai.mit.edu', for more information.
+
+ * New Source Code CD! (*note July 1997 Source Code CD-ROMs::.)
+
+ We are releasing the July 1997 (Edition 10) Source Code CD-ROM this
+ month. Once again, it is a two disk set. It includes several new
+ packages: `aegis', `cook', `guavac', `lesstif', `prcs', `rsync', `swarm',
+ & `vera'. On the CD-ROMs are full distributions of X11R6.3,,
+ Emacs, GCC, and current versions of all other GNU Software. *Note GNU
+ Software::, for more about these packages.
+
+ * New/Updated Manuals since Last Bulletin (*note Documentation::.)
+
+ Since the last bulletin, we have published several updated editions of
+ our manuals (note the price changes): `GNU Emacs Manual', revised for
+ GNU Emacs version 20, now $30; & `Texinfo Manual', for version 3.11 of
+ Texinfo, now $25. We hope to have the following available very soon:
+ `GNU Tar manual', first time in print, freshly reorganized and
+ rewritten, $20; `GNU Software for MS-Windows and MS-DOS', a book and
+ CD-ROM set with a variety of GNU software compiled for MS-DOS and
+ Windows 3.1/95/97/NT, $35 ($140 for corporate orders). Watch our Web
+ site, `http://www.gnu.ai.mit.edu', for announcements of these
+ publications.
+
+ * Fonts freed
+
+ A free commercial-quality set of the basic 35 Postscript Type 1 fonts is
+ now finally available. The copyright holder of these fonts, URW++
+ Design and Development Incorporated, has decided to release them under
+ the GPL. Each font includes `.pfb' (outlines), `.afm' (metrics), and
+ `.pfm' (Windows printer metrics) files. The fonts are compatible with
+ Adobe Type Manager and with general Type 1 manipulation tools, as well
+ as with Ghostscript and other Postscript language interpreters.
+
+ The fonts are available in `ghostscript-fonts-4.0.tar.gz' on the usual
+ FTP sites.
+
+ * DDD now works with LessTif (Also *note GNU Software::.) Release 2.1.1
+ of DDD, the Data Display Debugger, now works with LessTif, a free Motif
+ clone.
+
+ * Give to GNU the United Way!
+
+ As a 501(c)3 tax-exempt organization, the FSF is eligible to receive
+ United Way funds. When donating to United Way, one can specify that all
+ or part of the donation be directed to the FSF. On the donor form,
+ check the "Specific Requests" box and include the sentence, "Send my
+ gift to the Free Software Foundation, 59 Temple Place, Suite 330,
+ Boston, MA 02111." We especially appreciate the donations from Microsoft
+ matching the United Way donations of their employees. Also see *Note
+ Donations Translate Into Free Software::, and *Note Cygnus Matches
+ Donations!::.
+
+ * Tapes and MS-DOS Diskettes No Longer Available from the FSF
+
+ We no longer offer tapes or MS-DOS diskettes due to very low demand.
+
+ * GNU Software Works on MS-DOS (Also *note GNU Software::.)
+
+ GNU Emacs 19 and many other GNU programs have been ported to MS-DOS for
+ i386/i486/Pentium machines. We ship binaries & sources on the *Note
+ Compiler Tools Binaries CD-ROM::.
+
+ * The FSF Takes Discover
+
+ The Free Software Foundation now accepts the Discover card for orders or
+ donations. We also accept the following: Carte Blanche, Diner's Club,
+ JCB, MasterCard, Visa, and American Express. Note that we are charged
+ about 5% of an order's total amount in credit card processing fees;
+ please consider paying by check instead or adding on a 5% donation to
+ make up the difference. We do *not* recommend that you send credit card
+ numbers to us via email, since we have no way of insuring that the
+ information will remain confidential.
+
+ * MULE Merge Complete
+
+ MULE is the Multi-Lingual Emacs developed by Ken'ichi Handa at the
+ Electrotechnical Lab in Tsukuba, Japan. This code has been merged into
+ Emacs and is included in Emacs 20.
+
+ * GPC, the GNU Pascal Compiler
+
+ The GNU Pascal Compiler (GPC) is part of the GNU compiler family, GNU CC
+ or GCC. It combines a Pascal front end with the proven GNU compiler
+ backend for code generation and optimization. Unlike utilities such as
+ p2c, this is a true compiler, not just a converter.
+
+ Version 2.0 of GPC corresponds to GCC version 2.7.2.1.
- Wingnut Project
- Software Research Associates, Inc.
- 1-1-1 Hirakawa-cho, Chiyoda-ku
- Tokyo 102, Japan
+ The purpose of the GNU Pascal project is to produce a compiler which:
+ * combines the clarity of Pascal with powerful tools suitable for
+ real-life programming,
- Phone: (+81-3)3234-2611
- Fax: (+81-3)3942-5174
- E-mail: `info-wingnut@sra.co.jp'
+ * supports both the Pascal standard and the Extended Pascal standard
+ as defined by ISO, ANSI and IEEE. (ISO 7185:1990, ISO/IEC
+ 10206:1991, ANSI/IEEE 770X3.160-1989)
+ * supports other Pascal standards (UCSD Pascal, Borland Pascal,
+ Pascal-SC) in so far as this serves the goal of clarity and
+ usability,
+ * can generate code for and run on any computer for which the GNU C
+ Compiler can generate code and run on.
+
+ The current release (2.0) implements Standard Pascal (ISO 7185, level 0)
+ and a large subset of Extended Pascal (ISO 10206) and Borland Pascal.
+
+ The upcoming release 2.1 features better conformance to the various
+ Pascal standards, and of course bug fixes.
+
+ A growing group of GPC enthusiasts contributes to the project with code,
+ bug reports or fixes.
+
+ `http://agnes.dida.physik.uni-essen.de/~gnu-pascal/', also known as
+ `http://home.pages.de/~gnu-pascal/', is the GNU Pascal home page;
+ sources may be downloaded from `ftp://kampi.hut.fi/jtv/gnu-pascal/'
+ (official) or `ftp://agnes.dida.physik.uni-essen.de/pub/gnu-pascal/'
+ (development versions).
+
+ * GUILE
+
+ GUILE 1.2 is released. GNU's Ubiquitous Intelligent Language for
+ Extension is an SCM-based library that can make any ordinary C program
+ extensible. (For SCM info, see "JACAL" in *Note GNU Software::.)
+ Nightly snapshots of the development sources are also available, in
+ `ftp://ftp.red-bean.com/pub/guile/guile-core-snap.tar.gz'.
+
+ Also being developed are SCSH-compatible system call & Tk interfaces, a
+ module system, dynamic linking support, & a byte-code interpreter.
+ Support for Emacs Lisp & a more C-like language is coming.
+
+ * A New FSF T-shirt!
+
+ We have a new T-shirt design. *Note FSF T-shirt::, for the description.
+
+ * New free game
+
+ In August 1995, the action game Abuse by Jonathan Clark was released for
+ the first time. It wasn't free software then--but now, less than two
+ years later, the company Crack dot Com has rereleased it as free
+ software. Abuse was initially developed on Linux-based GNU systems, and
+ we've included it on our our source CD set.
+
+ Beyond providing the free software community with a game that many
+ people enjoy, and code that could be useful for developing other free
+ games, this demonstrates an important fact about the economic
+ circumstances of computer game development: most non-free games bring
+ their profit in a very short period of time. Therefore, a game company
+ can turn a game into free software fairly soon, with little hardship.
+
+ Let's hope that other game developers follow this example.
+
+
+
+The Deluxe Distribution
+***********************
+
+The Free Software Foundation has been asked repeatedly to create a package
+that provides executables for all of our software. Normally we offer only
+sources. The Deluxe Distribution provides binaries with the source code and
+includes six T-shirts, all our CD-ROMs, printed manuals, & reference cards.
+
+The FSF Deluxe Distribution contains the binaries and sources to hundreds of
+different programs including Emacs, the GNU C/C++ Compiler, the GNU Debugger,
+the complete X Window System, and all the GNU utilities.
+
+We will make a Deluxe Distribution for most machines/operating systems. We
+may be able to send someone to your office to do the compilation, if we can't
+find a suitable machine here. However, we can only compile the programs that
+already support your chosen machine/system - porting is a separate matter.
+(To commission a port, see the GNU Service Directory; details in *Note Free
+Software Support::.) Compiling all these programs takes time; a Deluxe
+Distribution for an unusual machine will take longer to produce than one for
+a common machine. Please contact the FSF Office with any questions.
+
+We supply the software on a write-once CD-ROM (in ISO 9660 format with "Rock
+Ridge" extensions), or on one of these tapes in Unix `tar' format: 1600 or
+6250bpi 1/2in reel, Sun DC300XLP 1/4in cartridge - QIC24, IBM RS/6000 1/4in
+c.t. - QIC 150, Exabyte 8mm c.t., or DAT 4mm c.t. If your computer cannot
+read any of these, please contact us to see if we can handle your format.
+
+The manuals included are one each of `Bison', `Calc', `GAWK', `GCC', `GNU C
+Library', `GDB', `Flex', `GNU Emacs Lisp Reference', `Programming in Emacs
+Lisp: An Introduction', `Make', `Texinfo', & `Termcap' manuals; six copies of
+the `GNU Emacs' manual; and ten reference cards each for Emacs, Bison, Calc,
+Flex, & GDB.
+
+Every Deluxe Distribution also has a copy of the latest editions of our
+CD-ROMs that have sources of our software & compiler tool binaries for some
+systems. The CDs are in ISO 9660 format with Rock Ridge extensions.
+
+The price of the Deluxe Distribution is $5000 (shipping included). These
+sales provide enormous financial assistance to help the FSF develop more free
+software. To order, please fill out the "Deluxe Distribution" section on the
+*note Free Software Foundation Order Form::. and send it to:
+
+ Free Software Foundation, Inc.
+ 59 Temple Place - Suite 330
+ Boston, MA 02111-1307
+ USA
+
+ Telephone: +1-617-542-5942
+ Fax (including Japan): +1-617-542-2652
+ Electronic Mail: gnu@prep.ai.mit.edu
+ World Wide Web: http://www.gnu.ai.mit.edu
+
+
GNU Documentation
*****************
-GNU is dedicated to having quality, easy-to-use online and printed
-documentation. GNU manuals are intended to explain underlying concepts,
-describe how to use all the features of each program, and give examples of
+GNU is dedicated to having quality, easy-to-use online & printed
+documentation. GNU manuals are intended to explain underlying concepts,
+describe how to use all the features of each program, & give examples of
command use. GNU manuals are distributed as Texinfo source files, which
-yield both typeset hardcopy via the TeX document formatting system, and online
+yield both typeset hardcopy via the TeX document formatting system and online
hypertext display via the menu-driven Info system. Source for these manuals
-comes with our software; here we list the manuals that we publish as printed
-books as well; see the *note Free Software Foundation Order Form::..
+comes with our software; here are the manuals that we publish as printed
+books. *Note Free Software Foundation Order Form::, to order them.
Most GNU manuals are bound as soft cover books with "lay-flat" bindings.
This allows you to open them so they lie flat on a table without creasing the
-binding. These books have an inner cloth spine and an outer cardboard cover
-that will not break or crease as an ordinary paperback will. Currently, the
-`GDB', `Emacs', `Emacs Lisp Reference', `GAWK', `Make', `Bison', and `Texinfo'
-manuals have this binding. The other GNU manuals also lie flat when opened,
-using a GBC or Wire-O binding. All of our manuals are 7in by 9.25in except
-the 8.5in by 11in `Calc' manual.
+binding. They have an inner cloth spine and an outer cardboard cover that
+will not break or crease as an ordinary paperback will. Currently, the
+`Using and Porting GNU CC', `GDB', `Emacs', `Emacs Lisp Reference',
+`Programming in Emacs Lisp: An Introduction', `GNU Awk User's Guide', `Make',
+& `Bison' manuals have this binding. Our other manuals also lie flat when
+opened, using a GBC binding. Our manuals are 7in by 9.25in except the 8.5in
+by 11in `Calc' manual.
The edition number of the manual and version number of the program listed
after each manual's name were current at the time this Bulletin was published.
-`Debugging with GDB' (Edition 4.12 for Version 4.14) tells how to use the GNU
-Debugger, run your program under debugger control, examine and alter data,
-modify a program's flow of control, and use GDB through GNU Emacs.
+`Debugging with GDB' (for Version 4.16) tells how to run your program under
+GNU Debugger control, examine and alter data, modify a program's flow of
+control, and use GDB through GNU Emacs.
-The `Emacs Manual' (11th Edition for Version 19.29) describes editing with
-GNU Emacs. It explains advanced features, including outline mode and regular
-expression search; how to use special modes for programming in languages like
-C++ and TeX; how to use the `tags' utility; how to compile and correct code;
-how to make your own keybindings; and other elementary customizations.
+The `GNU Emacs Manual' (13th Edition for Version 20) describes editing with
+GNU Emacs. It explains advanced features, including international character
+sets; outline mode and regular expression search; how to use special
+programming modes to write languages like C++ and TeX; how to use the `tags'
+utility; how to compile and correct code; how to make your own keybindings;
+and other elementary customizations.
-`Programming in Emacs Lisp, An Introduction' (Edition 1.03 for Version 19.29)
-is an elementary introduction to programming in Emacs Lisp. It is written
+`Programming in Emacs Lisp: An Introduction' (October 1995 Edition 1.04) is
for people who are not necessarily interested in programming, but who do want
-to customize or extend their computing environment. It tells how to write
-programs that find files; switchbuffers; use searches, conditionals, loops,
-and recursion; how to write Emacs initialization files; and how to run the
-Emacs Lisp debuggers. If you read the text in GNU Emacs under Info mode, you
-can run the sample programs directly.
-
-The `GNU Emacs Lisp Reference Manual' (Edition 2.4 for Version 19.29) covers
-this programming language in depth, including data types, control structures,
-functions, macros, syntax tables, searching/matching, modes, windows,
-keymaps, byte compilation, and the operating system interface.
-
-The `GAWK Manual' (Edition 0.16 for Version 2.16) tells how to use the GNU
-implementation of `awk'. It is written for those who have never used `awk'
-and describes the features of this powerful string and record manipulation
-language.
-
-The `Make Manual' (Edition 0.46 for Version 3.72) describes GNU `make', a
+to customize or extend their computing environment. If you read it in Emacs
+under Info mode, you can run the sample programs directly.
+
+`The GNU Emacs Lisp Reference Manual' (Edition 2.4 for Version 19.29) and
+`The GNU Emacs Lisp Reference, Japanese Edition' (Japanese Draft Revision
+1.0, from English Edition 2.4 for Version 19.29) cover this programming
+language in depth, including data types, control structures, functions,
+macros, syntax tables, searching/matching, modes, windows, keymaps, byte
+compilation, and the operating system interface.
+
+`The GNU Awk User's Guide' (Edition 1.0 for Version 3.0) tells how to use
+`gawk'. It is written for those who have never used `awk' and describes
+features of this powerful string and record manipulation language. It
+clearly delineates those features which are part of POSIX `awk' from `gawk'
+extensions, providing a comprehensive guide to `awk' program portability.
+
+`GNU Make' (Edition 0.51 for Version 3.76 Beta) describes GNU `make', a
program used to rebuild parts of other programs. The manual tells how to
write "makefiles", which specify how a program is to be compiled and how its
files depend on each other. Included are an introductory chapter for novice
users and a section about automatically generated dependencies.
-The `Flex Manual' (Edition 1.03 for Version 2.3.7) teaches you to write a
+The `Flex' manual (Edition 1.03 for Version 2.3.7) teaches you to write a
lexical scanner definition for the `flex' program to create a C++ or C-coded
scanner that recognizes the patterns defined. You need no prior knowledge of
scanners.
-The `Bison Manual' (December 1993 Edition for Version 1.23) teaches you how
+`The Bison Manual' (November 1995 Edition for Version 1.25) teaches you how
to write context-free grammars for the Bison program that convert into
C-coded parsers. You need no prior knowledge of parser generators.
-`Using and Porting GNU CC' (September 1994 Edition for Version 2.6) tells how
-to run, install, and port the GNU C Compiler to new systems. It lists new
-features and incompatibilities of GCC, but people not familiar with C will
-still need a good reference on the C programming language. It also covers
-G++.
+`Using and Porting GNU CC' (November 1995 Edition for Version 2.7.2) tells
+how to run, install, and port the GNU C Compiler to new systems. It lists
+new features and incompatibilities of GCC, but people not familiar with C
+will still need a good reference on the C programming language. It also
+covers G++.
-The `Texinfo Manual' (Edition 2.20 for Version 3) explains the markup
-language used to generate both the online Info documentation and typeset
-hardcopies. It tells you how to make tables, lists, chapters, nodes,
-indexes, cross references, how to use Texinfo mode in GNU Emacs, and how to
-catch mistakes. This second edition describes over 50 new commands.
+The `Texinfo' manual (Edition 2.24 for Version 3) explains the markup
+language that produces our online Info documentation & typeset hardcopies.
+It tells you how to make tables, lists, chapters, nodes, accented & special
+characters, indexes, cross references, & how to catch mistakes.
-The `Termcap Manual' (2nd Edition for Version 1.2), often described as "twice
+`The Termcap Manual' (3rd Edition for Version 1.3), often described as "twice
as much as you ever wanted to know about termcap," details the format of the
termcap database, the definitions of terminal capabilities, and the process
of interrogating a terminal description. This manual is primarily for
programmers.
-The `C Library Reference Manual' (Edition 0.06 for Version 1.09) describes
-most of the facilities of the GNU C library, including both what Unix calls
-"library functions" and "system calls." We are doing limited copier runs of
-this manual until it becomes more stable. Please send corrections and
-improvements to `bug-glibc-manual@prep.ai.mit.edu'.
-
-The `Emacs Calc Manual' (Edition 2.02 for Version 2.02) is both a tutorial
-and a reference manual. It tells how to do ordinary arithmetic, how to use
-Calc for algebra, calculus, and other forms of mathematics, and how to extend
-Calc.
+The `C Library Reference Manual' (Edition 0.08 for Version 2.0) describes the
+library's facilities, including both what Unix calls "library functions" &
+"system calls." We are doing small copier runs of this manual until it
+becomes more stable. Please send fixes to `bug-glibc-manual@prep.ai.mit.edu'.
+The `Emacs Calc Manual' (for Version 2.02) is both a tutorial and a reference
+manual. It tells how to do ordinary arithmetic, how to use Calc for algebra,
+calculus, and other forms of mathematics, and how to extend Calc.
+
-GNU Software - (NOT COMPLETELY UP TO DATE)
+GNU Software
************
All our software is available via FTP; see *Note How to Get GNU Software::.
-In addition, we offer software on various media and printed documentation:
-
- * *Note CD-ROMs::.
-
- * *Note Tapes::.
-
- * *Note MS-DOS Diskettes::.
+We also offer *Note CD-ROMs::, and printed *Note Documentation::, which
+includes manuals and reference cards. In the articles describing the
+contents of each medium, the version number listed after each program name
+was current when we published this Bulletin. When you order a newer CD-ROM,
+some of the programs may be newer and therefore the version number higher.
+*Note Free Software Foundation Order Form::, for ordering information.
- * *Note Documentation::, which includes manuals and reference cards.
+Some of the contents of our FTP distributions are compressed. We have
+software on our FTP sites to uncompress these files. Due to patent troubles
+with `compress', we use another compression program, `gzip'.
-We welcome all bug reports sent to the appropriate electronic mailing list
-(*note Free Software Support::.).
+You may need to build GNU `make' before you build our other software. Some
+vendors supply no `make' utility at all and some native `make' programs lack
+the `VPATH' feature essential for using the GNU configure system to its full
+extent. The GNU `make' sources have a shell script to build `make' itself on
+such systems.
-In the articles describing the contents of each medium, the version number
-listed after each program name was current when we published this Bulletin.
-When you order a distribution tape, diskette or newer CD-ROM, some of the
-programs may be newer, and therefore the version number higher.
+We welcome all bug reports and enhancements sent to the appropriate
+electronic mailing list (*note Free Software Support::.).
-Key to cross reference:
-
-
- BinCD
- Binaries CD-ROM
-
- DjgppD
- Djgpp Diskettes
-
- DosCD
- MS-DOS CD-ROM
-
- EmcsD
- Emacs Diskettes
+
- LspEmcT
- Lisps/Emacs Tape
+Configuring GNU Software
+------------------------
- LangT
- Languages Tape
+We are using Autoconf, a uniform scheme for configuring GNU software packages
+in order to compile them (see "Autoconf" and "Automake" below, in this
+article). The goal is to have all GNU software support the same alternatives
+for naming machine and system types.
- LiteT
- 4.4BSD-Lite Tape
+Ultimately, it will be possible to configure and build the entire system all
+at once, eliminating the need to configure each individual package separately.
- SchmT
- Scheme Tape
+You can also specify both the host and target system to build
+cross-compilation tools. Most GNU programs now use Autoconf-generated
+configure scripts.
- SrcCD
- Source CD-ROM
+
- UtilD
- Selected Utilities Diskettes
-
- UtilT
- Utilities Tape
-
- VMSCompT
- VMS Compiler Tape
+GNU Software Now Available
+--------------------------
- VMSEmcsT
- VMS Emacs Tape
+For future programs and features, see *Note Forthcoming GNUs::.
- WdwsD
- Windows Diskette
+Key to cross reference:
- X11OptT
- X11 Optional Tape
+ BinCD January 1997 Binaries CD-ROM
+ SrcCD July 1997 Source CD-ROMs
- X11ReqT
- X11 Required Tape
+[FSFman] shows that we sell a manual for that package. [FSFrc] shows we sell
+a reference card for that package. To order them, *Note Free Software
+Foundation Order Form::. *Note Documentation::, for more information on the
+manuals. Source code for each manual or reference card is included with each
+package.
+ * `abuse' *Also *note GNUs Flashes::.* (SrcCD)
+ The recently-freed program `abuse' is a dark, side-scrolling game with
+ Robotron-esque controls: you control your movement with the keyboard and
+ fire & aim with the mouse. You can get more info at
+ `http://crack.com/games/abuse'.
-Configuring GNU Software:
+ * acct (SrcCD)
-We are using a uniform scheme for configuring GNU software packages in order
-to compile them. It uses the `Autoconf' program (see item below). The goal
-is to have all GNU software support the same alternatives for naming machine
-and system types. When the GNU system is complete it will be possible to
-configure and build the entire system at once, eliminating the need to
-separately configure each individual package. The configuration scheme lets
-you specify both the host and target system to build cross-compilation tools.
+ acct is a system accounting package. It includes the programs `ac'
+ (summarize login accounting), `accton' (turn accounting on or off),
+ `last' (show who has logged in recently), `lastcomm' (show which
+ commands have been used), `sa' (summarize process accounting),
+ `dump-utmp' (print a `utmp' file in human-readable format), &
+ `dump-acct' (print an `acct' or `pacct' file in human-readable format).
+ * `acm' (SrcCD)
+ `acm' is a LAN-oriented, multiplayer, aerial combat simulation that runs
+ under the X Window System. Players engage in air to air combat against
+ one another using heat seeking missiles and cannons. We are working on
+ a more accurate simulation of real airplane flight characteristics.
-GNU software currently available:
+ * aegis (SrcCD)
-(For new features and coming programs, see *Note Forthcoming GNUs::.)
+ Aegis is a transaction-based software configuration management system.
+ It provides a framework within which a team of developers may work on
+ many changes to a program concurrently, and Aegis coordinates
+ integrating these changes back into the master source of the program,
+ with as little disruption as possible.
- * `acm' (SrcCD, UtilT)
+ * Apache *Also see* `http://www.apache.org/' (SrcCD)
- `acm' is a LAN-oriented, multiplayer aerial combat simulation that runs
- under the X Window System. Players engage in air to air combat against
- one another using heat seeking missiles and cannons. We are working on
- more accurate simulation of real airplane flight characteristics.
+ Apache is an HTTP server designed as a successor to the NCSA family of
+ Web servers. It adds a significant amount of new functionality, has an
+ extensive API for modular enhancements, is extremely flexible without
+ compromising speed, and has an active development group and user
+ community.
- * Autoconf (SrcCD, UtilT)
+ * Autoconf (SrcCD)
Autoconf produces shell scripts which automatically configure source code
- packages. These scripts adapt the packages to many kinds of Unix-like
- systems without manual user intervention. Autoconf creates a script for
+ packages. These scripts adapt the packages to many kinds of Unix-like
+ systems without manual user intervention. Autoconf creates a script for
a package from a template file which lists the operating system features
which the package can use, in the form of `m4' macro calls. Autoconf
requires GNU `m4' to operate, but the resulting configure scripts it
generates do not.
- Most GNU programs now use Autoconf-generated configure scripts.
+ * Automake (SrcCD)
- * BASH (SrcCD, UtilT)
+ Automake is a tool for generating `Makefile.in' files for use with
+ Autoconf. The generated makefiles are compliant with GNU Makefile
+ standards.
- The GNU shell, BASH (Bourne Again SHell), is compatible with the Unix
- `sh' and offers many extensions found in `csh' and `ksh'. BASH has job
- control, `csh'-style command history, and command-line editing (with
- Emacs and `vi' modes built-in, and the ability to rebind keys) via the
- readline library. BASH conforms to the POSIX 1003.2 shell specification.
+ * BASH (SrcCD)
- * `bc' (DjgppD, DosCD, SrcCD, UtilT)
+ GNU's shell, BASH (Bourne Again SHell), is compatible with the Unix `sh'
+ and offers many extensions found in `csh' and `ksh'. BASH has job
+ control, `csh'-style command history, command-line editing (with Emacs
+ and `vi' modes built-in), and the ability to rebind keys via the
+ `readline' library. BASH conforms to the POSIX 1003.2-1992 standard.
+
+ * bc (SrcCD)
`bc' is an interactive algebraic language with arbitrary precision
- numbers. GNU `bc' follows the POSIX.2-1992 standard, with several
- extensions including multi-character variable names, an `else'
+ numbers. GNU `bc' follows the POSIX 1003.2-1992 standard with several
+ extensions, including multi-character variable names, an `else'
statement, and full Boolean expressions. The RPN calculator `dc' is now
distributed as part of the same package, but GNU `bc' is not implemented
as a `dc' preprocessor.
- * BFD (BinCD, DjggpD, DosCD, LangT, SrcCD)
+ * BFD (BinCD, SrcCD)
The Binary File Descriptor library allows a program which operates on
object files (e.g., `ld' or GDB) to support many different formats in a
- clean way. BFD provides a portable interface, so that only BFD needs to
+ clean way. BFD provides a portable interface, so that only BFD needs to
know the details of a particular format. One result is that all
programs using BFD will support formats such as a.out, COFF, and ELF.
- BFD comes with source for Texinfo documentation (not yet published on
- paper). Presently BFD is not distributed separately; it is included
- with packages that use it.
-
- * Binutils (BinCD, DjgppD, DosCD, LangT, SrcCD)
-
- Binutils includes the programs: `ar', `c++filt', `demangle', `gas',
- `gprof', `ld', `nlmconv', `nm', `objcopy', `objdump', `ranlib', `size',
- `strings', and `strip'.
-
- Binutils Version 2 uses the BFD library. The GNU linker `ld' emits
- source-line numbered error messages for multiply-defined symbols and
- undefined references. It interprets a superset of the AT&T Linker
- Command Language, which gives general control over where segments are
- placed in memory. `nlmconv' converts object files into Novell NetWare
- Loadable Modules. `objdump' can disassemble code for a29k, ALPHA,
- H8/300, H8/500, HP-PA, i386, i960, m68k, m88k, MIPS, SH, SPARC, & Z8000
- processors, and can display other data (e.g., symbols & relocations)
- from any file format understood by BFD.
-
- * Bison (BinCD, DjgppD, DosCD, LangT, SrcCD, VMSCompT)
+ BFD comes with Texinfo source for a manual (not yet published on paper).
+
+ At present, BFD is not distributed separately; it is included with
+ packages that use it.
+
+ * Binutils (BinCD, SrcCD)
+
+ Binutils includes these programs: `addr2line', `ar', `c++filt', `gas',
+ `gprof', `ld', `nm', `objcopy', `objdump', `ranlib', `size', `strings', &
+ `strip'.
+
+ Binutils version 2 uses the BFD library. The GNU assembler, `gas',
+ supports the a29k, Alpha, ARM, D10V, H8/300, H8/500, HP-PA, i386, i960,
+ M32R, m68k, m88k, MIPS, Matsushita 10200 and 10300, NS32K, PowerPC,
+ RS/6000, SH, SPARC, Tahoe, Vax, and Z8000 CPUs, and attempts to be
+ compatible with many other assemblers for Unix and embedded systems. It
+ can produce mixed C and assembly listings, and includes a macro facility
+ similar to that in some other assemblers. GNU's linker, `ld', supports
+ shared libraries on many systems, emits source-line numbered error
+ messages for multiply-defined symbols and undefined references, and
+ interprets a superset of AT&T's Linker Command Language, which gives
+ control over where segments are placed in memory. `objdump' can
+ disassemble code for most of the CPUs listed above, and can display
+ other data (e.g., symbols and relocations) from any file format read by
+ BFD.
+
+ * Bison (BinCD, SrcCD) [FSFman, FSFrc]
Bison is an upwardly compatible replacement for the parser generator
`yacc'. Texinfo source for the `Bison Manual' and reference card are
- included. *Note Documentation::.
-
- We recently decided to change the policy for using the parsers that
- Bison generates. It is now permitted to use Bison-generated parsers in
- non-free programs. *Note GNUs Flashes::.
+ included.
- * GNU C Library (BinCD, LangT, SrcCD)
+ * C Library (`glibc') (BinCD, SrcCD) [FSFman]
- The GNU C library supports ANSI C-1989, POSIX 1003.1-1990 and most of the
- functions in POSIX 1003.2-1992. It is upwardly compatible with 4.4BSD
- and includes many System V functions, plus GNU extensions.
+ The GNU C library supports ISO C-1989, ISO C/amendment 1-1995, POSIX
+ 1003.1-1990, POSIX 1003.1b-1993, POSIX 1003.1c-1995 (when the underlying
+ system permits), & most of the functions in POSIX 1003.2-1992. It is
+ nearly compliant with the extended XPG4.2 specification which guarantees
+ upward compatibility with 4.4BSD & many System V functions.
- The C Library will perform many functions of the Unix system calls in
- the Hurd. Mike Haertel has written a fast `malloc' which wastes less
- memory than the old GNU version. The GNU regular-expression functions
- (`regex' and `rx') now nearly conform to the POSIX 1003.2 standard.
+ When used with the GNU Hurd, the C Library performs many functions of the
+ Unix system calls directly. Mike Haertel has written a fast `malloc'
+ which wastes less memory than the old GNU version.
GNU `stdio' lets you define new kinds of streams, just by writing a few
- C functions. The `fmemopen' function uses this to open a stream on a
- string, which can grow as necessary. You can define your own `printf'
- formats to use a C function you have written. For example, you can
- safely use format strings from user input to implement a `printf'-like
- function for another programming language. Extended `getopt' functions
- are already used to parse options, including long options, in many GNU
- utilities.
-
- The C Library runs on Sun-3 (SunOS 4.1), Sun-4 (SunOS 4.1 or Solaris 2),
- HP 9000/300 (4.3BSD), SONY News 800 (NewsOS 3 or 4), MIPS DECstation
- (Ultrix 4), DEC Alpha (OSF/1), i386/i486 (System V, SVR4, BSD, SCO 3.2 &
- SCO ODT 2.0), Sequent Symmetry i386 (Dynix 3) & SGI (Irix 4). Texinfo
- source for the `GNU C Library Reference Manual' is included (*note
- Documentation::.); the manual is now being updated.
-
- * GNU C++ Library (BinCD, DjgppD, DosCD, LangT, SrcCD)
-
- The GNU C++ library (libg++) contains an extensive collection of C++
- `forest' classes, an IOStream library for input/output routines, and
- support tools for use with G++. Supported classes include: Obstacks,
- multiple-precision Integers and Rationals, Complex numbers, arbitrary
- length Strings, BitSets and BitStrings. Version 2.6.2 includes the
- initial release of the libstdc++ library. This implements library
- facilities defined by the forthcoming ANSI/ISO C++ standard, including
- the Standard Template Library.
-
- * Calc (LspEmcT, SrcCD)
+ C functions. Two methods for handling translated messages help writing
+ internationalized programs & the user can adopt the environment the
+ program runs in to conform with local conventions. Extended `getopt'
+ functions are already used to parse options, including long options, in
+ many GNU utilities. The name lookup functions now are modularized which
+ makes it easier to select the service which is needed for the specific
+ database & the document interface makes it easy to add new services.
+ Texinfo source for the `GNU C Library Reference Manual' is included
+ (*note Documentation::.).
+
+ Previous versions of the GNU C library ran on a large number of systems.
+ The architecture-dependent parts of the C library have not been updated
+ since development on version 2.0 started, so today it runs out of the
+ box only on GNU/Hurd (all platforms GNU/Hurd also runs on) & GNU/Linux
+ (ix86, Alpha, m68k, MIPS, Sparc, PowerPC; work is in progress for ARM).
+ Other architectures will become available again as soon as somebody does
+ the port.
+
+ * C++ Library (`libg++') (BinCD, SrcCD)
+
+ The GNU C++ library (traditionally called `libg++') includes libstdc++,
+ which implements the library facilities defined by the forthcoming ISO
+ C++ standard. This includes strings, iostream, and various container
+ classes. All of this is templatized.
+
+ The package also contains the older libg++ library for backward
+ compatibility, but new programs should avoid using it.
+
+ * Calc (SrcCD) [FSFman, FSFrc]
Calc (written by Dave Gillespie in Emacs Lisp) is an extensible, advanced
desk calculator & mathematical tool that runs as part of GNU Emacs. You
- can use Calc just as a simple four-function calculator, but it has many
- more features including: choice of algebraic or RPN (stack-based) entry;
- logarithmic, trigonometric & financial functions; arbitrary precision;
+ can use Calc as a simple four-function calculator, but it has many more
+ features including: choice of algebraic or RPN (stack-based) entry;
+ logarithmic, trigonometric, & financial functions; arbitrary precision;
complex numbers; vectors; matrices; dates; times; infinities; sets;
- algebraic simplification; differentiation & integration. It outputs to
- `gnuplot' & comes with source for a reference card & a Manual. *Note
- Documentation::.
+ algebraic simplification; & differentiation & integration. It outputs
+ to `gnuplot', & comes with source for a manual & reference card (*note
+ Documentation::.).
+
+ * `cfengine' (SrcCD)
+
+ `cfengine' is used to maintain site-wide configuration of a
+ heterogeneous Unix network using a simple high level language. Its
+ appearance is similar to `rdist', but allows many more operations to be
+ performed automatically. See Mark Burgess, "A Site Configuration
+ Engine", `Computing Systems', Vol. 8, No. 3 (ask `office@usenix.org' how
+ to get a copy).
+
+ * Chess (SrcCD)
+
+ GNU Chess enables you to play a game of chess with a computer instead of
+ a person. It is useful to practice with when there are significant
+ spare cpu cycles and a real person is unavailable.
+
+ The program offers a plain terminal interface, one using curses, and a
+ reasonable X Windows interface `xboard'. Best results are obtained by
+ compiling with GNU C.
- * GNU Chess (SrcCD, UtilT, WdwsD)
-
- GNU Chess lets the computer play a full game of chess with you. It runs
- on most platforms & has dumb terminal, "curses" & X terminal interfaces.
- The X terminal interface is based on the `xboard' program.
- m{No Value For "ergegrafkludge"} GNU Chess implements many specialized
- features including the null move heuristic, a hash table with aging, the
- history heuristic (another form of the earlier killer heuristic),
- caching of static evaluations, & a database which lets it play the first
- several moves of the game quickly. Recent improvements include better
- heuristics, faster evaluation, thinking on opponent's time, a perfect
- King and Pawn vs King endgame routine, Swedish & German language
- support, support for more book formats, a rudimentary Bobby Fischer
- clock, & bug fixes. It is primarily supported by Stuart Cracraft, Chua
- Kong Sian, & Tim Mann on behalf of the FSF.
-
- * CLISP (LspEmcT, SrcCD)
-
- CLISP is a Common Lisp implementation by Bruno Haible and Michael Stoll.
+ Improvements this past year are in the Windows-compatible version,
+ mostly bugfixes.
+
+ Stuart Cracraft started the GNU mascot back in the mid-1980's. John
+ Stanback (and innumerable contributors) are responsible for GNU's brain
+ development and its fair play. Acknowledgements for the past year's
+ work are due Conor McCarthy.
+
+ Send bugs to `bug-gnu-chess@prep.ai.mit.edu' & general comments to
+ `info-gnu-chess@prep.ai.mit.edu'. Visit the author's Web site at
+ `http://www.earthlink.net/~cracraft/index.html'. Play GNU Chess on the
+ Web at `http://www.delorie.com/game-room/chess'.
+
+ * CLISP (SrcCD)
+
+ CLISP is a Common Lisp implementation by Bruno Haible & Michael Stoll.
It mostly supports the Lisp described by `Common LISP: The Language (2nd
- edition)' and the ANSI Common Lisp standard. CLISP includes an
- interpreter, a byte-compiler, a large subset of CLOS, a foreign language
- interface and, for some machines, a screen editor. The user interface
- language (English, German, French) is chooseable at run time. Major
- packages that run in CLISP include CLX & Garnet. CLISP needs only 2 MB
- of memory & runs on many microcomputers (including MS-DOS systems, OS/2,
- the Atari ST, Amiga 500-4000, Acorn RISC PC) & Unix-like systems
- (GNU/Linux, Sun4, SVR4, SGI, HP-UX, DEC Alpha, NeXTstep & others).
-
- * GNU Common Lisp (LspEmcT, SrcCD)
-
- GNU Common Lisp (GCL) has a compiler and interpreter for Common Lisp. It
- used to be known as Kyoto Common Lisp. It is very portable and extremely
- efficient on a wide class of applications. It compares favorably in
- performance with commercial Lisps on several large theorem-prover and
- symbolic algebra systems. It supports the CLtL1 specification but is
- moving towards the proposed ANSI definition. GCL compiles to C and
- then uses the native optimizing C compilers (e.g., GCC). A function
- with a fixed number of args and one value turns into a C function of the
- same number of args, returning one value, so GCL is maximally efficient
- on such calls. It has a conservative garbage collector which allows
- great freedom for the C compiler to put Lisp values in arbitrary
- registers. It has a source level Lisp debugger for interpreted code,
- with display of source code in an Emacs window. Ita profiling tools
- (based on the C profiling tools) count function calls and the time spent
- in each function. CLX works with GCL.
-
- There is now a builtin interface with the TK widget system. It runs in
- a separate process so that users may monitor progress on lisp
- computations, or interact with running computations via a windowing
- interface.
-
- There is also an Xlib interface via C (xgcl-2). PCL runs with GCL (see
- PCL item later in this article). *Note Forthcoming GNUs::, for plans for
- about GCL, or for recent developments. GCL version 2.0 is released
- under the GNU Library General Public License.
-
- * `cpio' (DjgppD, DosCD, SrcCD, UtilD, UtilT)
-
- `cpio' is an alternative archive program with all the features of SVR4
- `cpio', including support for the final POSIX 1003.1 `ustar' standard.
- `mt', a program to position magnetic tapes, is included with `cpio'.
-
- * CVS (SrcCD, UtilT)
-
- CVS, the Concurrent Version System, manages software revision and release
- control in a multi-developer, multi-directory, multi-group environment.
- It works best in conjunction with RCS versions 4 and above, but will
- parse older RCS formats with the loss of CVS's fancier features. See
- Berliner, Brian, "CVS-II: Parallelizing Software Development,"
- `Proceedings of the Winter 1990 USENIX Association Conference'. To find
- out how to get a copy of this report, contact `office@usenix.org'.
-
- * DejaGnu (LangT, SrcCD)
-
- DejaGnu is a framework for testing other programs that provides a single
- front end for all tests. The framework's flexibility and consistency
- makes it easy to write tests for any program. DejaGnu comes with
- `expect', which runs scripts to conduct dialogs with programs.
-
- * Diffutils (DjgppD, DosCD, SrcCD, UtilD, UtilT)
+ edition)' & the ANSI Common Lisp standard. CLISP includes an
+ interpreter, a byte-compiler, a large subset of CLOS & a foreign language
+ interface. The user interface language (English, German, French) can be
+ chosen at run time. An X11 API is available through CLX & Garnet.
+ CLISP needs only 2 MB of memory & runs on all kinds of Unix systems & on
+ many microcomputers (including MS-DOS systems, OS/2, Windows NT, Windows
+ 95, Amiga 500-4000, & Acorn RISC PC). See also item "Common Lisp",
+ which describes GCL, a complete Common Lisp implementation with compiler.
+
+ * CLX (SrcCD)
+
+ CLX is an X Window interface library for GCL. This is separate from the
+ built-in TK interface.
+
+ * Common Lisp (`gcl') (SrcCD)
+
+ GNU Common Lisp (GCL, formerly known as Kyoto Common Lisp) is a compiler
+ & interpreter for Common Lisp. GCL is very portable & extremely
+ efficient on a wide class of applications, & compares favorably in
+ performance with commercial Lisps on several large theorem-prover &
+ symbolic algebra systems. GCL supports the CLtL1 specification but is
+ moving towards the proposed ANSI standard.
+
+ GCL compiles to C & then uses the native optimizing C compiler (e.g.,
+ GCC). A function with a fixed number of args & one value turns into a C
+ function of the same number of args, returning one value--so GCL is
+ maximally efficient on such calls. Its conservative garbage collector
+ gives great freedom to the C compiler to put Lisp values in registers.
+ It has a source level Lisp debugger for interpreted code & displays
+ source code in an Emacs window. Its profiler (based on the C profiling
+ tools) counts function calls & the time spent in each function.
+
+ There is now a built-in interface to the Tk widget system. It runs in a
+ separate process, so users may monitor progress on Lisp computations or
+ interact with running computations via a windowing interface.
+
+ There is also an Xlib interface via C (xgcl-2). CLX runs with GCL, as
+ does PCL (see "PCL" later in this article).
+
+ GCL version 2.2.2 is released under the GNU Library General Public
+ License.
+
+ * cook (SrcCD)
+
+ Cook is a tool for constructing files, and maintaining referential
+ integrity between files. It is given a set of files to create, and
+ recipes of how to create and maintain them. In any non-trivial program
+ there will be prerequisites to performing the actions necessary to
+ creating any file, such as include files. The `cook' program provides a
+ mechanism to define these.
+
+ Some features which distinguish Cook include a strong procedural
+ description language, and fingerprints to supplement file modification
+ time stamps. There is also a `make2cook' utility included to ease
+ transition.
+
+ * `cpio' (SrcCD)
+
+ `cpio' is an archive program with all the features of SVR4 `cpio',
+ including support for the final POSIX 1003.1 `ustar' standard. `mt', a
+ program to position magnetic tapes, is included with `cpio'.
+
+ * CVS (SrcCD)
+
+ CVS is a version control system (like RCS or SCCS) which allows you to
+ keep old versions of files (usually source code), keep a log of who,
+ when, and why changes occurred, etc. It handles multiple developers,
+ multiple directories, triggers to enable/log/control various operations,
+ and can work over a wide area network. It does not handle build
+ management or bug-tracking; these are handled by `make' and GNATS,
+ respectively.
+
+ * `cxref' (SrcCD)
+
+ `cxref' is a program that will produce documentation (in LaTeX or HTML)
+ including cross-references from C program source code. It has been
+ designed to work with ANSI C, incorporating K&R, and most popular GNU
+ extensions. The documentation for the subject program is produced from
+ comments in the code that are appropriately formatted. The cross
+ referencing comes from the code itself and requires no extra work.
+
+ * DDD (SrcCD)
+
+ The Data Display Debugger (DDD) is a common graphical user interface to
+ GDB, DBX, and XDB, the popular Unix debuggers. DDD provides a graphical
+ data display where complex data structures can be explored incrementally
+ and interactively. DDD has been designed to compete with well-known
+ commercial debuggers; as of release 2.1.1, DDD also compiles and runs
+ with LessTif, a free Motif clone, without loss of functionality. For
+ more details, see the DDD WWW page at
+ `http://www.cs.tu-bs.de/softech/ddd/'.
+
+ * DejaGnu (SrcCD)
+
+ DejaGnu is a framework to test programs with a single front end for all
+ tests. DejaGnu's flexibility & consistency makes it easy to write tests.
+ DejaGnu will also work with remote hosts and embedded systems.
+
+ DejaGnu comes with `expect', which runs scripts to conduct dialogs with
+ programs.
+
+ * Diffutils (SrcCD)
GNU `diff' compares files showing line-by-line changes in several
- flexible formats. It is much faster than traditional Unix versions. The
- Diffutils package contains `diff', `diff3', `sdiff', and `cmp'.
+ flexible formats. It is much faster than traditional Unix versions. The
+ Diffutils package has `diff', `diff3', `sdiff', & `cmp'. Future plans
+ include support for internationalization (e.g., error messages in
+ Chinese) & some non-Unix PC environments, & a library interface that can
+ be used by other free software.
- Recent Diffutils improvements include more consistent handling of
- character sets, and a new `diff' option to do all input/output in
- binary; this is useful on some non-Posix hosts.
+ * DJGPP *Also see "GCC" below* (BinCD)
- Plans for the Diffutils package include support for internationalization
- (e.g., error messages in Chinese), and for some non-Unix PC environments.
+ DJ Delorie has ported GCC/G++ to i386s running DOS. DJGPP has a 32-bit
+ i386 DOS extender with a symbolic debugger, development libraries, &
+ ports of Bison, `flex', & Binutils. Full source code is provided. It
+ needs at least 5MB of hard disk space to install & 512K of RAM to use.
+ It supports SVGA (up to 1024x768), XMS & VDISK memory allocation,
+ `himem.sys', VCPI (e.g., QEMM, DESQview, & 386MAX), & DPMI (e.g.,
+ Windows 3.x, OS/2, QEMM, & QDPMI). Version 2 was released in Feb. 1996,
+ & needs a DPMI environment; a free DPMI server is included.
- * DJGPP (BinCD, DjgppD, DosCD)
+ WWW at `http://www.delorie.com/djgpp/' or FTP from `ftp.simtel.net' in
+ `/pub/simtelnet/gnu/djgpp/' (or a SimTel mirror site).
- DJ Delorie has ported GCC/G++ 2.6.0 (see the GCC item in this section)
- to the i386 MS-DOS platform. The DJGPP package also contains a 32-bit
- 80386 DOS extender with symbolic debugger; development libraries; and
- ports of Bison, `flex', GAS, and the GNU Binutils. Full source code is
- provided. It requires at least 5MB of hard disk space to install and
- 512K of RAM to use. It supports SVGA (up to 1024x768), XMS & VDISK
- memory allocation, `himem.sys', VCPI (e.g., QEMM, DESQview, & 386MAX),
- and DPMI (e.g., Windows 3.x, OS/2, QEMM, & QDPMI). Ask
- `djgpp-request@sun.soe.clarkson.edu' to join a DJGPP users mailing list.
+ Ask `listserv@delorie.com', to join a DJGPP users mailing list.
- * `dld' (LangT, SrcCD)
+ * `dld' (SrcCD)
- `dld' is a dynamic linker written by W. Wilson Ho. Linking your program
+ `dld' is a dynamic linker written by W. Wilson Ho. Linking your program
with the `dld' library allows you to dynamically load object files into
- the running binary. Currently supported are VAX (Ultrix), Sun 3 (SunOS
- 3.4 & 4.0), SPARC (SunOS 4.0), Sequent Symmetry (Dynix), & Atari ST.
-
- * `doschk' (DjgppD, DosCD, SrcCD, UtilT)
-
- This program is intended as a utility to help software developers ensure
- that their source file names are distinguishable on System V platforms
- with 14-character filenames and on MS-DOS with 8+3 character filenames.
+ the running binary. `dld' supports a.out object types on the following
+ platforms: Convex C-Series (BSD), i386/i486/Pentium (GNU/Linux), Sequent
+ Symmetry i386 (Dynix 3), Sun-3 (SunOS 3 & 4), Sun-4 (SunOS 4), & VAX
+ (Ultrix).
- * `ecc' (SrcCD, UtilT)
+ * `doschk' (SrcCD)
- `ecc' is a Reed-Solomon error correction checking program, which can
- correct three byte errors in a block of 255 bytes and detect more severe
- errors. Contact `paulf@Stanford.EDU' for more information.
+ This program is a utility to help software developers ensure that their
+ source file names are distinguishable on System V platforms with
+ 14-character filenames and on MS-DOS systems with 8+3 character
+ filenames.
- * `ed' (SrcCD, UtilT)
+ * `ed' (SrcCD)
- Ed is the standard text editor.
+ `ed' is the standard text editor. It is line-oriented and can be used
+ interactively or in scripts.
- * Elib (LspEmcT, SrcCD)
+ * Elib (SrcCD)
Elib is a small library of Emacs Lisp functions, including routines for
using AVL trees and doubly-linked lists.
- * GNU Emacs
+ * Elisp archive (SrcCD)
+
+ This is a snapshot of Ohio State's GNU Emacs Lisp FTP Archive. FTP it
+ from `archive.cis.ohio-state.edu' in `/pub/gnu/emacs/elisp-archive'.
+
+ * Emacs *Also *note GNUs Flashes::.* [FSFman(s), FSFrc]
In 1975, Richard Stallman developed the first Emacs, an extensible,
- customizable real-time display editor and computing environment. GNU
- Emacs is his second implementation. It offers true Lisp--smoothly
- integrated into the editor--for writing extensions, and provides an
- interface to the X Window System. It also runs on MS-DOS and Windows
- NT. In addition to its powerful native command set, Emacs has
- extensions which emulate the editors vi and EDT (DEC's VMS editor).
- Emacs has many other features which make it a full computing support
- environment. Our long term plan is now to move it in the direction of a
- WYSIWYG word processor and make it easy for beginners to use. Source
- for the `GNU Emacs Manual', `Programming in Emacs Lisp, An
- Introduction', the `GNU Emacs Lisp Reference Manual', and a reference
- card come with the software. *Note Documentation::.
-
- * GNU Emacs 18 (EmcsD, LspEmcT, SrcCD, VMSEmcsT)
-
- GNU Emacs 18.59 is the last release of version 18 from the FSF. We are
- no longer maintaining it. It runs on many Unix systems. In hardware
- order: Alliant FX/80 & FX/2800, Altos 3068, Amdahl (UTS), Apollo, AT&T
- (3Bs & 7300 PC), DG Aviion, Bull DPX/2 (2nn & 3nn) CCI 5/32 & 6/32,
- Celerity, Convex, Digital (DECstation 3100 & 5000 (PMAXes), Mips, VAX
- (BSD, SysV & VMS)), Motorola Delta 147 & 187, Dual, Elxsi 6400, Encore
- (DPC, APC & XPC), Gould, HP (9000 series 200, 300, 700 & 800, but not
- 500), HLH Orion (original & 1/05), IBM (RS/6000 (AIX), RT/PC (4.2 & AIX)
- & PS/2 (AIX (386 only))), ISI (Optimum V, 80386), Intel 860 & 80386
- (BSD, Esix, SVR3, SVR4, SCO, ISC, IX, AIX & others), Iris (2500, 2500
- Turbo & 4D), Masscomp, MIPS, National Semiconductor 32000, NeXT (Mach),
- NCR Tower 32 (SVR2 & SVR3), Nixdorf Targon 31, Nu (TI & LMI), pfa50,
- Plexus, Prime EXL, Pyramid (original & MIPS), Sequent (Balance &
- Symmetry), SONY News (m68k & MIPS), Stride (system release 2), all Suns
- including 386i (all SunOS & some Solaris vers.), Tadpole, Tahoe, Tandem
- Integrity S2, Tektronix (16000 & 4300), Triton 88, Ustation E30 (SS5E),
- Whitechapel (MG1) & Wicat.
-
- In operating system order: AIX (RS/6000, RT/PC, 386-PS/2), BSD (vers.
- 4.1, 4.2, 4.3), DomainOS, Esix (386), HP-UX (HP 9000 series 200, 300,
- 700, 800 but not 500), ISC (386), IX (386), Mach, Microport, NewsOS
- (Sony m68k & MIPS) SCO (386), SVR0 (Vax, AT&T 3Bs), SVR2, SVR3, SVR4,
- Solaris 2.0, SunOS, UTS (Amdahl), Ultrix (vers. 3.0, 4,1), Uniplus 5.2
- (Dual machines), VMS (vers. 4.0, 4.2, 4.4, 5.5) & Xenix (386).
-
- * GNU Emacs 19 (DosCD, EmacsD, LspEmcT, SrcCD)
-
- Emacs 19 works with character-only terminals as well as with the X
- Window System (with or without the X toolkit); New features in Emacs 19
- include: multiple X windows ("frames" to Emacs), with either a separate
- X window for the minibuffer or a minibuffer attached to each X window;
- property lists associated with regions of text in a buffer; multiple
- fonts and colors defined by those properties; simplified and improved
- processing of function keys, mouse clicks and mouse movement; X
- selection processing, including clipboard selections; hooks to be run if
- point or mouse moves outside a certain range; menu bars and popup menus
- defined by keymaps; scrollbars; before and after change hooks;
- source-level debugging of Emacs Lisp programs; European character sets
- support; floating point numbers; improved buffer allocation, including
- returning storage to the system when a buffer is killed; interfacing
- with the X resource manager; GNU configuration scheme support; good RCS
- support; & many updated libraries.
-
- Recent features include support for Motif widgets as well as the Athena
- widgets, displaying multiple views of an outline at the same time,
- version control support for CVS and for multiple branches, ability to
- open frames on more than one X display from a single Emacs job,
- operation on MS-DOS and MS Windows, commands to edit text properties,
- text properties for formatting text, the ability to save text properties
- in files, & GNU-standard long named command line options.
-
- Emacs 19.29 is believed to work on, in hardware order: Acorn Risc
- machine (RISCiX); Alliant FX/2800 (BSD); Alpha (OSF/1); Apollo
- (DomainOS); Bull DPX/2 2nn & 3nn (SysV.3) & sps7 (SysV.2); Clipper;
- Convex (BSD); Cubix QBx (SysV); Data General Aviion (DGUX); DEC MIPS
- (Ultrix 4.2 & OSF/1, not VMS); Elxsi 6400 (SysV); Gould Power Node & NP1
- (4.2 & 4.3BSD); Harris Night Hawk 1200 and 3000, 4000 and 5000 (cxux);
- Honeywell XPS100 (SysV); HP 9000 series 200, 300, 700, 800 (but not 500)
- (4.3BSD or HP-UX 7, 8, 9); Intel i386, i486 and Pentium (386BSD, AIX,
- BSDI/386, FreeBSD, Esix, GNU/Linux, ISC, MS-DOS (*note MS-DOS
- Diskettes::. & *Note MS-DOS CD-ROM::), NetBSD, SCO3.2v4, SysV, Xenix,
- WindowsNT); IBM RS6000 (AIX 3.2); IBM RT/PC (AIX or BSD); Motorola Delta
- 147 & 187 (SysV.3, SysV.4, & m88kbcs); National Semiconductor 32K
- (Genix); NeXT (BSD or Mach 2 w/ NeXTStep 3.0); Paragon (OSF/1); Prime
- EXL (SysV); Pyramid (BSD); Sequent Symmetry (BSD, ptx); Siemens RM400
- and RM600 (SysV); SGI Iris 4D (Irix 4.x & 5.x); Sony News/RISC (NewsOS);
- Stardent i860 (SysV); Sun 3 & 4, SPARC 1, 1+, 2, 10 & Classic (SunOS
- 4.0, 4.1, Solaris 2.0-2.3); Tadpole 68k (SysV); Tektronix XD88 (SysV.3)
- & 4300 (BSD); & Titan P2 & P3 (SysV).
-
- In operating system order: AIX (i386, RS6000, RT/PC); 4.1, 4.2, 4.3BSD
- (i386, i860, Convex, Gould Power Node & NP1, HP9000 series 300, NeXT,
- Pyramid, Symmetry, Tektronix 4300, RT/PC); DG/UX (Aviion);
- DomainOS(Apollo); Esix (i386); FreeBSD (i386); Genix (ns32k); GNU/Linux
- (i386); HP-UX 7, 8, 9 (HP 9000 series 200, 300, 700, 800, but not 500);
- Irix 4 & 5 (Iris 4D); ISC (i386); Mach 2 & 3 (i386, NeXT); MS-DOS (*note
- MS-DOS Diskettes::. & *Note MS-DOS CD-ROM::); NetBSD (i386, HP9000
- series 300); OSF/1 (Alpha, Paragon); RISCiX (Acorn); SCO 3.2v4 (i386);
- SysV (Cubix QBx, Elxsi 6400, Honeywell XPS100, Intel i386, Prime EXL,
- Siemens RM400 and RM600, Stardent, Tadpole 68k, Titan P2 & P3); SysV.2
- (Bull sps7); SysV.3 (Bull DPX/2 2nn & 3nn, Motorola Delta 147 & 187,
- Tektronix XD88); SysV.4 (Motorola Delta 147 & 187, Stardent i860);
- Solaris 2 (SPARC 1, 1+, 2, 10, Classic); SunOS 4.0, 4.1 (Sun 3 & 4,
- SPARC 1, 1+, 2, 10 & Classic); Ultrix 4.2 (DEC MIPS); Windows NT; &
- Xenix (i386).
-
- Other configurations supported by Emacs 18 should work with few changes
- in Emacs 19; as users tell us more about their experiences with different
- systems, we will augment the list. Also see *Note Forthcoming GNUs::.
-
- * `es' (SrcCD, UtilT)
-
- `es' is an extensible shell based on `rc' with first class functions,
+ customizable real-time display editor & computing environment. GNU Emacs
+ is his second implementation. It offers true Lisp--smoothly integrated
+ into the editor--for writing extensions & provides an interface to the X
+ Window System. It runs on Unix, MS-DOS, & Windows NT or 95. In
+ addition to its powerful native command set, Emacs can emulate the
+ editors vi & EDT (DEC's VMS editor). Emacs has many other features which
+ make it a full computing support environment. Source for the `GNU Emacs
+ Manual' & a reference card comes with the software. Sources for the
+ `GNU Emacs Lisp Reference Manual', & `Programming in Emacs Lisp: An
+ Introduction' are distributed in separate packages. *Note
+ Documentation::.
+
+ * Emacs 20 (SrcCD) [FSFman(s), FSFrc]
+
+ Emacs 20.1 was just released recently. Its main new features include
+ support for many languages and many character codes (the MULE facility)
+ and a new convenient customization feature. The text-filling commands
+ handle indented and bulleted paragraphs conveniently; there are new help
+ facilities for looking up documentation about functions and symbols in
+ various languages. A new method of file-locking works even when using
+ NFS. Some dired commands have been made more systematic.
+
+ We believe Emacs 20 operates on the same systems as Emacs 19, but we do
+ not have confirmation for all of them.
+
+ * Emacs 19 (SrcCD) [FSFman(s), FSFrc]
+
+ Emacs 19 works with character-only terminals & with the X Window System
+ (with or without an X toolkit). It also runs on MS-DOS, MS Windows, and
+ with multiple-window support on MS Windows 95/NT.
+
+ Emacs 19 works on: Acorn RISC (RISCiX); Alliant FX/2800 (BSD); Alpha
+ (OSF/1 or GNU/Linux); Apollo (DomainOS); Bull DPX/2 2nn & 3nn (SysV.3) &
+ sps7 (SysV.2); Clipper; Convex (BSD); Cubix QBx (SysV); Data General
+ Aviion (DGUX); DEC MIPS (Ultrix 4.2, OSF/1, not VMS); Elxsi 6400 (SysV);
+ Gould Power Node & NP1 (4.2 & 4.3BSD); Harris Night Hawk 1200, 3000,
+ 4000 & 5000 (cxux); Harris Night Hawk Power PC (powerunix); Honeywell
+ XPS100 (SysV); HP 9000 series 200, 300, 700, 800 (but not 500) (4.3BSD;
+ HP-UX 7, 8, 9; NextStep); Intel i386/i486/Pentium (GNU/Hurd, GNU/Linux,
+ 386BSD, AIX, BSDI/386, FreeBSD, Esix, ISC, MS-DOS, NetBSD, SCO3.2v4,
+ Solaris, SysV, Xenix, WindowsNT, Windows95); IBM RS/6000 (AIX 3.2) &
+ RT/PC (AIX, BSD); Motorola Delta 147 & 187 (SysV.3, SysV.4, m88kbcs);
+ National Semiconductor 32K (Genix); NeXT (BSD, Mach 2 w/ NeXTStep 3.0);
+ Paragon (OSF/1); Prime EXL (SysV); Pyramid (BSD); Sequent Symmetry (BSD,
+ ptx); Siemens RM400 & RM600 (SysV); SGI Iris 4D (Irix 4.x & 5.x); Sony
+ News/RISC (NewsOS); Stardent i860 (SysV); Sun 3 & 4, SPARC 1, 1+, 2, 10,
+ Classic (SunOS 4.0, 4.1, Solaris 2.0-2.3); Tadpole 68k (SysV); Tektronix
+ XD88 (SysV.3) & 4300 (BSD); & Titan P2 & P3 (SysV).
+
+ * Emacs 18 (SrcCD) [FSFrc]
+
+ Emacs 18 is several years old. We no longer maintain it, but still
+ distribute it for those using platforms which Emacs 19 does not support.
+
+ * `enscript' (SrcCD)
+
+ `enscript' is an upwardly-compatible replacement for the Adobe
+ `enscript' program. It formats ASCII files (outputting in Postscript)
+ and stores generated output to a file or sends it directly to the
+ printer.
+
+ * `es' (SrcCD)
+
+ `es' is an extensible shell (based on `rc') with first-class functions,
lexical scope, exceptions, and rich return values (i.e., functions can
return values other than just numbers). `es''s extensibility comes from
- the ability to modify and extend the shell's builtin services, such as
+ the ability to modify and extend the shell's built-in services, such as
path searching and redirection. Like `rc', it is great for both
- interactive use and for scripting, particularly since its quoting rules
- are much less baroque than the C or Bourne shells.
+ interactive use and scripting, particularly since its quoting rules are
+ much less baroque than the C and Bourne shells.
+
+ * Exim (SrcCD)
+
+ Exim is a new Internet mail transfer agent, similar in style to Smail 3.
+ It can handle relatively high volume mail systems, header rewriting,
+ control over which hosts/nets may use it as a relay, blocking of
+ unwanted mail from specified hosts/nets/senders, and multiple local
+ domains on one mail host ("virtual domains") with several options for
+ the way these are handled.
- * `f2c' (LangT, SrcCD)
+ * `f2c' *Also see "Fortran" below & in *Note Forthcoming GNUs::.*
+ (SrcCD)
- `f2c' converts Fortran-77 source files into C or C++, which can be
- compiled with GCC. You can get bug fixes by FTP from site
- `netlib.att.com' or by email from `netlib@research.att.com'. The fixes
- are summarized in the file `/netlib/f2c/changes.Z'. *Note Forthcoming
- GNUs::, for information about GNU Fortran.
+ `f2c' converts Fortran-77 source into C or C++, which can be compiled
+ with GCC or G++. Get bug fixes by FTP from site `netlib.bell-labs.com'
+ or by email from `netlib@netlib.bell-labs.com'. For a summary, see the
+ file `/netlib/f2c/readme.gz'.
- * Fileutils (DjgppD, DosCD, SrcCD, UtilD, UtilT)
+ * `ffcall' (SrcCD)
- The fileutils work on files: `chgrp', `chmod', `chown', `cp', `dd', `df',
- `dir', `du', `install', `ln', `ls', `mkdir', `mkfifo', `mknod', `mv',
- `mvdir', `rm', `rmdir', `sync', `touch', & `vdir'. Only some of these
- are on the *Note Selected Utilities Diskettes::.
+ `ffcall' is a C library for implementing foreign function calls in
+ embedded interpreters by Bill Triggs and Bruno Haible. It allows C
+ functions with arbitrary argument lists and return types to be called or
+ emulated (callbacks).
- * Findutils (DjgppD, DosCD, SrcCD, UtilD, UtilT)
+ * Fileutils (SrcCD)
+
+ The Fileutils are: `chgrp', `chmod', `chown', `cp', `dd', `df', `dir',
+ `dircolors', `du', `install', `ln', `ls', `mkdir', `mkfifo', `mknod',
+ `mv', `rm', `rmdir', `sync', `touch', & `vdir'.
+
+ * Findutils (SrcCD)
`find' is frequently used both interactively and in shell scripts to
find files which match certain criteria and perform arbitrary operations
- on them. Also included are `xargs', which applies a command to a list
- of files, and `locate', which scans a database for file names that match
- a pattern.
+ on them. Also included are `locate', which scans a database for file
+ names that match a pattern, and `xargs', which applies a command to a
+ list of files.
- * Finger (SrcCD, UtilT)
+ * Finger (SrcCD)
GNU Finger has more features than other finger programs. For sites with
- many hosts, a single host may be designated as the finger "server" host,
+ many hosts, a single host may be designated as the finger "server" host
and other hosts at that site configured as finger "clients". The server
- host collects information about who is logged in to the clients. To
- finger a user at a GNU Finger site, a query to any its client hosts gets
- useful information. GNU Finger supports many customization features,
- including user output filters, and site programmable output for special
- target names.
+ host collects information about who is logged in on the clients. To
+ finger a user at a GNU Finger site, a query to any of its client hosts
+ gets useful information. GNU Finger supports many customization
+ features, including user output filters and site-programmable output for
+ special target names.
- * `flex' (DjgppD, DosCD, LangT, SrcCD, UtilD)
+ * `flex' (BinCD, SrcCD) [FSFman, FSFrc]
`flex' is a replacement for the `lex' scanner generator. `flex' was
written by Vern Paxson of the Lawrence Berkeley Laboratory and generates
- far more efficient scanners than `lex' does. Source for the `Flex
- Manual' and reference card are included. *Note Documentation::.
-
- * FlexFAX (UtilT)
+ far more efficient scanners than `lex' does. Sources for the `Flex
+ Manual' and reference card are included (*note Documentation::.).
- FlexFAX is now called HylaFAX. For more information, *Note GNU
- Software::.
+ * Fontutils (SrcCD)
- * Fontutils (SrcCD, UtilT)
+ The Fontutils convert between font formats, create fonts for use with
+ Ghostscript or TeX (starting with a scanned type image & converting the
+ bitmaps to outlines), etc. It includes: `bpltobzr', `bzrto',
+ `charspace', `fontconvert', `gsrenderfont', `imageto', `imgrotate',
+ `limn', & `xbfe'.
- The fontutils create fonts for use with Ghostscript or TeX, starting
- with a scanned type image and converting the bitmaps to outlines. They
- also contain general conversion programs and other utilities.
+ * Fortran (`g77') *Also *note Forthcoming GNUs::.* (BinCD, SrcCD)
- Fontutils programs include: `bpltobzr', `bzrto', `charspace',
- `fontconvert', `gsrenderfont', `imageto', `imgrotate', `limn', and
- `xbfe'.
+ GNU Fortran (`g77'), developed by Craig Burley, is available for public
+ beta testing on the Internet. For now, `g77' produces code that is
+ mostly object-compatible with `f2c' & uses the same run-time library
+ (`libf2c').
- * GAWK (DjgppD, DosCD, LangT, SrcCD)
+ * `gawk' (SrcCD) [FSFman]
- GAWK is upwardly compatible with the latest POSIX specification of
+ `gawk' is upwardly compatible with the latest POSIX specification of
`awk'. It also provides several useful extensions not found in other
- `awk' implementations. Texinfo source for the `GAWK Manual' comes with
- the software. *Note Documentation::.
-
- * GCC (BinCD, DjgppD, DosCD, LangT, SrcCD, VMSCompT)
-
- Version 2 of the GNU C Compiler supports multiple languages; the source
- file name suffix or a compiler option selects the language. The GNU C
- Compiler distribution includes support for C, C++ and Objective-C.
- Support for Objective-C was donated by NeXT. The runtime support needed
- to run Objective-C programs is now distributed with GCC (this does not
- include any Objective-C classes aside from `object'). As much as
- possible, G++ is kept compatible with the evolving draft ANSI standard,
- but not with `cfront' (AT&T's compiler), which has been diverging from
- ANSI.
-
- The GNU C Compiler is a fairly portable optimizing compiler which
- performs automatic register allocation, common sub-expression
- elimination, invariant code motion from loops, induction variable
- optimizations, constant propagation and copy propagation, delayed
- popping of function call arguments, tail recursion elimination,
- integration of inline functions and frame pointer elimination,
+ `awk' implementations. Texinfo source for the `The GNU Awk User's
+ Guide' comes with the software (*note Documentation::.).
+
+ * `gcal' (SrcCD)
+
+ `gcal' is a program for printing calendars. It displays different
+ styled calendar sheets, eternal holiday lists, and fixed date warning
+ lists.
+
+ * GCC (BinCD, SrcCD) [FSFman]
+
+ Version 2 of the GNU C Compiler supports the languages C, C++, and
+ Objective-C; the source file name suffix or a compiler option selects
+ the language. (Also see "GNAT" later in this article for Ada language
+ supports.) Objective-C support was donated by NeXT. The runtime support
+ needed to run Objective-C programs is now distributed with GCC. (This
+ does not include any Objective-C classes aside from `object', but see
+ "GNUstep" in *Note Forthcoming GNUs::.) G++ seeks to be compliant with
+ the ANSI C++ language standard. See
+ `http://www.cygnus.com/misc/wp/index.html' for the latest draft.
+
+ GCC is a fairly portable optimizing compiler which performs many
+ optimizations. They include: automatic register allocation, common
+ sub-expression elimination (CSE) (including a certain amount of CSE
+ between basic blocks - though not all the supported machine descriptions
+ provide for scheduling or delay slots), invariant code motion from
+ loops, induction variable optimizations, constant propagation, copy
+ propagation, delayed popping of function call arguments, tail recursion
+ elimination, integration of inline functions & frame pointer elimination,
instruction scheduling, loop unrolling, filling of delay slots, leaf
- function optimization, optimized multiplication by constants, a certain
- amount of common subexpression elimination (CSE) between basic blocks
- (though not all of the supported machine descriptions provide for
- scheduling or delay slots), a feature for assigning attributes to
- instructions, and many local optimizations that are automatically
- deduced from the machine description. Position-independent code is
- supported on the 68k, i386, i486, Pentium, Hitachi Slt, Hitachi H8/300,
- Clipper, 88k, SPARC & SPARClite.
+ function optimization, optimized multiplication by constants, the
+ ability to assign attributes to instructions, & many local optimizations
+ automatically deduced from the machine description.
GCC can open-code most arithmetic on 64-bit values (type `long long
int'). It supports extended floating point (type `long double') on the
- 68k; other machines will follow.
+ 68k; other machines will follow. GCC supports full ANSI C, traditional
+ C, & GNU C extensions (including: nested functions support, nonlocal
+ gotos, & taking the address of a label).
- GCC supports full ANSI C, traditional C & GNU C extensions (including:
- nested functions support, nonlocal gotos & taking the address of a
- label).
-
- GCC can generate a.out, COFF, ELF & OSF-Rose files when used with a
+ GCC can generate a.out, COFF, ELF, & OSF-Rose files when used with a
suitable assembler. It can produce debugging information in these
- formats: BSD stabs, COFF, ECOFF, ECOFF with stabs & DWARF.
+ formats: BSD stabs, COFF, ECOFF, ECOFF with stabs, & DWARF.
+
+ GCC generates code for many CPUs, including the a29k, Alpha, ARM, AT&T,
+ DSP1610, Clipper, Convex cN, Elxsi, Fujitsu Gmicro, i370, i860, i960,
+ MIL-STD-1750a, MIPS, ns32k, PDP-11, Pyramid, ROMP, RS/6000, SH, SPUR,
+ Tahoe, VAX, & we32k.
- GCC generates code for many CPUs, including: a29k, Alpha, ARM, AT&T
- DSP1610, Convex cN, Clipper, Elxsi, Fujitsu Gmicro, H8/300, HP-PA (1.0
- and 1.1) i370, i386, i486, Pentium, i860, i960, m68k, m68020, m68030,
- m68040, m88k, MIL-STD-1750a, MIPS, ns32k, PDP-11, Pyramid, ROMP, RS6000,
- SH, SPARC, SPARClite, VAX, & we32k.
+ Position-independent code is generated for the Clipper, Hitachi H8/300,
+ HP-PA (1.0 & 1.1), i386/i486/Pentium, m68k, m88k, SPARC, & SPARClite.
- Operating systems supported include: AIX, ACIS, AOS, BSD, Clix, Ctix,
- DG/UX, Dynix, Genix, GNU, HP-UX, ISC, Irix, GNU/Linux, Luna, LynxOS,
- Mach, Minix, NetBSD, NewsOS, OSF, OSF-Rose, RISCOS, SCO, Solaris 2,
- SunOS 4, SysV, Ultrix, Unos, VMS & Windows/NT.
+ Operating systems supported include: GNU/Hurd, GNU/Linux, ACIS, AIX, AOS,
+ BSD, Clix, Concentrix, Ctix, DG/UX, Dynix, FreeBSD, Genix, HP-UX, Irix,
+ ISC, Luna, LynxOS, Minix, NetBSD, NewsOS, NeXTStep, OS/2, OSF, OSF-Rose,
+ RISCOS, SCO, Solaris 2, SunOS 4, System/370, SysV, Ultrix, Unos, VMS, &
+ Windows/NT.
Using the configuration scheme for GCC, building a cross-compiler is as
easy as building a native compiler.
- We no longer maintain version 1 of GCC, G++, or libg++.
-
- Texinfo source for the `Using and Porting GNU CC' manual, is included
- with GCC. *Note Forthcoming GNUs::, for plans for later releases of
- GCC.
+ Texinfo source for the `Using and Porting GNU CC' manual is included
+ with GCC (*note Documentation::.).
- * GDB (BinCD, DjgppD, DosCD, LangT, SrcCD)
+ * GDB (BinCD, SrcCD) [FSFman, FSFrc]
- GDB, the GNU DeBugger, is a source-level debugger which supports C, C++,
- and Fortran.
+ GDB, the GNU DeBugger, is a source-level debugger for C, C++, & Fortran.
+ It provides partial support for Modula-2 & Chill.
- GDB can debug both C and C++ programs, and will work with executables
- produced by many different compilers; however, C++ debugging will have
- some limitations if you do not use GCC.
+ GDB can debug both C & C++, & will work with executables made by many
+ different compilers; but, C++ debugging will have some limitations if
+ you do not use GCC.
- GDB has a command line user interface; GNU Emacs comes with a GDB mode,
- and `xxgdb' provides an X interface (but it is not distributed or
- maintained by the FSF; FTP it from `ftp.x.org' in the
- `/contrib/utilities' directory).
+ GDB has a command line user interface, and Emacs has GDB mode as an
+ interface. Two X interfaces (not distributed or maintained by the FSF)
+ are: `gdbtk' (FTP it from `ftp.cygnus.com' in directory `/pub/gdb'); and
+ `xxgdb' (FTP it from `ftp.x.org' in directory `/contrib/utilities').
Executable files and symbol tables are read via the BFD library, which
allows a single copy of GDB to debug programs with multiple object file
- formats (e.g., a.out, COFF, ELF). Other features include a rich command
+ formats (e.g., a.out, COFF, ELF). Other features include a rich command
language, remote debugging over serial lines or TCP/IP, and watchpoints
(breakpoints triggered when the value of an expression changes).
- GDB defines a standard interface for simulators, and the included
- simulator library includes simulators for the Zilog Z8001/2, Hitachi
- H8/300, H8/500 & Super-H.
+ GDB uses a standard remote interface to a simulator library which
+ includes simulators for the ARM, Hitachi H8/300, Hitachi SH, & PowerPC.
GDB can perform cross-debugging. To say that GDB "targets" a platform
- means that it can perform native or cross-debugging for it. To say that
- GDB can "host" a given platform means that it can be built on it, but
- cannot necessarily debug native programs. GDB can:
-
- * "target" & "host": Amiga 3000 (Amix), DEC Alpha (OSF/1), DECstation
- 3100 & 5000 (Ultrix), HP 9000/300 (BSD, HP-UX), HP 9000/700 (HP-UX),
- i386 (BSD, FreeBSD, GNU/Linux, LynxOS, NetBSD, SCO), IBM RS/6000
- (AIX, LynxOS), Motorola Delta m88k (System V, CX/UX), PC532
- (NetBSD), Motorola m68k MVME-167 (LynxOS), NCR 3000 (SVR4), SGI
- (Irix V3, V4, V5), SONY News (NewsOS 3.x), SPARC (SunOS 4.1,
- Solaris, NetBSD, LynxOS) Sun-3 (SunOS 4.1), & Ultracomputer (a29k
- running Sym1).
-
- * "target", but not "host": AMD 29000 (COFF & a.out), Hitachi H8/300,
- Hitachi SH, i386 (a.out, COFF, OS/9000) i960 (Nindy, VxWorks),
- m68k/m68332 (a.out, COFF, VxWorks), MIPS (IDT ecoff, ELF), Fujitsu
- SPARClite (a.out, COFF), & Z8000.
-
- * "host", but not "target": IBM RT/PC (AIX), and HP/Apollo 68k (BSD).
-
- GDB can use the symbol tables emitted by the vendor-supplied compilers of
- most MIPS-based machines, including DEC. (These tables are in a format
- which almost nobody else uses.) Source for the manual
- `Debugging with GDB' and a reference card are included. *Note
- Documentation::.
-
- * `gdbm' (LangT, SrcCD, UtilD)
+ means it can perform native or cross-debugging for it. To say that GDB
+ can "host" a given platform means that it can be built on it, but cannot
+ necessarily debug native programs.
+
+ GDB can:
+
+ * "target" & "host": Amiga 3000 (AmigaOS, Amix, NetBSD), DEC Alpha
+ (OSF/1), DECstation 3100 & 5000 (Ultrix), HP 9000/300 (BSD, HP-UX),
+ HP 9000/700 (HP-UX 9, 10), i386/i486/Pentium (GNU/Hurd, GNU/Linux,
+ BSD, FreeBSD, LynxOS, NetBSD, SCO, Windows NT), IBM RS/6000 (AIX
+ 3.x, AIX 4.x, LynxOS), Motorola Delta m88k (System V, CX/UX),
+ Motorola m68k MVME-167 (LynxOS), NCR 3000 (SVR4), PC532 (NetBSD),
+ PowerPC (AIX 4.x, MacOS, Windows NT), SGI (Irix V3, V4, V5), SONY
+ News (NewsOS 3.x), SPARC (LynxOS, NetBSD, Solaris 2.x, & SunOS 4.1),
+ & Sun-3 (SunOS 4.1).
+
+ * "target", but not "host": AMD 29000, ARM (RDP), Fujitsu SPARClite,
+ Hitachi H8/300, Hitachi SH (CMON, SH3, E7000), HP PA Pro (Winbond,
+ Oki), i960 (MON960, Nindy, VxWorks), m68k/m68332 (CPU32BUG, EST,
+ ROM68K, VxWorks), Matra Sparclet, MIPS (IDT, PMON, VxWorks),
+ PowerPC (PPCBug), & Z8000.
+
+ * "host", but not "target": HP/Apollo 68k (BSD), IBM RT/PC (AIX), &
+ m68k Apple Macintosh (MacOS). Sources for the manual,
+ `Debugging with GDB', and a reference card are included (*note
+ Documentation::.).
+
+ * `gdbm' (SrcCD)
`gdbm' is the GNU replacement for the traditional `dbm' and `ndbm'
- libraries. It implements a database using quick lookup by hashing.
+ libraries. It implements a database using quick lookup by hashing.
`gdbm' does not ordinarily make sparse files (unlike its Unix and BSD
counterparts).
- * Ghostscript (DjgppD, DosCD, SrcCD, UtilT)
-
- GNU Ghostscript is the GNU release of Ghostscript, which is an
- interpreter for the Postscript graphics language (*note Forthcoming
- GNUs::., for news on future plans).
-
- The current version of GNU Ghostscript is 2.6.2. Features include the
- ability to use the fonts provided by the platform on which Ghostscript
- runs (X Window System and Microsoft Windows), resulting in much
- better-looking screen displays; improved text file printing (like
- `enscript'); a utility to extract the text from a Postscript language
- document; a much more reliable (and faster) Microsoft Windows
- implementation; support for Microsoft C/C++ 7.0; drivers for many new
- printers, including the SPARCprinter, and for TIFF/F (fax) file format;
- many more Postscript Level 2 facilities, including most of the color
- space facilities (but not patterns), and the ability to switch between
- Level 1 and Level 2 dynamically. Version 2.6.2 adds a LaserJet 4 driver
- and several important bug fixes to version 2.6.1.
-
- Ghostscript executes commands in the Postscript language by writing
- directly to a printer, drawing on an X window, or writing to a file for
- later printing (or to a bitmap file that you can manipulate with other
- graphics programs).
+ * Generic NQS (SrcCD)
+
+ Generic NQS is a network queuing system for spreading batch jobs across a
+ network of machines. It is designed to be simple to install on a
+ heterogeneous network of machines, and has optimizations for running on
+ the high end, symmetric multiprocessing servers that are currently on the
+ market. It is available for many more Unix variants than any other
+ comparable product, and inter-operates with other NQS systems, including
+ Cray's NQE.
+
+ * `geomview' *See* `http://www.geom.umn.edu/software/geomview' (SrcCD)
+
+ `geomview' is an interactive geometry viewing program, for Unix systems
+ with Motif, using X, GL, or OpenGL graphics. It allows multiple
+ independently controllable objects and cameras. External programs may
+ drive desired aspects of the viewer, e.g. loading changing geometry or
+ controlling motion, while allowing interactive mouse-and-GUI control of
+ everything else. Controllable features include motion, appearance
+ (wireframe, shading, lighting and material properties), mouse-based
+ selection, snapshoting (PPM or SGI image, Postscript, and RenderMan
+ formats), display in hyperbolic and spherical spaces, and projection
+ from higher dimensions. Includes converters to display Mathematica and
+ Maple 3-D graphics, and limited conversion to/from VRML.
+
+ * `gettext' *Also *note Help the Translation Project::.* (SrcCD)
+
+ The GNU `gettext' tool set has everything maintainers need to
+ internationalize a package's user messages. Once a package has been
+ internationalized, `gettext''s many tools help translators localize
+ messages to their native language and automate handling the translation
+ files.
+
+ * `gforth' (SrcCD)
+
+ `gforth' is a fast, portable implementation of the ANS Forth language.
+
+ * Ghostscript (SrcCD)
+
+ Ghostscript is an interpreter for the Postscript and PDF graphics
+ languages.
+
+ The current version of GNU Ghostscript, 3.53, includes a Postscript
+ Level 2 interpreter and a PDF 1.1 interpreter (except for encryption).
+ Significant new features include the ability to convert PDF to
+ Postscript.
+
+ Ghostscript executes commands in the Postscript and PDF languages by
+ writing directly to a printer, drawing on an X window, or writing to
+ files for printing later or manipulating with other graphics programs.
Ghostscript includes a C-callable graphics library (for client programs
- that do not want to deal with the Postscript language). It also supports
- IBM PCs and compatibles with EGA, VGA, or SuperVGA graphics (but please
- do *not* ask the FSF staff any questions about this; we do not use PCs).
+ that do not want to deal with the Postscript language). It also runs on
+ MS-DOS, MS Windows, OS/2, OpenVMS, and Mac OS (native on both 68K and
+ PowerPC) (but please do *not* ask the FSF staff any questions about this;
+ we do not use these operating systems).
+
+ * Ghostview (SrcCD)
+
+ Tim Theisen, `ghostview@cs.wisc.edu', created Ghostview, a previewer for
+ multi-page files with an X Window interface. Ghostview & Ghostscript
+ work together; Ghostview creates a viewing window & Ghostscript draws in
+ it.
+
+ * GIT (SrcCD)
+
+ The GNU Interactive Tools package includes: an extensible file system
+ browser, an ASCII/hex file viewer, a process viewer/killer, & other
+ related utilities & shell scripts. It can be used to increase the speed
+ & efficiency of many daily tasks, such as copying & moving files &
+ directories, invoking editors, compressing/uncompressing files, creating
+ & expanding archives, compiling programs, sending mail, etc. It looks
+ nice, has colors (if the standard ANSI color sequences are supported), &
+ is user-friendly.
+
+ * `gmp' (SrcCD)
- * Ghostview (SrcCD, UtilT)
+ GNU `mp' is a library for arithmetic on arbitrary precision integers,
+ rational numbers, and floating-point numbers. It has a rich set of
+ functions with a regular interface.
- Tim Theisen, `ghostview@cs.wisc.edu', has created Ghostview, a previewer
- for multi-page files with an X11 user interface. Ghostview and
- Ghostscript function as two cooperating programs; Ghostview creates a
- viewing window and Ghostscript draws in it.
+ A major new release, version 2, came out in Spring '96. Compared to
+ previous versions, it is much faster, contains lots of new functions, &
+ has support for arbitrary precision floating-point numbers.
- * `gmp' (LangT, SrcCD)
+ * GN (SrcCD)
- GNU mp is a library for arbitrary precision arithmetic on signed integers
- and rational numbers. It has a rich set of functions with a regular
- interface.
+ GN is a gopher/HTTP server.
- * GNATS (SrcCD, UtilT)
+ * Gnans (SrcCD)
- GNATS (GNats: A Tracking System, not to be confused with GNAT, The GNU
- Ada Translator) is a bug-tracking system. It is based upon the paradigm
- of a central site or organization which receives problem reports and
- negotiates their resolution by electronic mail. Although it has been
- used primarily as a software bug-tracking system so far, it is
- sufficiently generalized so that it could be used for handling system
- administration issues, project management or any number of other
+ Gnans is a program (and language) for the numerical study of
+ deterministic and stochastic dynamical systems. The dynamical systems
+ may evolve in continuous or discrete time. Gnans has graphical &
+ command line interfaces.
+
+ * GNAT: The GNU Ada Translator (SrcCD)
+
+ GNAT, a front end for the entire Ada 95 language, including all special
+ needs annexes, is available via anonymous FTP from `cs.nyu.edu' and
+ various mirror sites in `/pub/gnat'. SGI, DEC, and Siemens Nixdorf have
+ chosen GNU Ada 95 as the Ada compiler for some of their systems. GNAT
+ is maintained by Ada Core Technologies. For more information, see
+ `http://www.gnat.com'.
+
+ * GNATS (SrcCD)
+
+ GNATS, GNats: A Tracking System, is a bug-tracking system. It is based
+ upon the paradigm of a central site or organization which receives
+ problem reports and negotiates their resolution by electronic mail.
+ Although it has been used primarily as a software bug-tracking system so
+ far, it is sufficiently generalized that it could be used for handling
+ system administration issues, project management, or any number of other
applications.
- * `gnuplot' (SrcCD, UtilT, WdwsD)
+ * GnuGo (SrcCD)
- `gnuplot' is an interactive program for plotting mathematical
- expressions and data. It handles both curves (2 dimensions) and surfaces
- (3 dimensions). Curiously, the program was neither written nor named for
- the GNU Project; the name is a coincidence. Various GNU programs use
- `gnuplot' to produce graphical output.
+ GnuGo plays the game of Go. It is not yet very sophisticated.
+
+ * GNUMATH (`gnussl') (SrcCD)
- * GnuGo (SrcCD, UtilT)
+ GNUMATH is a library (`gnussl') that simplifies scientific programming
+ in C & C++. Its focus is on problems that can be solved by a
+ straight-forward application of numerical linear algebra. It also
+ handles plotting. It is in beta release; it is expected to grow more
+ versatile & offer a wider scope in time.
- GnuGo plays the game of Go (Wei-Chi); it is not yet very sophisticated.
+ * `gnuplot' (SrcCD)
- * `gperf' (LangT, SrcCD)
+ `gnuplot' is an interactive program for plotting mathematical
+ expressions and data. It plots both curves (2 dimensions) & surfaces (3
+ dimensions). It was neither written nor named for the GNU Project; the
+ name is a coincidence. Various GNU programs use `gnuplot'.
- `gperf' generates perfect hash tables. There are two implementations of
- `gperf', written in C and C++. Both produce hash functions in either C
- or C++.
+ * `gnuserv' (SrcCD)
- * GNU Graphics (SrcCD, UtilT)
+ `gnuserv' is an enhanced version of Emacs' `emacsclient' program. It
+ lets the user direct a running Emacs to edit files or evaluate arbitrary
+ Emacs Lisp constructs from another process.
- GNU Graphics is a system which produces x-y plots from ASCII or binary
- data. It supports output in Postscript, Tektronix 4010 compatible and
- Unix device-independent "plot" formats as well as a previewer for the X
- Window System. Features include a `spline' interpolation program;
- examples of shell scripts using `graph' and `plot'; and a statistics
- toolkit; and output in TekniCAD TDA and ln03 file formats. Email bugs or
- questions to Rich Murphey, `Rich@lamprey.utmb.edu'.
+ * `gpc' *Also *note GNUs Flashes::.* (SrcCD)
- * grep (DjgppD, DosCD, SrcCD, UtilD, UtilT)
+ `gpc' is the GNU Pascal Compiler.
- This package has GNU `grep', `egrep', and `fgrep' which find lines that
- match inputed patterns. They are much faster than the traditional Unix
- versions.
+ * grep (SrcCD)
- * Groff (DjgppD, DosCD, SrcCD, UtilT)
+ This package has GNU `grep', `egrep', and `fgrep', which find lines that
+ match entered patterns. They are much faster than the traditional Unix
+ versions.
- Groff is a document formatting system based on an implementation of
- device-independent troff, which also includes implementations of `eqn',
- `nroff', `pic', `refer', `tbl', `troff', and the `man', `ms', and `mm'
- macros, as well as drivers for Postscript, TeX `dvi' format, and
- typewriter-like devices.
+ * Groff (SrcCD)
- Groff's `mm' macro package is almost compatible with the DWB `mm' macros
- and has several extensions. Also included is a modified version of the
- Berkeley `me' macros and an enhanced version of the X11 `xditview'
- previewer. Written in C++, these programs can be compiled with GNU C++
- Version 2.5 or later. A driver for the LaserJet 4 series of printers is
- currently in test.
+ Groff is a document formatting system based on a device-independent
+ version of `troff', & includes: `eqn', `nroff', `pic', `refer', `tbl',
+ `troff'; the `man', `ms', & `mm' macros; & drivers for Postscript, TeX
+ `dvi' format, the LaserJet 4 series of printers, and typewriter-like
+ devices. Groff's `mm' macro package is almost compatible with the DWB
+ `mm' macros with several extensions. Also included is a modified
+ version of the Berkeley `me' macros and an enhanced version of the X11
+ `xditview' previewer. Written in C++, these programs can be compiled
+ with GNU C++ Version 2.7.2 or later.
Groff users are encouraged to contribute enhancements. Most needed are
complete Texinfo documentation, a `grap' emulation (a `pic' preprocessor
for typesetting graphs), a page-makeup postprocessor similar to `pm'
(see `Computing Systems', Vol. 2, No. 2; ask `office@usenix.org' how to
- get a copy) and an ASCII output class for `pic' so that `pic' can be
- integrated with Texinfo. Questions and bug reports from users who have
- read the documentation provided with groff can be sent to
+ get a copy), and an ASCII output class for `pic' to integrate `pic' with
+ Texinfo. Questions and bug reports from users who have read the
+ documentation provided with Groff can be sent to
`bug-groff@prep.ai.mit.edu'.
- * `gzip' (DjgppD, DosCD, LangT, LspEmcT, SrcCD, UtilT)
+ * `guavac' (SrcCD)
+
+ `guavac' is a new free compiler for the Java language.
+
+ * GUILE *Also *note GNUs Flashes::.* (SrcCD)
+
+ GUILE is GNU's Ubiquitous Intelligent Language for Extension, an
+ interpreter for the Scheme programming language, packaged as a library
+ that you can link into your programs to make them extensible.
- Some of the contents of our tape and FTP distributions are compressed.
- We have software on our tapes and FTP sites to uncompress these files.
- Due to patent troubles with `compress', we use another compression
- program, `gzip'. (Such prohibitions on software development are fought
- by the League for Programming Freedom, *note What Is the LPF::., for
- details.) `gzip' can expand LZW-compressed files but uses another,
- unpatented algorithm for compression which generally produces better
- results. It also expands files compressed with System V's `pack'
- program.
+ * `gzip' (BinCD, SrcCD)
- * `hello' (DjgppD, DosCD, SrcCD, UtilT)
+ `gzip' can expand LZW-compressed files but uses another, unpatented
+ algorithm for compression which generally produces better results. It
+ also expands files compressed with System V's `pack' program.
+
+ * `hello' (SrcCD)
The GNU `hello' program produces a familiar, friendly greeting. It
allows non-programmers to use a classic computer science tool which would
- otherwise be unavailable to them. Because it is protected by the GNU
- General Public License, users are free to share and change it.
-
+ otherwise be unavailable to them. Because it is protected by the GNU
+ General Public License, users are free to share and change it. `hello'
+ is also a good example of a program that meets the GNU coding standards.
Like any truly useful program, `hello' contains a built-in mail reader.
- * `hp2xx' (SrcCD, UtilT)
+ * `hp2xx' (SrcCD)
GNU `hp2xx' reads HP-GL files, decomposes all drawing commands into
elementary vectors, and converts them into a variety of vector and raster
output formats. It is also an HP-GL previewer. Currently supported
- vector formats include encapsulated Postscript, Uniplex RGIP, Metafont
- and various special TeX-related formats, and simplified HP-GL (line
- drawing only) for imports. Raster formats supported include IMG, PBM,
- PCX, & HP-PCL (including Deskjet & DJ5xxC support). Previewers work
- under X11 (Unix), OS/2 (PM & full screen), MS-DOS (SVGA, VGA, & HGC).
-
- * HylaFAX (UtilT)
-
- HylaFAX is a facsimile system for Unix systems. It supports sending,
- receiving, and polled retrieval of facsimile, as well as transparent
- shared data use of the modem. Information is also available on the
- World Wide Web at URL: `http://www.vix.com/hylafax/'.
-
- * `indent' (DjgppD, DosCD, SrcCD, UtilD, UtilT)
-
- GNU `indent' is a revision of the BSD version. By default, it formats C
- source according to the GNU coding standards. The BSD default, K&R and
- other formats are available as options. It is also possible to define
- your own format. GNU `indent' is more robust and provides more
- functionality than other versions, e.g., it handles C++ comments.
-
- * Ispell (DjgppD, DosCD, SrcCD, UtilT)
-
- Ispell is an interactive spell checker that suggests "near misses" as
- replacements for unrecognized words. System & user-maintained
- dictionaries for multiple languages can be used. Standalone & GNU Emacs
- interfaces are available. Previously, the GNU Project had its own
- version of ispell ("Ispell 4.0"), but has dropped it for a parallel
- branch that has had more development ("Ispell 3.1"). (Version 3 was an
- earlier release from the original Ispell author, but others have since
- made it more sophisticated.)
-
- * JACAL *Not available from the FSF*
-
- JACAL is a symbolic mathematics system for the manipulation and
- simplification of equations and single and multiple-valued algebraic
- expressions constructed of numbers, variables, radicals, differential
- operators, and algebraic and holonomic functions. Vectors, matrices,
- and tensors of these objects are also supported.
-
- JACAL was written in Scheme by Aubrey Jaffer. It comes with SCM, an IEEE
- P1178 and R4RS compliant version of Scheme written in C. SCM runs on
- Amiga, Atari-ST, MS-DOS, OS/2, NOS/VE, Unicos, VMS, Unix, and similar
- systems. SLIB is a portable Scheme library used by JACAL.
- m{No Value For "ergegrafkludge"} The FSF is not distributing JACAL on
- any media. To receive an IBM PC floppy disk with the source and
- executable files, send $99.00 to:
- Aubrey Jaffer
- 84 Pleasant Street
- Wakefield, MA 01880-1846
- USA
-
- * `less' (SrcCD, UtilD, UtilT)
-
- `less' is a display paginator similar to `more' and `pg' but with
+ vector formats include encapsulated Postscript, Uniplex RGIP, Metafont,
+ various special TeX-related formats, and simplified HP-GL (line drawing
+ only) for imports. Raster formats supported include IMG, PBM, PCX, &
+ HP-PCL (including Deskjet & DJ5xxC support). Previewers work under X11
+ (Unix), OS/2 (PM & full screen), & MS-DOS (SVGA, VGA, & HGC).
+
+ * HylaFAX *Also see* `http://www.vix.com/hylafax/' (SrcCD)
+
+ HylaFAX (once named FlexFAX) is a facsimile system for Unix systems. It
+ supports sending, receiving, & polled retrieval of facsimile, as well as
+ transparent shared data use of the modem.
+
+ * Hyperbole (SrcCD)
+
+ Hyperbole, written by Bob Weiner in Emacs Lisp, is an open, efficient,
+ programmable information management, autonumbered outliner, & hypertext
+ system, intended for everyday work on any platform Emacs runs on.
+
+ * ID Utils (SrcCD)
+
+ ID Utils is a package of simple, fast, high-capacity,
+ language-independent tools that index program identifiers, literal
+ numbers, or words of human-readable text. Queries can be issued from
+ the command-line, or from within Emacs, serving as an augmented tags
+ facility.
+
+ * `indent' (SrcCD)
+
+ GNU `indent' formats C source code into the GNU, BSD, K&R, or your own
+ special indentation style. GNU `indent' is more robust & provides more
+ functionality than other such programs, including handling C++ comments.
+ It runs on Unix, Windows, VMS, ATARI and other systems.
+
+ The next version which formats C++ source code will soon be released.
+
+ * Inetutils (SrcCD)
+
+ Inetutils has common networking utilities & servers.
+
+ Version 1.3a is more portable than previous releases: Inetutils now
+ works on GNU/Linux and SunOS/Solaris systems, although it still requires
+ a system with some degree of BSD compatibility. This release also has
+ many security holes plugged.
+
+ * Ispell (SrcCD)
+
+ Ispell is an interactive spell checker that suggests "near misses" to
+ replace unrecognized words. System & user-maintained dictionaries for
+ multiple languages can be used. Standalone & Emacs interfaces are
+ available.
+
+ * JACAL *Not available from the FSF except by FTP*
+
+ JACAL is a symbolic mathematics system for the manipulation &
+ simplification of algebraic expressions & equations.
+
+ The FSF is not distributing JACAL on any physical media. You can FTP it,
+ or visit the Web site `http://www-swiss.ai.mit.edu/~jaffer/JACAL.html'.
+
+ * jargon (SrcCD)
+
+ The jargon file is the online version of `The New Hacker's Dictionary'.
+
+ * Karma (SrcCD)
+
+ Karma is a signal and image processing library and visualization toolkit
+ that provides interprocess communications, authentication, graphics
+ display, and user interface to and manipulation of the Karma network
+ data structure. Several foreign data formats are also supported. Karma
+ comes packaged with a number of generic visualization tools and some
+ astronomy-specific tools.
+
+ * `less' (SrcCD)
+
+ `less' is a display paginator similar to `more' and `pg', but with
various features (such as the ability to scroll backwards) that most
pagers lack.
- * `m4' (DjgppD, DosCD, SrcCD, UtilD, UtilT)
+ * LessTif (SrcCD)
- GNU `m4' is an implementation of the traditional Unix macro processor.
- It is mostly SVR4 compatible, although it has some extensions (for
- example, handling more than 9 positional parameters to macros). `m4'
- also has built-in functions for including files, running shell commands,
- doing arithmetic, etc.
+ LessTif is a free clone of Motif.
- * `make' (BinCD, DjgppD, DosCD, LangT, LspEmcT, SrcCD, UtilD,
- UtilT)
+ * Libtool (SrcCD)
- GNU `make' supports POSIX 1003.2 and has all but a few obscure features
- of the BSD and System V versions of `make', as well as many of our own
- extensions. GNU extensions include long options, parallel compilation,
- flexible implicit pattern rules, conditional execution and powerful text
- manipulation functions. Texinfo source for the `Make Manual' comes with
- the program. *Note Documentation::.
+ GNU libtool is a generic library support script which manages the
+ complexity of building and linking against shared libraries. Libtool
+ allows source code package maintainers to easily add shared library
+ support without breaking static-only platform compatibility.
- GNU `make' is on several of our tapes because some system vendors supply
- no `make' utility at all, and some native `make' programs lack the
- `VPATH' feature essential for using the GNU configure system to its full
- extent. The GNU `make' sources have a shell script to build `make'
- itself on such systems.
+ Libtool supports building static libraries on all known platforms.
+ Shared library support has been implemented for several platforms.
- MS-DOS binaries for `make' are available with the DJGPP distribution.
+ * Lynx *Also see* `http://lynx.browser.org' (SrcCD)
- * MandelSpawn (SrcCD, UtilT)
+ Lynx is a text-only World Wide Web browser for those running
+ character-only ("cursor-addressable") terminals or terminal emulators.
+
+ * `m4' (SrcCD)
+
+ GNU `m4' is an implementation of the traditional Unix macro processor.
+ It is mostly SVR4 compatible, although it has some extensions (e.g.,
+ handling more than 9 positional parameters to macros). `m4' also has
+ built-in functions for including files, running shell commands, doing
+ arithmetic, etc.
+
+ * `make' (BinCD, SrcCD) [FSFman]
+
+ GNU `make' supports POSIX 1003.2 and has all but a few obscure features
+ of the BSD and System V versions of `make', and runs on MS-DOS,
+ AmigaDOS, VMS, & Windows NT or 95, as well as all Unix-compatible
+ systems. GNU extensions include long options, parallel compilation,
+ flexible implicit pattern rules, conditional execution, & powerful text
+ manipulation functions. Source for the `Make Manual' comes with the
+ program (*note Documentation::.).
+
+ * MandelSpawn (SrcCD)
A parallel Mandelbrot generation program for the X Window System.
- * mtools (SrcCD, UtilT)
-
- mtools is a set of public domain programs to allow Unix systems to read,
- write and manipulate files on an MS-DOS file system (usually a diskette).
-
- * MULE (EmcsD, DosCD, SrcCD)
-
- MULE is a MULtilingual Enhancement to GNU Emacs. It can handle many
- character sets at once including Japanese, Chinese, Korean, Vietnamese,
- Thai, Greek, the ISO Latin-1 through Latin-8 character sets, Ukrainian,
- Arabic, Hebrew, Russian, and other Cyrillic alphabets. A text buffer in
- MULE can contain a mixture of characters from these languages. To input
- any of these characters, you can use various input methods provided by
- MULE itself. In addition, if you use MULE under some terminal emulators
- (kterm, cxterm, or exterm), you can use its input methods. MULE is
- being merged into GNU Emacs. *Note GNU and Other Free Software in
- Japan::, for more information about MULE.
-
- * NetHack (SrcCD, UtilT)
-
- NetHack is a display-oriented adventure game similar to Rogue. Both
- ASCII and X displays are supported.
-
- * NIH Class Library (LangT, SrcCD)
-
- The NIH Class Library (formerly known as "OOPS", Object-Oriented Program
- Support) is a portable collection of C++ classes, similar to those in
- Smalltalk-80, which has been developed by Keith Gorlen of the National
- Institutes of Health (NIH), using the C++ programming language.
-
- * `nvi' (SrcCD, UtilT)
-
- `nvi' is a free implementation of the `vi'/`ex' Unix editor. It has
- most of the functionality of the original `vi'/`ex', except "open" mode
- & the `lisp' option, which will be added. Enhancements over `vi'/`ex'
- include split screens with multiple buffers, handling 8-bit data,
- infinite file & line lengths, tag stacks, infinite undo & extended
- regular expressions. It runs under GNU/Linux, BSD, NetBSD, FreeBSD,
- BSDI, AIX, HP-UX, DGUX, IRIX, PSF, PTX, Solaris, SunOS, Ultrix, Unixware
- & should port easily to many other systems.
-
- * GNU Objective-C Library (LangT, SrcCD)
-
- The GNU Objective-C Class Library (`libobjects') is a library of
- general-purpose, non-graphical Objective-C objects written by Andrew
- McCallum and other volunteers. It includes collection classes for
- maintaining groups of objects and C types, streams for I/O to various
- destinations, coders for formatting objects and C types to streams, ports
- for network packet transmission, distributed objects (remote object
- messaging), string classes, pseudo-random number generators, and time
- handling facilities. The package will also include the foundation
- classes for the GNUStep project; over 50 of these classes have already
- been implemented. The library is known to work on i386, i486, Pentium,
- m68k, SPARC, MIPS, & RS6000. Send queries and bug reports to
- `mccallum@gnu.ai.mit.edu'.
-
- * `OBST' (LangT, SrcCD)
-
- `OBST' is a persistent object management system with bindings to C++.
- `OBST' supports incremental loading of methods. Its graphical tools
- require the X Window System. It features a hands-on tutorial including
- sample programs. It compiles with g++ and should install easily on most
- Unix platforms.
+ * Maxima (SrcCD)
- * Octave (LangT, SrcCD)
+ Maxima is a Common Lisp implementation of MIT's Macsyma system for
+ computer based algebra.
- Octave is a high-level language similar to MATLAB that is primarily
- intended for numerical computations. It provides a convenient command
- line interface for solving linear and nonlinear problems numerically.
- m{No Value For "ergegrafkludge"} Octave does arithmetic for real and
- complex scalars and matrices, solves sets of nonlinear algebraic
- equations, integrates systems of ordinary differential and
- differential-algebraic equations, and integrates functions over finite
- and infinite intervals. Two- and three-dimensional plotting is
- available using `gnuplot'. Send queries and bug reports to:
- `bug-octave@che.utexas.edu'. Source is included for a 220+ page
- Texinfo manual, which is not yet published by the FSF.
+ * MCSim (SrcCD)
- * Oleo (SrcCD, UtilT)
+ MCSim is a general purpose modeling and simulation program which also
+ performs standard or Markov chain Monte Carlo simulations. It allows
+ you to specify a set of linear or nonlinear equations (eventually
+ differential), and solve them using parameter values you choose or
+ parameter values sampled from specified statistical distributions.
+ Simulation outputs can be compared to experimental data for parameter
+ estimation.
- Oleo is a spreadsheet program (better for you than the more expensive
- spreadsheets). It supports the X Window System and character-based
- terminals, and can output Embedded Postscript renditions of spreadsheets.
- Keybindings should be familiar to Emacs users and are configurable.
- Under X and in Postscript output, Oleo supports multiple, variable width
- fonts. *Note Forthcoming GNUs::, for the plans for later releases of
- Oleo.
+ * Meta-HTML (SrcCD)
- * `p2c' (LangT, SrcCD)
+ <Meta-HTML> is a programming language specifically designed for working
+ within the World Wide Web environment. Although it is a genuine
+ programming language, suitable for large-scale symbolic manipulation, it
+ provides the most commonly wanted Web functionality as built-in
+ primitives, so you don't have to write them.
- `p2c' is a Pascal-to-C translator written by Dave Gillespie. It
- recognizes many Pascal dialects including Turbo, HP, VAX, and ISO, and
- produces readable, maintainable, portable C.
+ * Midnight Commander (`mc') (SrcCD)
- * `patch' (DjgppD, DosCD, SrcCD, UtilT)
+ The Midnight Commander is a user friendly & colorful Unix file manager &
+ shell, useful to novice & guru alike. It has a built-in virtual file
+ system that manipulates files inside tar files or files on remote
+ machines using the FTP protocol. This mechanism is extensible with
+ external Unix programs.
- `patch' is our version of Larry Wall's program to take `diff''s output
- and apply those differences to an original file to generate the modified
- version.
+ * Miscellaneous Files Distribution (SrcCD)
- * PCL (LspEmcT, SrcCD)
+ The GNU Miscellaneous Files are non-crucial files that are common on
+ various systems, including word lists, airport codes, ZIP codes etc.
- PCL is a free implementation of a large subset of CLOS, the Common Lisp
- Object System. It runs under both GCL and CLISP, mentioned above.
+ * `mkisofs' (SrcCD)
- * `perl' (LangT, SrcCD)
+ `mkisofs' is a pre-mastering program to generate an ISO 9660 file system.
+ It takes a snapshot of a directory tree, and makes a binary image which
+ corresponds to an ISO 9660 file system when written to a block device.
- Larry Wall's `perl' combines the features and capabilities of `sed',
- `awk', `sh' and C, as well as interfaces to the Unix system calls and
- many C library routines.
+ It can also generate the System Use Sharing Protocol records of the Rock
+ Ridge Interchange Protocol (used to further describe the files in an ISO
+ 9660 file system to a Unix host; it provides information such as longer
+ filenames, uid/gid, permissions, and device nodes).
- * `ptx' (SrcCD, UtilD, UtilT)
+ The `mkisofs' program is often used with `cdwrite'. The `cdwrite'
+ program works by taking the image that `mkisofs' generates and driving a
+ cdwriter drive to actually burn the disk. `cdwrite' works under
+ GNU/Linux, and supports popular cdwriter drives. Older versions of
+ `cdwrite' were included with older versions of `mkisofs';
+ `sunsite.unc.edu' has the latest version:
+ `/pub/Linux/utils/disk-management/cdwrite-2.0.tar.gz'.
- GNU `ptx' is our version of the traditional permuted index generator.
- It handles multiple input files at once, produces TeX compatible output,
- & outputs readable "KWIC" (KeyWords In Context) indexes. It does not
- yet handle input files that do not fit in memory all at once.
+ * `mtools' (SrcCD)
- * `rc' (SrcCD, UtilT)
+ `mtools' is a collection of utilities to access MS-DOS disks from Unix
+ without mounting them. It supports Windows 95 style long file names,
+ OS/2 Xdf disks, ZIP/JAZ disks and 2m disks (store up to 1992k on a high
+ density 3 1/2 disk).
- `rc' is a shell that features a C-like syntax (much more so than `csh')
- and far cleaner quoting rules than the C or Bourne shells. It's
- intended to be used interactively, but is also great for writing
- scripts. It inspired the shell `es'.
+ * MULE *Also *note GNUs Flashes::.* (SrcCD)
- * RCS (SrcCD, UtilD, UtilT)
+ MULE is a MULtilingual Enhancement to GNU Emacs. MULE text buffers can
+ contain a mix of characters from many languages including: Japanese,
+ Chinese, Korean, Vietnamese, Thai, modern European languages (including
+ Greek & Russian), Arabic, & Hebrew. MULE also provides input methods
+ for all of them. *Note GNU & Other Free Software in Japan::, for more
+ information about MULE.
- RCS, the Revision Control System, is used for version control &
- management of software projects. When used with GNU `diff', RCS can
- handle binary files (executables, object files, 8-bit data, etc). Also
- see the item about CVS in this section.
+ The version 20 release of Emacs includes the MULE features, making MULE
+ itself obsolete.
- * `recode' (SrcCD, UtilT)
+ * `mutt' *Also see* `http://www.cs.hmc.edu/~me/mutt' (SrcCD)
- GNU `recode' converts files between character sets and usages. When
- exact transliterations are not possible, it may get rid of the offending
- characters or fall back on approximations. This program recognizes or
- produces nearly 150 different character sets and is able to
- transliterate files between almost any pair. Most RFC 1345 character
- sets are supported.
+ Mutt is a small but very powerful mail client: a hybrid, or "mutt,"
+ consisting of features from various other curses-based e-mail clients.
- * regex (LangT, SrcCD)
+ * NetHack (SrcCD)
- The GNU regular expression library supports POSIX.2, except for
- internationalization features. It is included in many GNU programs which
- do regular expression matching and available separately. An alternative
- regular expression package, `rx', comes with `sed'; it has the potential
- to be faster than `regex' in most cases, but still needs work.
+ NetHack is a display-oriented adventure game similar to Rogue. ASCII,
+ X11, and various PC based GUI displays are supported.
- * Scheme (SchmT, SrcCD)
+ NetHack runs on GNU/Linux, Amiga, Atari, BeBox, Mac, MS Windows, MS-DOS,
+ OS/2, Unix, VMS, and Windows NT.
- For information about Scheme, see *Note Scheme Tape::.
+ The current release of NetHack is 3.2.2. Bug reports concerning NetHack
+ should be sent to `nethack-bugs@linc.cis.upenn.edu'.
- * `screen' (SrcCD, UtilT)
+ * NIH Class Library (SrcCD)
- `screen' is a terminal multiplexer that runs several separate "screens"
- (ttys) on a single character-based terminal. Each virtual terminal
- emulates a DEC VT100 plus several ISO 6429 (ECMA 48, ANSI X3.64) and ISO
- 2022 functions. Arbitrary keyboard input translation is also supported.
- `screen' sessions can be detached and resumed later on a different
- terminal type. Output in detached sessions is saved for later viewing.
+ The NIH Class Library is a set of C++ classes (similar to
+ Smalltalk-80's) written in C++ by Keith Gorlen of the National Institutes
+ of Health (NIH).
- * `sed' (DjgppD, DosCD, SrcCD, UtilD, UtilT)
+ * `nvi' (SrcCD)
- `sed' is a stream-oriented version of `ed'. GNU `sed' comes with the
- `rx' library, a faster version of `regex' (*note Forthcoming GNUs::.).
+ `nvi' is an implementation of the `ex'/`vi' Unix editor. It has all the
+ functionality of the original `ex'/`vi', except `open' mode & the `lisp'
+ edit option. Enhancements include multiple buffers, command-line
+ editing & path completion, integrated Perl5 & Tcl scripting languages,
+ Cscope support & tag stacks, 8-bit data support, infinite file/line
+ lengths, infinite undo, language catalogs, incremental search, extended
+ regular expressions, and security fixes. It uses Autoconf for
+ configuration and runs on any Unix-like system.
- * Sharutils (SrcCD, UtilT)
+ * Oaklisp (SrcCD)
- `shar' makes so-called shell archives out of many files, preparing them
- for transmission by electronic mail services, while `unshar' helps
- unpack these shell archives after reception. `uuencode' prepares a file
- for transmission over an electronic channel which ignores or otherwise
- mangles the high order bit of bytes, while `uudecode' does the converse
- transformation.
+ Oaklisp is a fast, portable, object-oriented Scheme with first class
+ types.
- * Shellutils (DjgppD, DosCD, SrcCD, UtilT)
+ * Objective-C Library (SrcCD)
- Use shellutils interactively or in shell scripts: `basename', `date',
- `dirname', `echo', `env', `expr', `false', `groups', `hostname', `id',
- `logname', `nice', `nohup', `pathchk', `printenv', `printf', `pwd',
- `sleep', `stty', `su', `tee', `test', `true', `tty', `uname', `users',
- `who', `whoami', and `yes'.
+ Our Objective-C Class Library (`gstep-base.tar.gz', `libgnustep-base')
+ has general-purpose, non-graphical Objective-C objects written by Andrew
+ McCallum & others. It includes collection classes for maintaining
+ groups of objects, I/O streams, coders for formatting objects & C types
+ to streams, ports for network packet transmission, distributed objects
+ (remote object messaging), string classes, invocations, notifications,
+ event loops, timers, exceptions, pseudo-random number generators, &
+ more. It has the base classes for the GNUstep project; all but a few of
+ them have already been written. Send queries & bugs to
+ `mccallum@gnu.ai.mit.edu'. See "GNUstep" in *Note Forthcoming GNUs::.
- * GNU Shogi (SrcCD, UtilT)
+ * OBST (SrcCD)
- Shogi is a Japanese game similar to Chess; a major difference is that
- captured pieces can be returned into play. GNU Shogi is a variant of
- GNU Chess; GNU Shogi implements the same features as GNU Chess and uses
- similar heuristics. As a new feature, sequences of partial board
- patterns can be introduced in order to help the program play toward
- specific opening patterns. There are both character and X display
- interfaces. GNU Shogi is primarily supported by Matthias Mutz on
- behalf of the FSF.
+ OBST is a persistent object management system with bindings to C++.
+ OBST supports incremental loading of methods. Its graphical tools
+ require the X Window System. It features a hands-on tutorial including
+ sample programs. It compiles with G++, and should install easily on
+ most Unix platforms.
- * Smalltalk (LangT, SrcCD)
+ * Octave *Also see* `http://www.che.wisc.edu/octave' (SrcCD)
- GNU Smalltalk is an interpreted object-oriented programming language
- system written in highly portable C. It has been successfully ported to
- many Unix and some other platforms, including DOS (but these non-Unix
- ports are not available from the FSF). Current features include a
- binary image save capability, the ability to invoke user-written C code
- and pass parameters to it, a GNU Emacs editing mode, a version of the X
- protocol invocable from Smalltalk, optional byte-code compilation
- tracing and byte-code execution tracing, and automatically loaded
- per-user initialization files. It implements all of the classes and
- protocol in the Smalltalk-80 book "Smalltalk-80: The Language", except
- for the graphic user interface (`GUI') related classes.
+ Octave does arithmetic for real and complex scalars and matrices, solves
+ sets of nonlinear algebraic equations, integrates systems of ordinary
+ differential & differential-algebraic equations, and integrates
+ functions over finite & infinite intervals. Two- & three-dimensional
+ plotting is available using `gnuplot'.
- *Note Forthcoming GNUs::, for plans for later releases of Smalltalk.
+ Version 2.0.9 of Octave was released in July. It includes support for
+ dynamically linked functions, user-defined data types, many new
+ functions, & a completely revised manual. Octave works on most Unix
+ systems, OS/2, and Windows NT/95.
- * Superopt (LangT, SrcCD)
+ * Oleo (SrcCD)
- Superopt is a function sequence generator that uses an exhaustive
- generate-and-test approach to find the shortest instruction sequence for
- a given function. You provide a function as input, a CPU to generate
- code for, and how many instructions you can accept. Its application in
- GCC is described in the `ACM SIGPLAN PLDI'92' proceedings. Superopt
- supports: SPARC, m68k, m68020, m88k, IBM RS/6000, AMD 29000, Intel
- 80x86, Pyramid, DEC Alpha, & HP-PA.
+ Oleo is a spreadsheet program (better for you than the more expensive
+ spreadsheets). It supports the X Window System and character-based
+ terminals, and can output Embedded Postscript renditions of spreadsheets.
+ Keybindings should be familiar to Emacs users and are configurable.
+ Oleo supports multiple variable-width fonts when used under the X Window
+ System or outputting to Postscript devices.
- * `tar' (SrcCD, UtilT)
+ * `p2c' (SrcCD)
- GNU `tar' includes multivolume support, the ability to archive sparse
- files, automatic archive compression/decompression, remote archives and
- special features that allow `tar' to be used for incremental and full
- backups. Unfortunately, GNU `tar' implements an early draft of the
- POSIX 1003.1 `ustar' standard which is different from the final
- standard. Adding support for the new changes in a backward-compatible
- fashion is not trivial.
+ `p2c' is Dave Gillespie's Pascal-to-C translator. It inputs many
+ dialects (HP, ISO, Turbo, VAX, etc.) & generates readable,
+ maintainable, portable C.
- * Termcap Library (SrcCD, UtilT)
+ * `patch' (SrcCD)
- The GNU Termcap library is a drop-in replacement for `libtermcap.a' on
- any system. It does not place an arbitrary limit on the size of Termcap
- entries, unlike most other Termcap libraries. Included is source for the
- `Termcap Manual' in Texinfo format. *Note Documentation::.
-
- * TeX (SrcCD)
-
- TeX is a document formatting system that handles complicated
- typesetting, including mathematics. It is GNU's standard text formatter.
-
- You can obtain TeX from the University of Washington, which maintains and
- supports a tape distribution of TeX for Unix systems. The core material
- consists of Karl Berry's `web2c' TeX package, the sources for which are
- available via anonymous ftp; retrieval instructions are in
- `pub/tex/unixtex.ftp' on `ftp.cs.umb.edu'. If you receive any
- installation support from the University of Washington, please consider
- sending them a donation.
-
- To order a full distribution written in `tar' on either a 1/4inch
- 4-track QIC-24 cartridge or a 4mm DAT cartridge, send $210.00 to:
-
- Pierre A. MacKay
- Department of Classics
- DH-10, Denny Hall 218
- University of Washington
- Seattle, WA 98195
- USA
-
- Electronic-Mail: `mackay@cs.washington.edu'
- Telephone: +1-206-543-2268
-
- Please make checks payable to the University of Washington. Do not
- specify any other payee. That causes accounting difficulties. Checks
- must be in U.S. dollars, drawn on a U.S. bank. Prepaid orders are the
- only orders that can now be handled. Overseas sites: please add to the
- base cost $20.00 for shipment via air parcel post, or $30.00 for
- shipment via courier. Please check with the above for current prices
- and formats.
-
- * Texinfo (DjgppD, DosCD, LangT, LspEmcT, SrcCD, UtilD, UtilT)
-
- Texinfo is a set of utilities which generate both printed manuals and
- online hypertext documentation (called "Info"). There are also programs
- for reading online Info documents. Version 3 has both GNU Emacs Lisp
- and standalone programs written in C or shell script. Texinfo mode for
- GNU Emacs enables easy editing and updating of Texinfo files. Programs
- provided include `makeinfo', `info', `texi2dvi', `texindex', `tex2patch',
- and `fixfonts'. Source for the `Texinfo Manual' is included. *Note
- Documentation::.
+ `patch' applies `diff''s output to a set of original files to generate
+ the modified versions. Recent versions of GNU `patch' can update binary
+ files, and can remove files and directories when they become obsolete.
- * Textutils (DjgppD, DosCD, SrcCD, UtilT)
+ * PCL (SrcCD)
- The Textutils programs manipulate textual data. They include: `cat',
- `cksum', `comm', `csplit', `cut', `expand', `fmt', `fold', `head',
- `join', `nl', `od', `paste', `pr', `sort', `split', `sum', `tac', `tail',
- `tr', `unexpand', `uniq', and `wc'.
+ PCL is a free implementation of a large subset of CLOS, the Common Lisp
+ Object System. It runs under both GCL and CLISP, mentioned above.
- * Tile Forth (LangT, SrcCD)
+ * `perl' (SrcCD)
- Tile Forth is a 32-bit implementation of the Forth-83 standard written
- in C, allowing it to be easily ported to new systems, and extended with
- "any" C-function (graphics, windowing, etc). Many Forth libraries with
- full documentation are available including ones for top-down parsing,
- multi-threads, and object oriented programming.
+ Larry Wall's `perl' combines the features & capabilities of C, `sed',
+ `awk', & `sh', and provides interfaces to the Unix system calls & many C
+ library routines.
- * `time' (SrcCD, UtilT)
+ * `phttpd' (SrcCD)
- `time' is used to report statistics (usually from a shell) about the
- amount of user, system and real time used by a process. On some systems
- it also reports memory usage, page faults, and other statistics.
+ `phttpd' is a high speed World Wide Web server using multithreading,
+ memory mapping, and dynamic linking to achieve its goals of high speed,
+ scalability, and light weight. It is currently supported only on
+ Solaris (SunOS5).
- * `tput' (SrcCD, UtilT)
+ * plotutils (SrcCD)
- `tput' is a portable way for shell scripts to use special terminal
- capabilities. Our `tput' uses the Termcap database, instead of Terminfo
- as most others do.
+ The GNU plotutils (plotting utilities) package includes `libplot', a
+ subroutine library for producing 2-D device-independent vector graphics,
+ and `graph', a sample application for plotting 2-D scientific data that
+ is built on top of `libplot'. Supported devices include X Window System
+ displays, Postscript devices, and Tektronix emulators. `xfig' output
+ format, which can be edited with the free graphics editor `xfig', is
+ also supported. The Postscript output format includes directives which
+ allow it to be edited with the `idraw' graphics editor. Included with
+ `graph' are `spline', a program that uses splines in tension to
+ interpolate data, and `ode', an application that will numerically
+ integrate a system of ordinary differential equations.
- * UUCP (SrcCD, UtilT)
+ * PRCS (SrcCD)
- This version of UUCP was written by Ian Lance Taylor, and is GNU's
- standard UUCP system. It supports the `f', `g' and `v' (in all window
- and packet sizes), `G', `t', `e', Zmodem and two new bidirectional (`i'
- and `j') protocols. If you have a Berkeley sockets library, it can make
- TCP connections. If you have TLI libraries, it can make TLI
- connections. Source is included for a Texinfo manual, which is not yet
- published by the FSF.
+ PRCS, the Project Revision Control System, is a version control program
+ with purpose similar to that of CVS. It was designed with simplicity in
+ mind. Like CVS, PRCS uses RCS to accomplish this task, but this is
+ inconsequential to the user, as RCS is completely hidden beneath a layer
+ of abstraction.
- * `wdiff' (DjgppD, DosCD, SrcCD, UtilT)
+ * `ptx' (SrcCD)
- `wdiff' is a front-end to GNU `diff'. It compares two files, finding
- the words deleted or added to the first to make the second. It has many
- output formats and works well with terminals and pagers. `wdiff' is
- very useful when two texts differ only by a few words and paragraphs
- have been refilled.
+ GNU `ptx' is our version of the traditional permuted index generator.
+ It handles multiple input files at once, has TeX compatible output, &
+ outputs readable "KWIC" (KeyWords In Context) indexes without using
+ `nroff'. Plans are to merge this package into `textutils'.
- * `Ygl' (SrcCD, UtilT)
+ It does not yet handle input files that do not fit in memory all at once.
- `Ygl' emulates SGI's GL (Graphics Language) library under X11. It runs
- under GNU/Linux with XFree, AIX 3.2, ConvexOS, HP-UX 7.0/8.0/9.0, SunOS
- and many others.
+ * `rc' (SrcCD)
+ `rc' is a shell that features a C-like syntax (much more so than `csh')
+ and far cleaner quoting rules than the C or Bourne shells. It's
+ intended to be used interactively, but is also great for writing
+ scripts. It inspired the shell `es'.
+ * RCS (SrcCD)
-Program/Package Cross Reference - (NOT COMPLETELY UP TO DATE)
-*******************************
+ RCS, the Revision Control System, is used for version control &
+ management of software projects. Used with GNU `diff', RCS can handle
+ binary files (8-bit data, executables, object files, etc). RCS now
+ conforms to GNU configuration standards & to POSIX 1003.1b-1993. Also
+ see the CVS item above.
-Here is a list of what package each GNU program or library is in. You can
-anonymously FTP a full list in the file `/pub/gnu/ProgramIndex' from a GNU
-FTP host (*note How to Get GNU Software::. for a list).
-
- * a2p perl
- * a2x xopt
- * ac bsd44
- * accton bsd44
- * acl bsd44
- * acm acm
- * acms acm
- * addftinfo Groff
- * adventure bsd44
- * afm2tfm TeX
- * amd bsd44
- * ansitape bsd44
- * AnswerGarden xopt
- * apply bsd44
- * appres xreq
- * apropos bsd44
- * ar Binutils
- * arithmetic bsd44
- * arp bsd44
- * atc bsd44
- * autoconf Autoconf
- * autoheader Autoconf
- * autoreconf Autoconf
- * autoscan Autoconf
- * autoupdate Autoconf
- * auto_box xopt
- * auto_box xreq
-
- * b2m Emacs
- * backgammon bsd44
- * bad144 bsd44
- * badsect bsd44
- * banner bsd44
- * basename Shellutils
- * bash BASH
- * battlestar bsd44
- * bc bc
- * bcd bsd44
- * bdes bsd44
- * bdftops Ghostscript
- * beach_ball xopt
- * beach_ball xreq
- * beach_ball2 xopt
- * bibtex TeX
- * biff bsd44
- * bison Bison
- * bitmap xreq
- * boggle bsd44
- * bpltobzr Fontutils
- * bugfiler bsd44
- * build ispell
- * bzrto Fontutils
-
- * c++ GCC
- * c++filt Binutils
- * c2ph perl
- * ca100 xopt
- * caeser bsd44
- * cal bsd44
- * calendar bsd44
- * canfield bsd44
- * cat Textutils
- * cbars wdiff
- * cc GCC
- * cc1 GCC
- * cc1obj GCC
- * cc1plus GCC
- * cccp GCC
- * charspace Fontutils
- * checknr bsd44
- * chess bsd44
- * chflags bsd44
- * chgrp Fileutils
- * ching bsd44
- * chmod Fileutils
- * chown Fileutils
- * chpass bsd44
- * chroot bsd44
- * ci RCS
- * cksum Textutils
- * clisp CLISP
- * clri bsd44
- * cmail xboard
- * cmmf TeX
- * cmodext xopt
- * cmp Diffutils
- * co RCS
- * col bsd44
- * colcrt bsd44
- * colrm bsd44
- * column bsd44
- * comm Textutils
- * compress bsd44
- * comsat bsd44
- * connectd bsd44
- * cp Fileutils
- * cpicker xopt
- * cpio cpio
- * cpp GCC
- * cppstdin perl
- * cribbage bsd44
- * crock xopt
- * csh bsd44
- * csplit Textutils
- * ctags Emacs
- * ctwm xopt
- * cu UUCP
- * cut Textutils
- * cvs CVS
- * cvscheck CVS
- * cvtmail Emacs
- * cxterm xopt
-
- * d Fileutils
- * date Shellutils
- * dc bc
- * dd Fileutils
- * delatex TeX
- * demangle Binutils
- * descend CVS
- * detex TeX
- * df Fileutils
- * diff Diffutils
- * diff3 Diffutils
- * digest-doc Emacs
- * dipress bsd44
- * dir Fileutils
- * dirname Shellutils
- * dish xopt
- * disklabel bsd44
- * diskpart bsd44
- * dld dld
- * dm bsd44
- * dmesg bsd44
- * doschk doschk
- * dox xopt
- * du Fileutils
- * dump bsd44
- * dumpfs bsd44
- * dvi2tty TeX
- * dvicopy TeX
- * dvips TeX
- * dvitype TeX
-
- * ecc ecc
- * echo Shellutils
- * ed ed
- * edit-pr GNATS
- * editres xreq
- * edquota bsd44
- * eeprom bsd44
- * egrep grep
- * emacs Emacs
- * emacsclient Emacs
- * emacsserver Emacs
- * emacstool Emacs
- * emu xopt
- * env Shellutils
- * eqn Groff
- * error bsd44
- * es es
- * esdebug es
- * etags Emacs
- * ex nvi
- * expand Textutils
- * expect DejaGnu
- * expr Shellutils
- * exterm xopt
-
- * f2c f2c
- * factor bsd44
- * fakemail Emacs
- * false Shellutils
- * fastboot bsd44
- * fax2ps HylaFAX
- * faxalter HylaFAX
- * faxanswer HylaFAX
- * faxcover HylaFAX
- * faxd HylaFAX
- * faxd.recv HylaFAX
- * faxmail HylaFAX
- * faxquit HylaFAX
- * faxrcvd HylaFAX
- * faxrm HylaFAX
- * faxstat HylaFAX
- * fc f2c
- * fdraw xopt
- * fgrep grep
- * file bsd44
- * find Findutils
- * find2perl perl
- * finger finger
- * fingerd finger
- * fish bsd44
- * fixfonts Texinfo
- * fixinc.svr4 GCC
- * fixincludes GCC
- * flex flex
- * fmt bsd44
- * fold Textutils
- * font2c Ghostscript
- * fontconvert Fontutils
- * forth Tile Forth
- * forthicon Tile Forth
- * forthtool Tile Forth
- * fortune bsd44
- * fpr bsd44
- * freq ispell
- * freqtbl ispell
- * from bsd44
- * fsck bsd44
- * fsplit bsd44
- * fstat bsd44
- * ftp bsd44
- * ftpd bsd44
-
- * g++ GCC
- * gas Binutils
- * gawk Gawk
- * gcc GCC
- * gcore bsd44
- * gdb GDB
- * genclass libg++
- * getty bsd44
- * gftodvi TeX
- * gftopk TeX
- * gftype TeX
- * ghostview Ghostview
- * gnats GNATS
- * gnuchess Chess
- * gnuchessc Chess
- * gnuchessn Chess
- * gnuchessr Chess
- * gnuchessx Chess
- * gnupdisp Shogi
- * gnuplot gnuplot
- * gnuplot_x11 gnuplot
- * gnushogi Shogi
- * gnushogir Shogi
- * gnushogix Shogi
- * go GnuGo
- * gpc xopt
- * gpc xreq
- * gperf gperf
- * gperf libg++
- * gprof Binutils
- * graph Graphics
- * grep grep
- * grodvi Groff
- * groff Groff
- * grops Groff
- * grotty Groff
- * groups Shellutils
- * gs Ghostscript
- * gsbj Ghostscript
- * gsdj Ghostscript
- * gslj Ghostscript
- * gslp Ghostscript
- * gsnd Ghostscript
- * gsrenderfont Fontutils
- * gunzip gzip
- * gwm xopt
- * gzexe gzip
- * gzip gzip
-
- * h2ph perl
- * h2pl perl
- * hack bsd44
- * hangman bsd44
- * head Textutils
- * hello hello
- * hexdump bsd44
- * hexl Emacs
- * hostname Shellutils
- * hp2xx hp2xx
- * hterm xopt
-
- * i18nOlwmV2 xopt
- * i2mif xopt
- * ico xopt
- * ico xreq
- * id Shellutils
- * ident RCS
- * ifconfig bsd44
- * ifnames Autoconf
- * ImageMagick xopt
- * imageto Fontutils
- * iman xopt
- * imgrotate Fontutils
- * indent indent
- * indxbib Groff
- * inetd bsd44
- * info Texinfo
- * inimf TeX
- * init bsd44
- * initex TeX
- * inn bsd44
- * install Fileutils
- * iostat bsd44
- * ispell ispell
- * ixterm xopt
- * ixx xopt
-
- * join Textutils
- * jot bsd44
- * jove bsd44
-
- * kdestroy bsd44
- * kdump bsd44
- * kermit bsd44
- * kgames xopt
- * kgmon bsd44
- * kill bsd44
- * kinit bsd44
- * kinput2 xopt
- * klist bsd44
- * kpasswdd bsd44
- * ksrvtgt bsd44
- * kterm xopt
- * ktrace bsd44
-
- * lam bsd44
- * larn bsd44
- * lasergnu gnuplot
- * last bsd44
- * lastcomm bsd44
- * latex TeX
- * lclock xopt
- * ld Binutils
- * leave bsd44
- * less less
- * lesskey less
- * libbfd.a Binutils
- * libbfd.a GAS
- * libbfd.a GDB
- * libbzr.a Fontutils
- * libc.a C Library
- * libcompat.a bsd44
- * libcurses.a bsd44
- * libcurses.a nvi
- * libedit.a bsd44
- * libF77.a f2c
- * libg++.a libg++
- * libgdbm.a gdbm
- * libgf.a Fontutils
- * libgmp.a gmp
- * libI77.a f2c
- * libkvm.a bsd44
- * libm.a bsd44
- * libnihcl.a NIHCL
- * libnihclmi.a NIHCL
- * libnihclvec.a NIHCL
- * libnls.a xreq
- * liboctave.a Octave
- * liboldX.a xreq
- * libpbm.a Fontutils
- * libPEXt.a xopt
- * libpk.a Fontutils
- * libresolv.a bsd44
- * librpc.a bsd44
- * libtcl.a DejaGnu
- * libtelnet.a bsd44
- * libterm.a bsd44
- * libtermcap.a Termcap
- * libtfm.a Fontutils
- * libutil.a bsd44
- * libWc.a xopt
- * libwidgets.a Fontutils
- * libX.a xreq
- * libXau.a xreq
- * libXaw.a xreq
- * libXcp.a xopt
- * libXcu.a xopt
- * libXdmcp.a xreq
- * libXmp.a xopt
- * libXmu.a xreq
- * libXO.a xopt
- * libXop.a xopt
- * libXp.a xopt
- * libXpex.a xopt
- * libXt.a xopt
- * libXt.a xreq
- * libXwchar.a xopt
- * liby.a bsd44
- * libYgl.a Ygl
- * limn Fontutils
- * listres xopt
- * listres xreq
- * lkbib Groff
- * ln Fileutils
- * locate Findutils
- * lock bsd44
- * logger bsd44
- * login bsd44
- * logname Shellutils
- * look ispell
- * lookbib Groff
- * lorder bsd44
- * lpr bsd44
- * ls Fileutils
-
- * m4 m4
- * mail bsd44
- * make Make
- * make-docfile Emacs
- * make-path Emacs
- * makeindex TeX
- * makeinfo Texinfo
- * MakeTeXPK TeX
- * man bsd44
- * man-macros Groff
- * mattrib mtools
- * maze xopt
- * maze xreq
- * mazewar xopt
- * mcd mtools
- * mcopy mtools
- * mdel mtools
- * mdir mtools
- * me-macros Groff
- * merge RCS
- * mesg bsd44
- * mf TeX
- * mformat mtools
- * mft TeX
- * mgdiff xopt
- * mh bsd44
- * mille bsd44
- * mkdep bsd44
- * mkdir Fileutils
- * mkfifo Fileutils
- * mklocale bsd44
- * mkmanifest mtools
- * mkmf bsd44
- * mkmodules CVS
- * mknod Fileutils
- * mkstr bsd44
- * mlabel mtools
- * mm-macros Groff
- * mmd mtools
- * monop bsd44
- * more bsd44
- * morse bsd44
- * mount bsd44
- * mountd bsd44
- * movemail Emacs
- * mprof bsd44
- * mrd mtools
- * mread mtools
- * mren mtools
- * ms-macros Groff
- * msgs bsd44
- * mt cpio
- * mterm xopt
- * mtree bsd44
- * mtype mtools
- * mule MULE
- * muncher xopt
- * mv Fileutils
- * mvdir Fileutils
- * mwrite mtools
-
- * nethack Nethack
- * netstat bsd44
- * newfs bsd44
- * nfsd bsd44
- * nfsiod bsd44
- * nfsstat bsd44
- * nice Shellutils
- * nl Textutils
- * nlmconv Binutils
- * nm Binutils
- * nohup Shellutils
- * notify HylaFAX
- * nroff Groff
- * number bsd44
-
- * objc GCC
- * objcopy Binutils
- * objdump Binutils
- * objective-c GCC
- * obst-boot OBST
- * obst-CC OBST
- * obst-cct OBST
- * obst-cgc OBST
- * obst-cmp OBST
- * obst-cnt OBST
- * obst-cpcnt OBST
- * obst-csz OBST
- * obst-dir OBST
- * obst-dmp OBST
- * obst-gen OBST
- * obst-gsh OBST
- * obst-init OBST
- * obst-scp OBST
- * obst-sil OBST
- * obst-stf OBST
- * oclock xreq
- * octave Octave
- * od Textutils
- * oleo Oleo
- * ora-examples xopt
-
- * p2c p2c
- * pagesize bsd44
- * palette xopt
- * pascal bsd44
- * passwd bsd44
- * paste Textutils
- * patch patch
- * patgen TeX
- * pathalias bsd44
- * pathchk Shellutils
- * pax bsd44
- * pbmplus xopt
- * perl perl
- * pfbtops Groff
- * phantasia bsd44
- * pic Groff
- * pig bsd44
- * ping bsd44
- * pixedit xopt
- * pixmap xopt
- * pktogf TeX
- * pktype TeX
- * plaid xopt
- * plot2fig Graphics
- * plot2plot Graphics
- * plot2ps Graphics
- * plot2tek Graphics
- * pltotf TeX
- * pollrcvd HylaFAX
- * pom bsd44
- * pooltype TeX
- * portmap bsd44
- * ppt bsd44
- * pr Textutils
- * pr-addr GNATS
- * pr-edit GNATS
- * primes bsd44
- * printenv Shellutils
- * printf Shellutils
- * protoize GCC
- * ps bsd44
- * ps2ascii Ghostscript
- * ps2epsi Ghostscript
- * ps2fax HylaFAX
- * psbb Groff
- * pstat bsd44
- * psycho xopt
- * ptx ptx
- * pubdic+ xopt
- * puzzle xopt
- * puzzle xreq
- * pwd Shellutils
- * pyramid xopt
-
- * query-pr GNATS
- * quiz bsd44
- * quot bsd44
- * quota bsd44
- * quotacheck bsd44
- * quotaon bsd44
-
- * rain bsd44
- * random bsd44
- * ranlib Binutils
- * rbootd bsd44
- * rc rc
- * rcp bsd44
- * rcs RCS
- * rcs-to-cvs CVS
- * rcs2log Emacs
- * rcsdiff RCS
- * rcsfreeze RCS
- * rcsmerge RCS
- * rdist bsd44
- * reboot bsd44
- * recode recode
- * recvstats HylaFAX
- * refer Groff
- * renice bsd44
- * repquota bsd44
- * restore bsd44
- * rev bsd44
- * rexecd bsd44
- * rlog RCS
- * rlogin bsd44
- * rlogind bsd44
- * rm Fileutils
- * rmail bsd44
- * rmdir Fileutils
- * rmt cpio
- * rmt tar
- * robots bsd44
- * rogue bsd44
- * route bsd44
- * routed bsd44
- * rr xopt
- * rs bsd44
- * rsh bsd44
- * rshd bsd44
- * runtest DejaGnu
- * runtest.exp DejaGnu
- * ruptime bsd44
- * rwho bsd44
- * rwhod bsd44
-
- * s2p perl
- * sail bsd44
- * savecore bsd44
- * sc bsd44
- * sccs bsd44
- * sccs2rcs CVS
- * scdisp xopt
- * screen screen
- * script bsd44
- * scsiformat bsd44
- * sctext xopt
- * sdiff Diffutils
- * sed sed
- * send-pr GNATS
- * sendfax HylaFAX
- * sendmail bsd44
- * sgi2fax HylaFAX
- * sh bsd44
- * shar Sharutils
- * shinbun xopt
- * shogi Shogi
- * showfont xopt
- * showmount bsd44
- * shutdown bsd44
- * size Binutils
- * sj3 xopt
- * sjxa xopt
- * slattach bsd44
- * sleep Shellutils
- * sliplogin bsd44
- * snake bsd44
- * snftobdf xopt
- * soelim Groff
- * sort Textutils
- * sos2obst OBST
- * spider xopt
- * split Textutils
- * startslip bsd44
- * stf OBST
- * strings Binutils
- * strip Binutils
- * stty Shellutils
- * su Shellutils
- * sum Textutils
- * superopt Superopt
- * swapon bsd44
- * sync bsd44
- * sysctl bsd44
- * syslogd bsd44
- * systat bsd44
-
- * tac Textutils
- * tail Textutils
- * taintperl perl
- * talk bsd44
- * talkd bsd44
- * tangle TeX
- * tar tar
- * tbl Groff
- * tcl DejaGnu
- * tclsh DejaGnu
- * tcopy bsd44
- * tcp Emacs
- * tee Shellutils
- * tek2plot Graphics
- * telnet bsd44
- * telnetd bsd44
- * test Shellutils
- * test-g++ DejaGnu
- * test-tool DejaGnu
- * tetris bsd44
- * tex TeX
- * tex3patch Texinfo
- * texi2dvi Texinfo
- * texindex Texinfo
- * texspell TeX
- * textfmt HylaFAX
- * tfmtodit Groff
- * tftopl TeX
- * tftp bsd44
- * tftpd bsd44
- * tgrind TeX
- * time time
- * timed bsd44
- * timer Emacs
- * timex xopt
- * tip bsd44
- * tkpostage xopt
- * tn3270 bsd44
- * touch Fileutils
- * tput tput
- * tr Textutils
- * traceroute bsd44
- * transcript HylaFAX
- * transfig xopt
- * trek bsd44
- * trn3 bsd44
- * troff Groff
- * trpt bsd44
- * trsp bsd44
- * true Shellutils
- * tset bsd44
- * tsort bsd44
- * tty Shellutils
- * tunefs bsd44
- * tvtwm xopt
- * twm xreq
-
- * ul bsd44
- * umount bsd44
- * uname Shellutils
- * uncompress gzip
- * unexpand Textutils
- * unifdef bsd44
- * uniq Textutils
- * unprotoize GCC
- * unshar Sharutils
- * unvis bsd44
- * update bsd44
- * updatedb Findutils
- * users Shellutils
- * uuchk UUCP
- * uucico UUCP
- * uuconv UUCP
- * uucp UUCP
- * uucpd bsd44
- * uudecode Sharutils
- * uudir UUCP
- * uuencode Sharutils
- * uulog UUCP
- * uuname UUCP
- * uupick UUCP
- * uurate UUCP
- * uusched UUCP
- * uustat UUCP
- * uuto UUCP
- * uux UUCP
- * uuxqt UUCP
-
- * v Fileutils
- * vacation bsd44
- * vandal xopt
- * vcdiff Emacs
- * vdir Fileutils
- * vftovp TeX
- * vgrind bsd44
- * vi nvi
- * viewres xopt
- * viewres xreq
- * vine xopt
- * vipw bsd44
- * virmf TeX
- * virtex TeX
- * vis bsd44
- * vmstat bsd44
- * vptovf TeX
-
- * w bsd44
- * wakeup Emacs
- * wall bsd44
- * wargames bsd44
- * wc Textutils
- * wdiff wdiff
- * weave TeX
- * what bsd44
- * whatis bsd44
- * whereis bsd44
- * who Shellutils
- * whoami Shellutils
- * whois bsd44
- * window bsd44
- * winterp xopt
- * wish DejaGnu
- * worm bsd44
- * worms bsd44
- * write bsd44
- * wump bsd44
-
- * x11perf xreq
- * x2p perl
- * xalarm xopt
- * xancur xopt
- * xargs Findutils
- * xauth xreq
- * xbfe Fontutils
- * xbiff xopt
- * xbiff xreq
- * xboard xboard
- * xboing xopt
- * xbuffy3 xopt
- * xcalc xopt
- * xcalc xreq
- * xcalendar xopt
- * xcdplayer xopt
- * xcell xopt
- * xclipboard xreq
- * xclock xreq
- * xcmdmenu xopt
- * xcms xopt
- * xcmsdb xreq
- * xcmstest xreq
- * xco xopt
- * xcolorize xopt
- * xcolors xopt
- * xconsole xreq
- * xcrtca xopt
- * xdaliclock xopt
- * xdiary xopt
- * xditview Groff
- * xditview xopt
- * xditview xreq
- * xdm xreq
- * xdpyinfo xreq
- * xdu xopt
- * xdvi TeX
- * xdvi xopt
- * xdvorak xopt
- * xearth xopt
- * xed xopt
- * xedit xopt
- * xedit xreq
- * xev xopt
- * xev xreq
- * xexit xopt
- * xeyes xopt
- * xeyes xreq
- * xfd xreq
- * xfed xopt
- * xfedor xopt
- * xfeoak xopt
- * xferstats HylaFAX
- * xfig xopt
- * xfontsel xopt
- * xfontsel xreq
- * xforecast xopt
- * xgas xopt
- * xgas xreq
- * xgc xopt
- * xgc xreq
- * xhearts xopt
- * xhelp xopt
- * xhost xreq
- * xinit xreq
- * xkeycaps xopt
- * xkill xreq
- * xlax xopt
- * xlayout xopt
- * xlbiff xopt
- * xless xopt
- * xload xopt
- * xload xreq
- * xlogin xopt
- * xlogo xreq
- * xlsatoms xreq
- * xlsclients xreq
- * xlsfonts xreq
- * xmag xreq
- * xmail xopt
- * xmailbox xopt
- * xmailwatcher xopt
- * xman xopt
- * xman xreq
- * xmandel xopt
- * xmessage xopt
- * xmeter xopt
- * xmh xreq
- * xmh-icons xopt
- * xmh.editor xopt
- * xmodmap xreq
- * xmon xopt
- * xmove xopt
- * xmphone xopt
- * xpd xopt
- * xphoon xopt
- * xpipeman xopt
- * xplot Graphics
- * xpostit xopt
- * xpr xopt
- * xpr xreq
- * xprompt xopt
- * xproof xopt
- * xprop xreq
- * xpserv xopt
- * xrdb xreq
- * xrefresh xreq
- * xrsh xopt
- * xrubik xopt
- * xrunclient xopt
- * xscope xopt
- * xscreensaver xopt
- * xsession xopt
- * xset xreq
- * xsetroot xreq
- * xshogi xshogi
- * xstdcmap xreq
- * xstr bsd44
- * xtalk xopt
- * xterm xreq
- * xterm_color xopt
- * xtetris xopt
- * xTeXcad.13 xopt
- * xtiff xopt
- * xtree xopt
- * xtv xopt
- * xwd xreq
- * xwininfo xreq
- * xwud xreq
-
- * yacc bsd44
- * yes Shellutils
- * youbin xopt
- * yow Emacs
-
- * zcat gzip
- * zcmp gzip
- * zdiff gzip
- * zforce gzip
- * zgrep gzip
- * zmore gzip
- * znew gzip
-
- * [ Shellutils
-
-
-
-Tapes
-*****
-
-We offer Unix source code on tapes in `tar' format on these media:
-
- * 4mm DAT cartridges
-
- * 8mm Exabyte cartridges
-
- * Sun DC300XLP QIC-24 1/4in cartridges (readable on some other systems)
-
- * Hewlett-Packard 16-track DC600HC 1/4in cartridges
-
- * IBM RS/6000 QIC-150 1/4in cartridges (readable on some other systems)
-
- * 1600bpi 9-track 1/2in reel tape
-
-The contents of the reel and various cartridge tapes for Unix systems are the
-same (except for the RS/6000 Emacs tape, which also has executables for
-Emacs); only the media are different. For pricing information, see the *note
-Free Software Foundation Order Form::.. Source code for the manuals and
-reference cards is included (*note Documentation::.).
-
-Some of the files on the tapes may be compressed with `gzip' to make them
-fit. Refer to the top-level `README' file at the beginning of each tape for
-instructions on uncompressing them. `uncompress' and `unpack' *do not work*!
-
-
-
-Languages Tape - (VERSION NUMBERS NOT COMPLETELY UP TO DATE)
---------------
-
-This tape contains programming tools: compilers, interpreters, and related
-programs (parsers, conversion programs, debuggers, etc.).
-
- * Binutils 2.5.2
- * Bison 1.22
- * C Library 1.09
- * DejaGnu 1.2
- * dld 3.2.3
- * ecc 1.2.1
- * f2c 1994.11.03
- * flex 2.4.7
- * Gawk 2.15.5
- * GCC/G++/Objective-C 2.7.0
- * GDB 4.13
- * gdbm 1.7.3
- * gmp 1.3.2
- * gperf 2.1a
- * gzip 1.2.4
- * indent 1.9.1
- * libg++ 2.6.1
- * libobjects 0.1.0
- * Make 3.72.1
- * NIHCL 3.0
- * OBST 3.4
- * Octave 1.0
- * p2c 1.20
- * perl 4.036
- * perl 5.000
- * regex 0.12
- * rx 0.05
- * Smalltalk 1.1.1
- * Superopt 2.3
- * Texinfo 3.1
- * Tile Forth 2.1
-
-
-
-Lisps and Emacs Tape - (VERSION NUMBERS NOT COMPLETELY UP TO DATE)
---------------------
+ * `readline' (BinCD, SrcCD)
-This tape has Common Lisp systems and libraries, GNU Emacs, assorted
-extensions that work with GNU Emacs, and a few other important utilities.
-
- * Calc 2.02c
- * CLISP 1994.10.26
- * Common Lisp 1.1
- * elib 0.06
- * Emacs 18.59
- * Emacs 19.29
- * GNU Emacs Lisp Reference Manaul, Ed. 2.3
- * gzip 1.2.4
- * Make 3.72.1
- * MULE 2.1
- * PCL 1993.03.18
- * Texinfo 3.1
-
-
-
-Utilities Tape - (VERSION NUMBERS NOT COMPLETELY UP TO DATE)
---------------
-
-This tape consists mostly of smaller utilities and miscellaneous applications.
-
- * acm 4.6
- * Autoconf 1.11
- * Autoconf 2.1
- * BASH 1.14.2
- * bc 1.03
- * Chess 4.0.73
- * cpio 2.3
- * CVS 1.3
- * dc 0.2
- * Diffutils 2.7
- * doschk 1.1
- * ed 0.2
- * es 0.84
- * Fileutils 3.12
- * Findutils 4.1
- * finger 1.37
- * HylaFAX 2.2.2.1
- * Fontutils 0.6
- * Ghostscript 2.6.1
- * Ghostview 1.5
- * GNATS 3.2
- * GnuGo 1.1
- * gnuplot 3.5
- * Graphics 0.17
- * grep 2.0
- * Groff 1.09
- * gzip 1.2.4
- * hello 1.3
- * hp2xx 3.1.4
- * ispell 3.1.13
- * m4 1.3
- * Make 3.72.1
- * mkisofs 1.01
- * mm 1.07
- * mtools 2.0.7
- * Nethack 3.1.3
- * nvi 1.34
- * Oleo 1.6
- * patch 2.1
- * ptx 0.4
- * rc 1.4
- * RCS 5.6.0.1
- * recode 3.4
- * saoimage 1.08
- * screen 3.5.2
- * screen 3.6.0
- * sed 1.18 & 2.05
- * Sharutils 4.1
- * Shellutils 1.12
- * Shogi 1.2.02
- * tar 1.11.2
- * Termcap 1.2
- * Texinfo 3.1
- * Textutils 1.11
- * time 1.6
- * tput 1.0
- * UUCP 1.05
- * wdiff 0.04
- * xboard 3.1.1
- * xshogi 1.2.02
- * Ygl 2.9
-
-
-
-Scheme Tape
------------
+ Brian Fox wrote the `readline' library one weekend in 1987, so that the
+ FSF would have a clean Emacs-like line editing facility that could be
+ used across multiple programs. After installing it in Bash, he went on
+ to test the reusability of the code by adding it to GDB, and then later,
+ to the GNU FTP client. The library supplies many entry points--the
+ simplest interface gives any program the ability to store a history of
+ input lines, and gives the end user a complete Emacs-like (or vi-like)
+ editing capability over the input, simply by replacing calls to `gets'
+ with calls to `readline'.
-Scheme is a simplified, lexically-scoped dialect of Lisp. It was designed at
-MIT and other universities to teach students the art of programming, and to
-research new parallel programming constructs and compilation techniques.
+ * `recode' *Also *note Forthcoming GNUs::.* (SrcCD)
-This tape now contains MIT Scheme 7.3, which conforms to the "Revised^4
-Report On the Algorithmic Language Scheme" (MIT AI Lab Memo 848b), for which
-TeX source is included. It is written partly in C, but is presently hard to
-bootstrap. Binaries that can be used to bootstrap Scheme are available for:
+ GNU `recode' converts files between character sets and usages. When
+ exact transliterations are not possible, it may delete the offending
+ characters or fall back on approximations. This program recognizes or
+ outputs nearly 150 different character sets and is able to transliterate
+ files between almost any pair. Most RFC 1345 character sets are
+ supported.
- * HP 9000 series 300, 400, 700 & 800 running HP-UX 7.0 or 8.0
+ * `regex' (SrcCD)
- * NeXT running NeXT OS 1.0 or 2.0
+ The GNU regular expression library supports POSIX.2, except for
+ internationalization features. It is included in many GNU programs which
+ do regular expression matching & is available separately. An alternate
+ regular expression package, `rx', is faster than `regex' in many cases;
+ we were planning to replace `regex' with `rx', but it is not certain
+ this will happen.
- * Sun-3 or Sun-4 running SunOS 4.1
+ * Roxen (SrcCD)
- * DECstation 3100/5100 running Ultrix 4.0
+ Roxen is a modularized, object-oriented, non-forking World Wide Web
+ server with high performance and throughput, and capabilities for on the
+ fly image generation (`http://www.roxen.com'). It was formerly named
+ Spinner, but was renamed for trademark reasons.
- * Sony NeWS-3250 running NEWS OS 5.01
+ * `rsync' (SrcCD)
- * Vax running 4.3BSD
+ `rsync' is a replacement for `rcp' that has many more features. `rsync'
+ uses the "rsync algorithm", which provides a very fast method for
+ synchronizing large remote files, sending only the differences across
+ the link. It does not require both versions of a file to be local in
+ order to compute the differences. A technical report describing the
+ rsync algorithm is included with the package.
-If your system is not on this list and you don't enjoy the bootstrap
-challenge, see the JACAL item in *Note GNU Software::.
+ * `rx' (SrcCD)
+ Tom Lord has written `rx', a new regular expression library which is
+ generally faster and more correct than the older GNU `regex' library.
+ * SAOimage (SrcCD)
-X11 Tapes
----------
+ SAOimage is an X-based astronomical image viewer. It reads array data
+ images, which may be in specific formats, and displays them with a
+ pseudocolor colormap. There is full interactive control of the
+ colormap, panning and zooming, graphical annotation, and cursor tracking
+ in pixel and sky coordinates, among other features.
-The two X11 tapes contain Version 11, Release 6 of the X Window System. The
-first tape contains all of the core software, documentation and some
-contributed clients. We call this the "required" X tape since it is
-necessary for running X or running GNU Emacs under X. The second, "optional"
-tape contains contributed libraries and other toolkits, the Andrew User
-Interface System, games, and other programs.
+ * `screen' (SrcCD)
-The X11 Required tape also contains all fixes and patches released to date.
-We update this tape as new fixes and patches are released for programs on
-both tapes. *Note Tape & CD-ROM Subscription Service::.
+ `screen' is a terminal multiplexer that runs several separate "screens"
+ (ttys) on a single character-based terminal. Each virtual terminal
+ emulates a DEC VT100 plus several ISO 2022 and ISO 6429 (ECMA 48, ANSI
+ X3.64) functions, including color. Arbitrary keyboard input translation
+ is also supported. `screen' sessions can be detached and resumed later
+ on a different terminal type. Output in detached sessions is saved for
+ later viewing.
-We will distribute X11R5 on tape until X11R6 is stable, and on the *Note
-November 1993 Source Code CD-ROM::, while supplies last.
+ * `sed' (SrcCD)
+ `sed' is a stream-oriented version of `ed'. It comes with the `rx'
+ library.
+ * Sharutils (SrcCD)
-Berkeley 4.4BSD-Lite Tape
--------------------------
+ `shar' makes so-called shell archives out of many files, preparing them
+ for transmission by electronic mail services; `unshar' helps unpack
+ these shell archives after reception. `uuencode' and `uudecode' are
+ POSIX compliant implementations of a pair of programs which transform
+ files into a format that can be safely transmitted across a 7-bit ASCII
+ link.
-The "4.4BSD-Lite" release is the last from the Computer Systems Research
-Group at the University of California at Berkeley. It has most of the BSD
-software system, except for a few files that remain proprietary. It is much
-more complete than the previous "Net2" release.
+ * Shellutils (SrcCD)
+ The Shellutils are: `basename', `chroot', `date', `dirname', `echo',
+ `env', `expr', `factor', `false', `groups', `hostname', `id', `logname',
+ `nice', `nohup', `pathchk', `printenv', `printf', `pwd', `seq', `sleep',
+ `stty', `su', `tee', `test', `true', `tty', `uname', `uptime', `users',
+ `who', `whoami', & `yes'.
+ * Shogi (SrcCD)
-VMS Emacs and VMS Compiler Tapes
---------------------------------
+ Shogi is a Japanese game similar to Chess; a major difference is that
+ captured pieces can be returned into play.
-We offer two VMS tapes. One has just GNU Emacs 18.59 (none of the other
-software on the *Note Lisps/Emacs Tape::, is included). The other has GCC
-2.3.3, Bison 1.19 (to compile GCC), GAS 1.38 (to assemble GCC's output) and
-some library and include files (none of the other software on the *Note
-Languages Tape::, is included). We are not aware of a GDB port for VMS.
-Both VMS tapes have DEC VAX executables from which you can bootstrap, as the
-DEC VMS C compiler cannot compile GCC. We do not have executables for DEC
-Alpha VMS systems. Please do not ask us to devote effort to VMS support,
-because it is peripheral to the GNU Project.
+ GNU Shogi is a variant of GNU Chess; it implements the same features &
+ similar heuristics. As a new feature, sequences of partial board
+ patterns can be introduced to help the program play toward specific
+ opening patterns. It has both character and X display interfaces.
+ It is primarily supported by Matthias Mutz on behalf of the FSF.
+ * SIPP (SrcCD)
-CD-ROMs
-*******
+ SIPP is a library for photorealistically rendering 3D scenes. Scenes can
+ be illuminated by an arbitrary number of light sources; they are built up
+ of object hierarchies, with arbitrarily many subobjects and subsurfaces.
+ Surfaces can be rendered with either Phong, Gouraud, or flat shading.
+ The library supports programmable shaders and texture mapping.
-We offer these CD-ROMs:
+ * Smail (SrcCD)
- * *Note MS-DOS CD-ROM::, expected in September 1995.
+ Smail is a mail transport system, designed as a compatible drop-in
+ replacement for `sendmail'. It uses a much simpler configuration format
+ than `sendmail' and is designed to be setup with minimal effort.
- * *Note Debian GNU/Linux CD-ROM::, expected in late fall 1995.
+ * Smalltalk (SrcCD)
- * *Note Compiler Tools Binaries CD-ROM::.
+ GNU Smalltalk is an interpreted object-oriented programming language
+ system written in highly portable C. It has been ported to MS-DOS, many
+ Unixes, & other OSes. Features include a binary image save capability,
+ the ability to call user-written C code with parameters, an Emacs
+ editing mode, a version of the X protocol invocable from Smalltalk,
+ optional byte-code compilation and/or execution tracing, & automatically
+ loaded per-user initialization files. It implements all of the classes
+ & protocol in the book "Smalltalk-80: The Language", except for the
+ graphic user interface (GUI) related classes.
- * *Note June 1995 Source Code CD-ROM::.
+ * SNePS (SrcCD)
- * *Note May 1994 Source Code CD-ROM::.
+ SNePS is the Semantic Network Processing System. It is an
+ implementation of a fully intensional theory of propositional knowledge
+ representation and reasoning. SNePS runs under CLISP or GCL.
- * *Note November 1993 Source Code CD-ROM::.
+ * `spell' (SrcCD)
-Our CD-ROMs are in ISO 9660 format & can be mounted as a read-only file
-system on most computers. If your driver supports it you can mount each
-CD-ROM with "Rock Ridge" extensions (the MS-DOS CD-ROM is only in ISO 9660
-format) & it will look just like an ordinary Unix file system, rather than
-one full of truncated & otherwise mangled names that fit vanilla ISO 9660.
+ GNU `spell' is a clone of standard Unix `spell', implemented as a
+ wrapper to `ispell'.
-You can build most of the software without copying the sources off the CD.
-You only need enough disk space for object files and intermediate build
-targets.
+ * `stow' (SrcCD)
+ `stow' manages the installation of multiple software packages, keeping
+ them separate while making them appear (via symbolic links) to be
+ installed in the same place. For example, Emacs can be installed in
+ `/usr/local/stow/emacs' and Perl in `/usr/local/stow/perl', permitting
+ each to be administered separately, while with `stow' they will both
+ appear to be installed in `/usr/local'.
+ * Superopt (SrcCD)
-Pricing of the GNU CD-ROMs
---------------------------
+ Superopt is a function sequence generator that uses an exhaustive
+ generate-and-test approach to find the shortest instruction sequence for
+ a given function. You provide a function as input, a CPU to generate
+ code for, and how many instructions you want. Its use in GCC is
+ described in the `ACM SIGPLAN PLDI'92 Proceedings'. It supports: SPARC,
+ m68k, m68020, m88k, IBM POWER and PowerPC, AMD 29k, Intel x86 & 960,
+ Pyramid, DEC Alpha, Hitachi SH, & HP-PA.
-If a business or organization is ultimately paying, the June 1995 Source CD
-costs $240. It costs $60 if you, an individual, are paying out of your own
-pocket. The December 1994 Compiler Tools Binaries CD-ROM costs $220 for a
-business or organization, and $55 for an individual.
+ * Swarm (SrcCD)
+ Swarm is a software package for multi-agent simulation of complex systems
+ being developed at The Santa Fe Institute. Swarm is intended to be a
+ useful tool for researchers in a variety of disciplines, especially
+ artificial life. The basic architecture of Swarm is the simulation of
+ collections of concurrently interacting agents: with this architecture,
+ a large variety of agent based models can be implemented.
+ * `tar' (BinCD, SrcCD)
-What do the individual and company prices mean?
+ GNU `tar' includes multi-volume support, the ability to archive sparse
+ files, compression/decompression, remote archives, and special features
+ that allow `tar' to be used for incremental and full backups. GNU `tar'
+ uses an early draft of the POSIX 1003.1 `ustar' format which is
+ different from the final version. This will be corrected in the future.
-The software on our disk is free; anyone can copy it and anyone can run it.
-What we charge for is the physical disk and the service of distribution.
+ * Termcap Library (SrcCD) [FSFman]
-We charge two different prices depending on who is buying. When a company or
-other organization buys the June 1995 Source CD-ROM, we charge $240. When an
-individual buys the same disk, we charge just $60.
+ The GNU Termcap library is a drop-in replacement for `libtermcap.a' on
+ any system. It does not place an arbitrary limit on the size of Termcap
+ entries, unlike most other Termcap libraries. Included is source for the
+ `Termcap Manual' in Texinfo format (*note Documentation::.).
-This distinction is not a matter of who is allowed to use the software. In
-either case, once you have a copy, you can distribute as many copies as you
-wish, and there's no restriction on who can have or run them. The price
-distinction is entirely a matter of what kind of entity pays for the CD.
+ * Termutils (SrcCD)
-You, the reader, are certainly an individual, not a company. If you are
-buying a disk "in person", then you are probably doing so as an individual.
-But if you expect to be reimbursed by your employer, then the disk is really
-for the company; so please pay the company price and get reimbursed for it.
-We won't try to check up on you--we use the honor system--so please cooperate.
+ The Termutils package contains programs for controlling terminals.
+ `tput' is a portable way for shell scripts to use special terminal
+ capabilities. `tabs' is a program to set hardware terminal tab settings.
-Buying CDs at the company price is very helpful for GNU; just 140 Source CDs
-at that price supports an FSF programmer or tech writer for a year.
+ * TeX (SrcCD)
+ TeX is a document formatter that is used, among other things, by the FSF
+ for all its printed documentation. You will need it if you want to make
+ printed manuals. See `http://www.tug.org/web2c/'.
+ The Source Code CD-ROM contains a minimal TeX collection, sufficient to
+ process Texinfo files. For a complete TeX distribution, including both
+ sources and precompiled binaries for many platforms, consider teTeX.
+ This is available on CD-ROM (see `http://www.tug.org/texlive.html'), or
+ by FTP. The FTP instructions change too frequently to include them here;
+ see `ftp://ftp.tug.org/tex/unixtex.ftp'.
-Why is there an individual price?
+ * Texinfo (SrcCD) [FSFman]
-In the past, our distribution tapes have been ordered mainly by companies.
-The CD at the price of $240 provides them with all of our software for a much
-lower price than they would previously have paid for six different tapes. To
-lower the price more would cut into the FSF's funds very badly, and decrease
-the software development we can do.
+ Texinfo is a set of utilities (`makeinfo', `info', `install-info',
+ `texi2dvi', `texindex', & `texinfmt.el') which generate printed manuals,
+ plain ASCII text, & online hypertext documentation (called "Info"), &
+ can read online Info documents; Info files can also be read in Emacs.
+ Version 3 has both Emacs Lisp & standalone programs written in C or as
+ shell scripts. Texinfo mode for Emacs enables easy editing & updating
+ of Texinfo files. Source for the `Texinfo Manual' is included (*note
+ Documentation::.).
-However, for individuals, $240 is too high a price; hardly anyone could
-afford that. So we decided to make CDs available to individuals at the lower
-price of $60.
+ * Textutils (SrcCD)
+ The Textutils programs manipulate textual data. They include: `cat',
+ `cksum', `comm', `csplit', `cut', `expand', `fmt', `fold', `head',
+ `join', `md5sum', `nl', `od', `paste', `pr', `sort', `split', `sum',
+ `tac', `tail', `tr', `unexpand', `uniq', and `wc'.
+ * TIFF library (SrcCD)
-Is there a maximum price?
+ The TIFF library, `libtiff', is a library for manipulating Tagged Image
+ File Format files, a commonly used bitmap graphics format.
-Our stated prices are minimum prices. Feel free to pay a higher price if you
-wish to support GNU development more. The sky's the limit; we will accept as
-high a price as you can offer. Or simply give a donation (tax-deductible in
-the U.S.) to the Free Software Foundation, a tax-exempt public charity.
+ * Tile Forth (SrcCD)
+ Tile Forth is a 32-bit implementation of the Forth-83 standard written
+ in C, allowing it to be easily ported to new systems & extended with any
+ C-function (graphics, windowing, etc).
+ Many documented Forth libraries are available, e.g. top-down parsing,
+ multi-threads, & object-oriented programming.
-MS-DOS CD-ROM
--------------
+ * `time' (SrcCD)
-We expect to release our first CD-ROM for MS-DOS in September, 1995. Contact
-either address on page 1 for more information at that time. The MS-DOS CD
-will be packaged inside a book describing its contents. It will have all the
-sources and executables on the MS-DOS Diskettes. For details and version
-numbers, *note MS-DOS Diskettes::..
+ `time' reports (usually from a shell) the user, system, & real time used
+ by a process. On some systems it also reports memory usage, page
+ faults, etc.
+ * `ucblogo' (SrcCD)
+ `ucblogo' implements the classic teaching language, Logo.
-Debian GNU/Linux CD-ROM
------------------------
+ * `units'
-The FSF expects to ship a CD-ROM with Debian GNU/Linux on it in the late fall
-1995. This CD will be packaged inside a book describing its contents.
-m{No Value For "ergegrafkludge"} Debian GNU/Linux is a complete operating
-system for x86 machines, available in both source code and binary form. It
-is a GNU/Linux system--that is to say, a variant GNU system which uses Linux
-as the kernel. (All the systems now available which use the Linux kernel are
-GNU/Linux systems.)
+ GNU `units' converts between different units of measurement, such as
+ miles/gallon to km/liter. (It can only handle multiplicative scale
+ changes, so it cannot convert Celsius to Fahrenheit though it could
+ convert temperature differences between those temperatures scales.)
-Debian is being developed by Ian Murdock and the Debian Association in
-conjunction with the Free Software Foundation. We are distributing it as an
-interim measure until the GNU kernel (the Hurd) is ready for users.
+ * UUCP (SrcCD)
-Debian GNU/Linux is available for FTP at `ftp.cps.cmich.edu' in file
-`/pub/debian'. For more information about the Debian Project and how to get
-involved, see `/pub/gnu/GNUinfo/DEBIAN' on a GNU FTP host (*note How to Get
-GNU Software::. for a list).
+ GNU's UUCP system (written by Ian Lance Taylor) supports the `f', `g'
+ (all window & packet sizes), `v', `G', `t', `e', Zmodem, & two new
+ bidirectional (`i' & `j') protocols. With a BSD sockets library, it can
+ make TCP connections. With TLI libraries, it can make TLI connections.
+ Source is included for a manual (not yet published by the FSF).
+ * vera (SrcCD)
+ VERA (Virtual Entity of Relevant Acronyms) is a document listing
+ thousands of acronyms of the computer field.
-December 1994 Compiler Tools Binaries CD-ROM
---------------------------------------------
+ * viewfax (SrcCD)
-We are now offering a CD-ROM that contains executables for GNU compiler tools
-for some systems which lack a compiler. This enables the people who use
-these systems to compile GNU and other free software without having to buy a
-proprietary compiler. You can also use the GNU compilation system to compile
-your own C/C++/Objective-C programs.
+ Viewfax is a tool for displaying fax files on an X display. It can
+ display raw, digifax or tiff/f files, such as those received by HylaFAX.
-We hope to have more systems on each update of this CD. If you can help
-build binaries for new systems (especially those that don't come with a C
-compiler), or have one to suggest, please contact us at the addresses on page
-1.
+ * W3 (SrcCD)
-These packages:
+ W3 (written by William Perry in Emacs Lisp) is an extensible, advanced
+ World Wide Web browser that runs as part of Emacs. It supports all the
+ bells and whistles you find on the Web today, including frames, tables,
+ stylesheets, and much more. See
+ `http://www.cs.indiana.edu/elisp/w3/docs.html'.
- *DJGPP 1.12.m2 from GCC 2.6.0
- *GCC/G++/Objective-C 2.6.2
- *GNU C Library 1.09
- *GDB 4.13
- *Binutils 2.5.2
- *Bison 1.22
- *Emacs 19.26 (MS-DOS only)
- *Flex 2.4.7
- *Make 3.72.1
- *libg++ 2.6.1
+ * `wdiff' (SrcCD)
-On these platforms:
+ `wdiff' is a front-end to GNU `diff'. It compares two files, finding
+ the words deleted or added to the first to make the second. It has many
+ output formats and works well with terminals and pagers. `wdiff' is
+ very useful when two texts differ only by a few words and paragraphs
+ have been refilled. Plans are to merge this package into `diffutils'.
- *`i386-msdos'
- *`hppa1.1-hp-hpux9'
- *`sparc-sun-solaris2'
- *`sparc-sun-sunos4.1'
+ * `Wget' (SrcCD)
+ `Wget' non-interactively retrieves files from the WWW using HTTP & FTP.
+ It is suitable for use in shell scripts.
+ * `windows32api' (SrcCD)
-Source Code CD-ROMs
--------------------
+ `windows32' is a set of header files & import libraries that can be used
+ by GNU tools for compiling & linking programs to be run on Windows NT/95.
-We have several versions of our Source Code CD-ROMs available:
+ * WN (SrcCD)
- * *Note June 1995 Source Code CD-ROM::.
+ WN is a World Wide Web server designed to be secure and flexible. It
+ offers many different capabilities in pre-parsing files before passing
+ them to the client, and has a very different design from Apache and the
+ NCSA server.
- * *Note May 1994 Source Code CD-ROM::.
+ * X11 (SrcCD)
- * *Note November 1993 Source Code CD-ROM::.
+ We distribute Version 11, Release 6.3 of the X Window System with the
+ latest patches & bug fixes. X11 includes all of the core software,
+ documentation, contributed clients, libraries, & toolkits, games, etc.
-The older Source Code CDs will be available while supplies last at a reduced
-price; see the *note Free Software Foundation Order Form::..
+ While supplies last, we will distribute X11R5 on the November 1993
+ Source Code CD-ROM.
-All of the Source Code CDs also contain Texinfo source for the GNU manuals
-listed in *Note Documentation::.
+ * `xboard' (SrcCD)
-The VMS tapes' contents are *not* included. Many programs that are only on
-MS-DOS diskettes and not on the tapes are also *not* included. The contents
-of the MIT Scheme & X11 Optional tapes are *not* on the November 1993 & May
-1994 Source CDs. *Note Tapes:: & *Note MS-DOS Diskettes::.
+ `xboard' is a graphical chessboard for X Windows. It can serve as a
+ user interface to the Crafty or GNU chess programs, the Internet Chess
+ Servers, e-mail correspondence chess, or games saved in Portable Game
+ Notation.
-There are no precompiled programs on these Source CDs. You will need a C
-compiler (programs which need some other interpreter or compiler normally
-provide the C source for a bootstrapping program). We ship C compiler
-binaries for some systems on the *Note Compiler Tools Binaries CD-ROM::.
+ * `xgrabsc' (SrcCD)
+ `xgrabsc' is a screen capture program similar to `xwd' but with a
+ graphical user interface, more ways of selecting the part of the screen
+ to capture, & different types of output: Postscript, color Postscript,
+ xwd, bitmap, pixmap, & puzzle.
+ * `xinfo' (SrcCD)
-June 1995 Source Code CD-ROM - (VERSION NUMBERS NOT COMPLETELY UP TO DATE)
-............................
-
-We now have the sixth edition of our Source CD. This CD has Edition X.X for
-version 19 of the `GNU Emacs Lisp Reference Manual' & some additional
-software; not all FSF distributed software is included (*note Source Code
-CD-ROMs::.). It contains the following packages:
- *XXXXX UPDATE THIS LIST XXXXX*
- *acm 4.5
- *Autoconf 1.10
- *BASH 1.13.5
- *bc 1.02
- *Binutils 2.3
- *Bison 1.22
- *C Library 1.08
- *Calc 2.02c
- *Chess 4.0.69
- *CLISP 1994.01.08
- *Common Lisp 1.0
- *cpio 2.3
- *CVS 1.3
- *dc 0.2
- *DejaGnu 1.2
- *Diffutils 2.6
- *dld 3.2.3
- *doschk 1.1
- *ecc 1.2.1
- *ed 0.1
- *elib 0.06
- *Emacs 18.59
- *Emacs 19.23
- *es 0.84
- *f2c 1994.04.14
- *Fileutils 3.9
- *find 3.8
- *finger 1.37
- *flex 2.4.6
- *Fontutils 0.6
- *GAS 1.36.utah
- *GAS 2.2
- *Gawk 2.15.4
- *GCC 2.5.8
- *GDB 4.12
- *gdbm 1.7.1
- *Ghostscript 2.6.1
- *Ghostview 1.5
- *Ghostview for Windows 1.0
- *gmp 1.3.2
- *GNATS 3.2
- *GnuGo 1.1
- *gnuplot 3.5
- *gperf 2.1a
- *Graphics 0.17
- *grep 2.0
- *Groff 1.09
- *gzip 1.2.4
- *hello 1.3
- *hp2xx 3.1.4
- *indent 1.9.1
- *ispell 4.0
- *libg++ 2.5.3
- *m4 1.1
- *Make 3.71
- *MandelSpawn 0.07
- *mtools 2.0.7
- *MULE 1.0
- *NetFax 3.2.1
- *Nethack 3.1.3
- *NIHCL 3.0
- *nvi 1.11
- *Octave 1.0
- *Oleo 1.5
- *p2c 1.20
- *patch 2.1
- *PCL 1993.03.18
- *perl 4.036
- *ptx 0.3
- *rc 1.4
- *RCS 5.6.0.1
- *recode 3.3
- *regex 0.12
- *screen 3.5.2
- *sed 2.05
- *shellutils 1.9.4
- *Shogi 1.1.02
- *Smalltalk 1.1.1
- *Superopt 2.3
- *tar 1.11.2
- *Termcap 1.2
- *TeX 3.1
- *Texinfo 3.1
- *Textutils 1.9.1
- *Tile Forth 2.1
- *time 1.6
- *tput 1.0
- *UUCP 1.05
- *uuencode 1.0
- *wdiff 0.04
- *X11R6
- *xboard 3.0.9
- *xshogi 1.2.02
-
-
-
-May 1994 Source Code CD-ROM
-...........................
-
-We still have the fourth edition of our Source CD, at a reduced price. This
-CD has Edition 2.3 for version 19 of the `GNU Emacs Lisp Reference Manual' &
-some additional software; not all FSF distributed software is included (*note
-Source Code CD-ROMs::.). It contains these packages:
- *acm 4.5
- *Autoconf 1.10
- *BASH 1.13.5
- *bc 1.02
- *Binutils 2.3
- *Bison 1.22
- *C Library 1.08
- *Calc 2.02c
- *Chess 4.0.69
- *CLISP 1994.01.08
- *Common Lisp 1.0
- *cpio 2.3
- *CVS 1.3
- *dc 0.2
- *DejaGnu 1.2
- *Diffutils 2.6
- *dld 3.2.3
- *doschk 1.1
- *ecc 1.2.1
- *ed 0.1
- *elib 0.06
- *Emacs 18.59
- *Emacs 19.23
- *es 0.84
- *f2c 1994.04.14
- *Fileutils 3.9
- *find 3.8
- *finger 1.37
- *flex 2.4.6
- *Fontutils 0.6
- *GAS 1.36.utah
- *GAS 2.2
- *Gawk 2.15.4
- *GCC 2.5.8
- *GDB 4.12
- *gdbm 1.7.1
- *Ghostscript 2.6.1
- *Ghostview 1.5
- *Ghostview for Windows 1.0
- *gmp 1.3.2
- *GNATS 3.2
- *GnuGo 1.1
- *gnuplot 3.5
- *gperf 2.1a
- *Graphics 0.17
- *grep 2.0
- *Groff 1.09
- *gzip 1.2.4
- *hello 1.3
- *hp2xx 3.1.4
- *indent 1.9.1
- *ispell 4.0
- *libg++ 2.5.3
- *m4 1.1
- *Make 3.71
- *MandelSpawn 0.07
- *mtools 2.0.7
- *MULE 1.0
- *NetFax 3.2.1
- *Nethack 3.1.3
- *NIHCL 3.0
- *nvi 1.11
- *Octave 1.0
- *Oleo 1.5
- *p2c 1.20
- *patch 2.1
- *PCL 1993.03.18
- *perl 4.036
- *ptx 0.3
- *rc 1.4
- *RCS 5.6.0.1
- *recode 3.3
- *regex 0.12
- *screen 3.5.2
- *sed 2.05
- *shellutils 1.9.4
- *Shogi 1.1.02
- *Smalltalk 1.1.1
- *Superopt 2.3
- *tar 1.11.2
- *Termcap 1.2
- *TeX 3.1
- *Texinfo 3.1
- *Textutils 1.9.1
- *Tile Forth 2.1
- *time 1.6
- *tput 1.0
- *UUCP 1.05
- *uuencode 1.0
- *wdiff 0.04
- *X11R6
- *xboard 3.0.9
- *xshogi 1.2.02
-
-
-
-November 1993 Source Code CD-ROM
-................................
+ `xinfo' is an X-windows program for reading Info files. It uses a
+ special widget, which is available for use in other programs.
-We still have the third edition of our Source CD, at a reduced price. It
-contains X11R5, as we feel that people should have a choice between X11R5 and
-X11R6 until the latter is stable. This CD has Edition 2.2 for version 19 of
-the `GNU Emacs Lisp Reference Manual' & some additional software; not all FSF
-distributed software is included (*note Source Code CD-ROMs::.). It contains
-the following packages:
- *acm 3.1
- *Autoconf 1.7
- *BASH 1.13.4
- *bc 1.02
- *Binutils 1.9 2.3
- *Bison 1.22
- *C Library 1.06.7
- *Calc 2.02b
- *Chess 4.0p62
- *CLISP 93.11.08
- *cpio 2.3
- *CVS 1.3
- *dc 0.2
- *DejaGnu 1.0.1
- *Diffutils 2.6
- *dld 3.2.3
- *doschk 1.1
- *ecc 1.2.1
- *elib 0.06
- *Emacs 18.59
- *Emacs 19.21
- *es 0.84
- *f2c 1993.04.28
- *Fileutils 3.9
- *find 3.8
- *finger 1.37
- *flex 2.3.8
- *Fontutils 0.6
- *GAS 1.36.utah
- *GAS 1.38.1
- *GAS 2.2
- *Gawk 2.15.3
- *GCC 2.5.4
- *GDB 4.11
- *gdbm 1.7.1
- *Ghostscript 2.6.1
- *Ghostview 1.5
- *Ghostview for Windows 1.0
- *gmp 1.3.2
- *GNATS 3.01
- *GnuGo 1.1
- *gnuplot 3.5
- *gperf 2.1a
- *Graphics 0.17
- *grep 2.0
- *Groff 1.08
- *gzip 1.2.4
- *hello 1.3
- *hp2xx 3.1.3a
- *indent 1.8
- *Ispell 4.0
- *less 177
- *libg++ 2.5.1
- *m4 1.1
- *Make 3.69.1
- *MandelSpawn 0.06
- *mtools 2.0.7
- *MULE 1.0
- *NetFax 3.2.1
- *Nethack 3.1.3
- *NIHCL 3.0
- *Oleo 1.5
- *p2c 1.20
- *patch 2.1
- *PCL 93.03.18
- *perl 4.036
- *ptx 0.3
- *rc 1.4
- *RCS 5.6.0.1
- *recode 3.2.4
- *regex 0.12
- *screen 3.5.2
- *sed 1.18 2.03
- *Shellutils 1.9.1
- *Shogi 1.1p02
- *Smalltalk 1.1.1
- *Superopt 2.3
- *tar 1.11.2
- *Termcap 1.2
- *TeX 3.1
- *Texinfo 3.1
- *Tile Forth 2.1
- *time 1.6
- *time 1.6
- *tput 1.0
- *UUCP 1.04
- *uuencode 1.0
- *wdiff 0.04
- *X11R5
-
-
-
-
-MS-DOS Diskettes
-****************
-
-The FSF distributes some of the GNU software ported to MS-DOS, on 3.5inch
-1.44MB diskettes. These disks have both sources and executables.
-
-
-
-DJGPP Diskettes - (VERSION NUMBERS NOT COMPLETELY UP TO DATE)
----------------
+ * xmcd *Also see* `http://sunsite.unc.edu/~cddb/xmcd/' (SrcCD)
-We offer DJGPP on 30 diskettes. For further details, see *Note GNU
-Software::. The DJGPP diskettes contain the following:
-
- * bc 1.03
- * Binutils 2.4
- * Bison 1.22
- * cpio 2.3
- * Diffutils 2.6
- * doschk 1.1
- * Fileutils 3.9
- * Findutils 3.8
- * GAS 2.4
- * Gawk 2.15.5
- * GCC 2.6.0
- * GDB 4.12
- * Ghostscript 2.6.1
- * Ghostview for Windows 1.0
- * Groff 1.09
- * gzip 1.24
- * hello 1.3
- * indent 1.9
- * ispell 4.0
- * m4 1.2
- * Make 3.71
- * patch 2.1
- * sed 1.18
- * shellutils 1.9
- * Texinfo 3.1
- * texutils 1.9
- * wdiff 0.04
-
-
-
-Emacs Diskettes - (VERSION NUMBERS NOT COMPLETELY UP TO DATE)
----------------
+ `xmcd' is an X11-based CD player utility and `cda' is a command-line
+ driven, non-graphical CD audio player. `xmcd' is developed to use the
+ OSF/Motif API (version 1.1 and later) and can also be used with LessTif,
+ the free Motif clone.
-Two versions of GNU Emacs are included on the Emacs diskettes we distribute:
-GNU Emacs version 19.29 handles 8-bit character sets; the other, MULE version
-2.1, handles 16-bit character sets including Kanji.
+ In its evolution over the past few years, `xmcd' has established itself
+ as the premier CD player application for the X window system with an
+ attractive, easy-to-use user interface. It is feature-rich and runs on
+ virtually all of the popular Unix and OpenVMS platforms. It also
+ supports the widest array of CD-ROM and CD-R devices, including some
+ older SCSI-1 drives that do not work with other CD player applications.
+ The remote CD database query feature fully utilizes the Internet and
+ taps on a vast repository of CD artists/titles, track titles and other
+ information. Multi-disc changers are also supported.
+ Like many other CD player applications, `xmcd' supports a CD database of
+ disc and track titles and other information. A distinguishing feature
+ of `xmcd' is the ability to connect to a remote CD database server to
+ query this information. Many public Internet CD database servers have
+ been established around the world for this purpose, and `xmcd' also
+ allows the user to submit new CD entries to the master database.
+ * `xshogi' (SrcCD)
-Selected Utilities Diskettes - (NOT COMPLETELY UP TO DATE)
-----------------------------
+ `xshogi' is a graphical Shogi (Japanese Chess) board for the X Window
+ System. It can serve as a user interface to GNU Shogi, as a referee for
+ games between two humans, or as a client for the Internet Shogi Server.
-The GNUish MS-DOS Project ported GNU software to PC compatibles. Though the
-GNUish Project is no longer active, users still ask for these ports that were
-done several years ago. You can anonymous FTP files
-`/pub/gnu/MicrosPorts/MSDOS*' from `prep.ai.mit.edu' to find out how to
-access these ports over the Internet. We offer these programs on five
-diskettes. In general, this software will run on 8086 and 80286-based 16-bit
-machines; an 80386 is not required. Some of these utilities are necessarily
-missing features. Included are: `cpio', `diff', `find', `flex', `gdbm',
-`grep', `indent', `less', `m4', `make', `ptx', RCS, `sed', `shar', `sort', &
-Texinfo.
+ * `Ygl' (SrcCD)
+ `Ygl' emulates a subset of SGI's GL (Graphics Language) library under
+ X11 on most platforms with an ANSI C compiler (including GCC). It has
+ most two-dimensional graphics routines, the queue device & query
+ routines, double buffering, RGB mode with dithering, Fortran bindings,
+ etc.
+ * zlibc (SrcCD)
-Windows Diskette
-----------------
+ Zlibc is an uncompressing C library for GNU/Linux and SunOS systems. It
+ is a preloadable shared object that allows executables to uncompress the
+ datafiles that they need on the fly. No kernel patch, no recompilation
+ of these executables and no recompilation of the libraries is needed;
+ the package overrides the `open' function (and other system call
+ functions) in the shared library.
-We offer GNU Chess and `gnuplot' for Microsoft Windows on a single diskette.
+
+Program/Package Cross Reference
+*******************************
+Here is a list of the package each GNU program or library is in. You can FTP
+the current list in the file `/pub/gnu/ProgramIndex' from a GNU FTP host
+(*note How to Get GNU Software::.).
+
+ * 4dview geomview
+
+ * a2p perl
+ * a2x xopt
+ * ac bsd44
+ * accton bsd44
+ * ackpfd phttpd
+ * acl bsd44
+ * acm acm
+ * acms acm
+ * addbbox geomview
+ * addftinfo Groff
+ * adventure bsd44
+ * afm2tfm TeX
+ * aid ID Utils
+ * amd bsd44
+ * ansitape bsd44
+ * AnswerGarden xopt
+ * apply bsd44
+ * appres xreq
+ * apropos bsd44
+ * ar Binutils
+ * arithmetic bsd44
+ * arp bsd44
+ * atc bsd44
+ * authwn WN
+ * autoconf Autoconf
+ * autoheader Autoconf
+ * automake Automake
+ * autoreconf Autoconf
+ * autoscan Autoconf
+ * autoupdate Autoconf
+ * auto_box xopt
+ * auto_box xreq
+
+ * b2m Emacs
+ * backgammon bsd44
+ * bad144 bsd44
+ * badsect bsd44
+ * banner bsd44
+ * basename Shellutils
+ * bash BASH
+ * battlestar bsd44
+ * bc bc
+ * bcd bsd44
+ * bdes bsd44
+ * bdftops Ghostscript
+ * beach_ball xopt
+ * beach_ball xreq
+ * beach_ball2 xopt
+ * bibtex TeX
+ * biff bsd44
+ * bison Bison
+ * bitmap xreq
+ * boggle bsd44
+ * bpltobzr Fontutils
+ * bugfiler bsd44
+ * buildhash Ispell
+ * bzrto Fontutils
+
+ * c++ GCC
+ * c++filt Binutils
+ * c2ph perl
+ * ca100 xopt
+ * caesar bsd44
+ * cal bsd44
+ * calendar bsd44
+ * canfield bsd44
+ * cat Textutils
+ * cbars wdiff
+ * cc GCC
+ * cc1 GCC
+ * cc1obj GCC
+ * cc1plus GCC
+ * cccp GCC
+ * cdwrite mkisofs
+ * cfengine cfengine
+ * cgi Spinner
+ * charspace Fontutils
+ * checknr bsd44
+ * chess bsd44
+ * chflags bsd44
+ * chgrp Fileutils
+ * ching bsd44
+ * chmod Fileutils
+ * chown Fileutils
+ * chpass bsd44
+ * chroot bsd44
+ * ci RCS
+ * cksum Textutils
+ * cktyps g77
+ * clisp CLISP
+ * clri bsd44
+ * cmail xboard
+ * cmmf TeX
+ * cmodext xopt
+ * cmp Diffutils
+ * co RCS
+ * col bsd44
+ * colcrt bsd44
+ * colrm bsd44
+ * column bsd44
+ * comm Textutils
+ * compress bsd44
+ * comsat bsd44
+ * connectd bsd44
+ * cp Fileutils
+ * cpicker xopt
+ * cpio cpio
+ * cpp GCC
+ * cppstdin perl
+ * cribbage bsd44
+ * crock xopt
+ * csh bsd44
+ * csplit Textutils
+ * ctags Emacs
+ * ctwm xopt
+ * cu UUCP
+ * cut Textutils
+ * cvs CVS
+ * cvscheck CVS
+ * cvtmail Emacs
+ * cxterm xopt
+
+ * d Fileutils
+ * date Shellutils
+ * dc bc
+ * dd Fileutils
+ * ddd DDD
+ * defid ID Utils
+ * delatex TeX
+ * demangle Binutils
+ * descend CVS
+ * detex TeX
+ * df Fileutils
+ * dhtppd phttpd
+ * diff Diffutils
+ * diff3 Diffutils
+ * diffpp enscript
+ * digest-doc Emacs
+ * dipress bsd44
+ * dir Fileutils
+ * dircolors Fileutils
+ * dirname Shellutils
+ * dish xopt
+ * disklabel bsd44
+ * diskpart bsd44
+ * dld dld
+ * dm bsd44
+ * dmesg bsd44
+ * doschk doschk
+ * dox xopt
+ * du Fileutils
+ * dump bsd44
+ * dump mkisofs
+ * dumpfs bsd44
+ * dvi2tty TeX
+ * dvicopy TeX
+ * dvips TeX
+ * dvitype TeX
+
+ * ecc ecc
+ * echo Shellutils
+ * ed ed
+ * edit-pr GNATS
+ * editres xreq
+ * edquota bsd44
+ * eeprom bsd44
+ * egrep grep
+ * eid ID Utils
+ * emacs Emacs
+ * emacsclient Emacs
+ * emacsserver Emacs
+ * emacstool Emacs
+ * emu xopt
+ * enscript enscript
+ * env Shellutils
+ * eqn Groff
+ * error bsd44
+ * es es
+ * esdebug es
+ * etags Emacs
+ * ex nvi
+ * example geomview
+ * exicyclog Exim
+ * exigrep Exim
+ * exim Exim
+ * eximon Exim
+ * eximon Exim
+ * eximstats Exim
+ * exinext Exim
+ * exiwhat Exim
+ * expand Textutils
+ * expect DejaGnu
+ * expr Shellutils
+ * exterm xopt
+
+ * f2c f2c
+ * factor bsd44
+ * fakemail Emacs
+ * false Shellutils
+ * fastboot bsd44
+ * fax2ps HylaFAX
+ * faxalter HylaFAX
+ * faxanswer HylaFAX
+ * faxcover HylaFAX
+ * faxd HylaFAX
+ * faxd.recv HylaFAX
+ * faxmail HylaFAX
+ * faxquit HylaFAX
+ * faxrcvd HylaFAX
+ * faxrm HylaFAX
+ * faxstat HylaFAX
+ * fc f2c
+ * fdraw xopt
+ * ffe g77
+ * fgrep grep
+ * fid ID Utils
+ * file bsd44
+ * find Findutils
+ * find2perl perl
+ * finger Finger
+ * fingerd Finger
+ * fish bsd44
+ * fixfonts Texinfo
+ * fixinc.svr4 GCC
+ * fixincludes GCC
+ * flex flex
+ * flex++ flex
+ * flythrough geomview
+ * fmt bsd44
+ * fnid ID Utils
+ * fold Textutils
+ * font2c Ghostscript
+ * fontconvert Fontutils
+ * forth Tile Forth
+ * forthicon Tile Forth
+ * forthtool Tile Forth
+ * fortune bsd44
+ * fpr bsd44
+ * freq Ispell
+ * freqtbl Ispell
+ * from bsd44
+ * fsck bsd44
+ * fsplit bsd44
+ * fstat bsd44
+ * ftp bsd44
+ * ftp Inetutils
+ * ftpd bsd44
+ * ftpd Inetutils
+
+ * g++ GCC
+ * gas Binutils
+ * gawk GAWK
+ * gcal gcal
+ * gcc GCC
+ * gcore bsd44
+ * gdb GDB
+ * genclass libg++
+ * geomstuff geomview
+ * gettext gettext
+ * getty bsd44
+ * gftodvi TeX
+ * gftopk TeX
+ * gftype TeX
+ * ghostview Ghostview
+ * gid ID Utils
+ * ginsu geomview
+ * git GIT
+ * gitaction GIT
+ * gitcmp GIT
+ * gitkeys GIT
+ * gitmatch GIT
+ * gitmount GIT
+ * gitps GIT
+ * gitredir GIT
+ * gitrgrep GIT
+ * gitview GIT
+ * gitwipe GIT
+ * gn GN
+ * gnans Gnans
+ * gnanslator Gnans
+ * gnats GNATS
+ * gnuchess Chess
+ * gnuchessc Chess
+ * gnuchessn Chess
+ * gnuchessr Chess
+ * gnuchessx Chess
+ * gnuclient gnuserv
+ * gnudoit gnuserv
+ * gnupdisp Shogi
+ * gnuplot gnuplot
+ * gnuplot_x11 gnuplot
+ * gnuserv gnuserv
+ * gnushogi Shogi
+ * gnushogir Shogi
+ * gnushogix Shogi
+ * go GnuGo
+ * gpc xopt
+ * gpc xreq
+ * gperf cperf
+ * gperf libg++
+ * gprof Binutils
+ * graffiti geomview
+ * graph Graphics
+ * grep grep
+ * grodvi Groff
+ * groff Groff
+ * grops Groff
+ * grotty Groff
+ * groups Shellutils
+ * gs Ghostscript
+ * gsbj Ghostscript
+ * gsdj Ghostscript
+ * gslj Ghostscript
+ * gslp Ghostscript
+ * gsnd Ghostscript
+ * gsrenderfont Fontutils
+ * gunzip gzip
+ * gvclock geomview
+ * gwm xopt
+ * gzexe gzip
+ * gzip gzip
+
+ * h2ph perl
+ * h2pl perl
+ * hack bsd44
+ * hangman bsd44
+ * head Textutils
+ * hello hello
+ * hexdump bsd44
+ * hexl Emacs
+ * hinge geomview
+ * hostname Shellutils
+ * hp2xx hp2xx
+ * hterm xopt
+ * htmlencode phttpd
+ * httpd apache
+ * httpdecode phttpd
+
+ * i18nOlwmV2 xopt
+ * i2mif xopt
+ * ico xopt
+ * ico xreq
+ * id Shellutils
+ * ident RCS
+ * ifconfig bsd44
+ * ifnames Autoconf
+ * ImageMagick xopt
+ * imageto Fontutils
+ * iman xopt
+ * imgrotate Fontutils
+ * indent indent
+ * indxbib Groff
+ * inetd bsd44
+ * inetd Inetutils
+ * info Texinfo
+ * inimf TeX
+ * init bsd44
+ * initex TeX
+ * inn bsd44
+ * install Fileutils
+ * iostat bsd44
+ * isodiag mkisofs
+ * isodump mkisofs
+ * ispell Ispell
+ * ixterm xopt
+ * ixx xopt
+
+ * join Textutils
+ * jot bsd44
+ * jove bsd44
+
+ * kdestroy bsd44
+ * kdump bsd44
+ * kermit bsd44
+ * kgames xopt
+ * kgmon bsd44
+ * kill bsd44
+ * kinit bsd44
+ * kinput2 xopt
+ * klist bsd44
+ * kpasswdd bsd44
+ * ksrvtgt bsd44
+ * kterm xopt
+ * ktrace bsd44
+
+ * lam bsd44
+ * larn bsd44
+ * lasergnu gnuplot
+ * last bsd44
+ * lastcomm bsd44
+ * latex TeX
+ * lclock xopt
+ * ld Binutils
+ * leave bsd44
+ * less less
+ * lesskey less
+ * libavcall.a ffcall
+ * libbfd.a Binutils
+ * libbfd.a GDB
+ * libbzr.a Fontutils
+ * libc.a C Library
+ * libcompat.a bsd44
+ * libcurses.a bsd44
+ * libcurses.a ncurses
+ * libdcurses.a ncurses
+ * libedit.a bsd44
+ * libF77.a f2c
+ * libF77.a g77
+ * libg++.a libg++
+ * libgdbm.a gdbm
+ * libgf.a Fontutils
+ * libgmp.a gmp
+ * libgnanslib.a Gnans
+ * libgnussl.a gnussl
+ * libI77.a f2c
+ * libI77.a g77
+ * libkvm.a bsd44
+ * libm.a bsd44
+ * libncurses.a ncurses
+ * libnihcl.a NIHCL
+ * libnihclmi.a NIHCL
+ * libnihclvec.a NIHCL
+ * libnls.a xreq
+ * libobjects.a libobjects
+ * liboctave.a Octave
+ * liboldX.a xreq
+ * libpbm.a Fontutils
+ * libPEXt.a xopt
+ * libpk.a Fontutils
+ * libresolv.a bsd44
+ * librpc.a bsd44
+ * libsipp.a SIPP
+ * libtcl.a DejaGnu
+ * libtelnet.a bsd44
+ * libterm.a bsd44
+ * libtermcap.a Termcap
+ * libtfm.a Fontutils
+ * libtiff.a tiff
+ * libutil.a bsd44
+ * libvacall.a ffcall
+ * libWc.a xopt
+ * libwidgets.a Fontutils
+ * libX.a xreq
+ * libXau.a xreq
+ * libXaw.a xreq
+ * libXcp.a xopt
+ * libXcu.a xopt
+ * libXdmcp.a xreq
+ * libXmp.a xopt
+ * libXmu.a xreq
+ * libXO.a xopt
+ * libXop.a xopt
+ * libXp.a xopt
+ * libXpex.a xopt
+ * libXt.a xopt
+ * libXt.a xreq
+ * libXwchar.a xopt
+ * liby.a bsd44
+ * libYgl.a Ygl
+ * lid ID Utils
+ * limn Fontutils
+ * listres xopt
+ * listres xreq
+ * lkbib Groff
+ * ln Fileutils
+ * locate Findutils
+ * lock bsd44
+ * logcvt-ip2n phttpd
+ * logger bsd44
+ * login bsd44
+ * logname Shellutils
+ * logo ucblogo
+ * lookbib Groff
+ * lorder bsd44
+ * lpr bsd44
+ * ls Fileutils
+ * lynx lynx
+
+ * m4 m4
+ * mail bsd44
+ * mail-files Sharutils
+ * mailq smail
+ * mailshar Sharutils
+ * make make
+ * make-docfile Emacs
+ * make-path Emacs
+ * makeindex TeX
+ * makeinfo Texinfo
+ * MakeTeXPK TeX
+ * man bsd44
+ * man-macros Groff
+ * maniview geomview
+ * mattrib mtools
+ * maze xopt
+ * maze xreq
+ * mazewar xopt
+ * mc mc
+ * mcd mtools
+ * mcopy mtools
+ * mcserv mc
+ * md5sum Textutils
+ * mdel mtools
+ * mdir mtools
+ * me-macros Groff
+ * medit2gv geomview
+ * merge RCS
+ * mesg bsd44
+ * mf TeX
+ * mformat mtools
+ * mft TeX
+ * mgdiff xopt
+ * mh bsd44
+ * mille bsd44
+ * mkafmmap enscript
+ * mkcache GN
+ * mkdep bsd44
+ * mkdir Fileutils
+ * mkfifo Fileutils
+ * mkid ID Utils
+ * mkisofs mkisofs
+ * mklocale bsd44
+ * mkmanifest mtools
+ * mkmf bsd44
+ * mkmodules CVS
+ * mknod Fileutils
+ * mkstr bsd44
+ * mlabel mtools
+ * mm-macros Groff
+ * mmd mtools
+ * monop bsd44
+ * more bsd44
+ * morse bsd44
+ * mount bsd44
+ * mountd bsd44
+ * movemail Emacs
+ * mprof bsd44
+ * mrd mtools
+ * mread mtools
+ * mren mtools
+ * ms-macros Groff
+ * msgcmp gettext
+ * msgfmt gettext
+ * msgmerge gettext
+ * msgs bsd44
+ * msgunfmt gettext
+ * mst Smalltalk
+ * mt cpio
+ * mterm xopt
+ * mtree bsd44
+ * mtype mtools
+ * mule MULE
+ * muncher xopt
+ * mv Fileutils
+ * mvdir Fileutils
+ * mwrite mtools
+
+ * NDview geomview
+ * nethack NetHack
+ * netstat bsd44
+ * newfs bsd44
+ * nfsd bsd44
+ * nfsiod bsd44
+ * nfsstat bsd44
+ * nice Shellutils
+ * nl Textutils
+ * nlmconv Binutils
+ * nm Binutils
+ * nohup Shellutils
+ * nose geomview
+ * notify HylaFAX
+ * nroff Groff
+ * number bsd44
+
+ * objc GCC
+ * objcopy Binutils
+ * objdump Binutils
+ * objective-c GCC
+ * obst-boot OBST
+ * obst-CC OBST
+ * obst-cct OBST
+ * obst-cgc OBST
+ * obst-cmp OBST
+ * obst-cnt OBST
+ * obst-cpcnt OBST
+ * obst-csz OBST
+ * obst-dir OBST
+ * obst-dmp OBST
+ * obst-gen OBST
+ * obst-gsh OBST
+ * obst-init OBST
+ * obst-scp OBST
+ * obst-sil OBST
+ * obst-stf OBST
+ * oclock xreq
+ * octave Octave
+ * od Textutils
+ * oleo Oleo
+ * ora-examples xopt
+
+ * p2c p2c
+ * pagesize bsd44
+ * palette xopt
+ * pascal bsd44
+ * passwd bsd44
+ * paste Textutils
+ * patch patch
+ * patgen TeX
+ * pathalias bsd44
+ * pathchk Shellutils
+ * pathto smail
+ * pax bsd44
+ * pbmplus xopt
+ * perl perl
+ * pfbtops Groff
+ * phantasia bsd44
+ * phttpd phttpd
+ * pic Groff
+ * pico pine
+ * pig bsd44
+ * pine pine
+ * ping bsd44
+ * pixedit xopt
+ * pixmap xopt
+ * pktogf TeX
+ * pktype TeX
+ * plaid xopt
+ * plot2fig Graphics
+ * plot2plot Graphics
+ * plot2ps Graphics
+ * plot2tek Graphics
+ * pltotf TeX
+ * pollrcvd HylaFAX
+ * pom bsd44
+ * pooltype TeX
+ * portmap bsd44
+ * ppt bsd44
+ * pr Textutils
+ * pr-addr GNATS
+ * pr-edit GNATS
+ * primes bsd44
+ * printenv Shellutils
+ * printf Shellutils
+ * protoize GCC
+ * proxygarb Spinner
+ * ps bsd44
+ * ps2ascii Ghostscript
+ * ps2epsi Ghostscript
+ * ps2fax HylaFAX
+ * psbb Groff
+ * pstat bsd44
+ * psycho xopt
+ * ptester phttpd
+ * ptx ptx
+ * pubdic+ xopt
+ * puzzle xopt
+ * puzzle xreq
+ * pwd Shellutils
+ * pyramid xopt
+
+ * query-pr GNATS
+ * quiz bsd44
+ * quot bsd44
+ * quota bsd44
+ * quotacheck bsd44
+ * quotaon bsd44
+
+ * rain bsd44
+ * random bsd44
+ * ranlib Binutils
+ * rbootd bsd44
+ * rc rc
+ * rcp bsd44
+ * rcp Inetutils
+ * rcs RCS
+ * rcs-to-cvs CVS
+ * rcs2log Emacs
+ * rcsdiff RCS
+ * rcsfreeze RCS
+ * rcsmerge RCS
+ * rdist bsd44
+ * reboot bsd44
+ * recode recode
+ * recvstats HylaFAX
+ * red ed
+ * refer Groff
+ * remsync Sharutils
+ * renice bsd44
+ * repquota bsd44
+ * restore bsd44
+ * rev bsd44
+ * rexecd bsd44
+ * rexecd Inetutils
+ * rlog RCS
+ * rlogin bsd44
+ * rlogin Inetutils
+ * rlogind bsd44
+ * rlogind Inetutils
+ * rm Fileutils
+ * rmail bsd44
+ * rmdir Fileutils
+ * rmt cpio
+ * rmt tar
+ * robots bsd44
+ * rogue bsd44
+ * route bsd44
+ * routed bsd44
+ * rr xopt
+ * rs bsd44
+ * rsh bsd44
+ * rsh Inetutils
+ * rshd bsd44
+ * rshd Inetutils
+ * rsmtp smail
+ * runq smail
+ * runtest DejaGnu
+ * runtest.exp DejaGnu
+ * ruptime bsd44
+ * rwho bsd44
+ * rwhod bsd44
+
+ * s2p perl
+ * sail bsd44
+ * saoimage SAOimage
+ * savecore bsd44
+ * sc bsd44
+ * sccs bsd44
+ * sccs2rcs CVS
+ * scdisp xopt
+ * screen screen
+ * script bsd44
+ * scsiformat bsd44
+ * sctext xopt
+ * sdiff Diffutils
+ * sed sed
+ * send-pr GNATS
+ * sendfax HylaFAX
+ * sendmail bsd44
+ * sgi2fax HylaFAX
+ * sgn GN
+ * sh bsd44
+ * shar Sharutils
+ * shinbun xopt
+ * shogi Shogi
+ * showfont xopt
+ * showmount bsd44
+ * shutdown bsd44
+ * size Binutils
+ * sj3 xopt
+ * sjxa xopt
+ * slattach bsd44
+ * sleep Shellutils
+ * sliplogin bsd44
+ * smail smail
+ * smtpd smail
+ * snake bsd44
+ * snftobdf xopt
+ * soelim Groff
+ * sort Textutils
+ * sos2obst OBST
+ * spider xopt
+ * split Textutils
+ * startslip bsd44
+ * stereo geomview
+ * stf OBST
+ * strings Binutils
+ * strip Binutils
+ * stty Shellutils
+ * su Shellutils
+ * sum Textutils
+ * superopt Superopt
+ * swapon bsd44
+ * sweep geomview
+ * sync bsd44
+ * sysctl bsd44
+ * syslog Inetutils
+ * syslogd bsd44
+ * syslogd Inetutils
+ * systat bsd44
+
+ * tabs Termutils
+ * tac Textutils
+ * tackdown geomview
+ * tail Textutils
+ * taintperl perl
+ * talk bsd44
+ * talk Inetutils
+ * talkd bsd44
+ * talkd Inetutils
+ * tangle TeX
+ * tar tar
+ * tbl Groff
+ * tcal gcal
+ * tcl DejaGnu
+ * tclsh DejaGnu
+ * tcopy bsd44
+ * tcp Emacs
+ * tee Shellutils
+ * tek2plot Graphics
+ * telnet bsd44
+ * telnet Inetutils
+ * telnetd bsd44
+ * telnetd Inetutils
+ * test Shellutils
+ * test-g++ DejaGnu
+ * test-tool DejaGnu
+ * tetris bsd44
+ * tex TeX
+ * tex3patch Texinfo
+ * texi2dvi Texinfo
+ * texindex Texinfo
+ * texspell TeX
+ * textfmt HylaFAX
+ * tfmtodit Groff
+ * tftopl TeX
+ * tftp bsd44
+ * tftp Inetutils
+ * tftpd bsd44
+ * tftpd Inetutils
+ * tgrind TeX
+ * time time
+ * timed bsd44
+ * timer Emacs
+ * timex xopt
+ * tip bsd44
+ * tkpostage xopt
+ * tn3270 bsd44
+ * togeomview geomview
+ * touch Fileutils
+ * tput Termutils
+ * tr Textutils
+ * traceroute bsd44
+ * transcript HylaFAX
+ * transfig xopt
+ * transformer geomview
+ * trek bsd44
+ * trigrp geomview
+ * trn3 bsd44
+ * troff Groff
+ * trpt bsd44
+ * trsp bsd44
+ * true Shellutils
+ * tset bsd44
+ * tsort bsd44
+ * tty Shellutils
+ * ttygnans Gnans
+ * tunefs bsd44
+ * tupdate gettext
+ * tvtwm xopt
+ * twm xreq
+
+ * ul bsd44
+ * ulpc Spinner
+ * umount bsd44
+ * uname Shellutils
+ * uncompress gzip
+ * unexpand Textutils
+ * unifdef bsd44
+ * unify wdiff
+ * uniq Textutils
+ * unprotoize GCC
+ * unshar Sharutils
+ * unvis bsd44
+ * update bsd44
+ * updatedb Findutils
+ * users Shellutils
+ * uuchk UUCP
+ * uucico UUCP
+ * uuconv UUCP
+ * uucp UUCP
+ * uucpd bsd44
+ * uucpd Inetutils
+ * uudecode Sharutils
+ * uudir UUCP
+ * uuencode Sharutils
+ * uulog UUCP
+ * uuname UUCP
+ * uupath smail
+ * uupick UUCP
+ * uurate UUCP
+ * uusched UUCP
+ * uustat UUCP
+ * uuto UUCP
+ * uux UUCP
+ * uuxqt UUCP
+
+ * v Fileutils
+ * vacation bsd44
+ * vandal xopt
+ * vcdiff Emacs
+ * vdir Fileutils
+ * vftovp TeX
+ * vgrind bsd44
+ * vi nvi
+ * viewres xopt
+ * viewres xreq
+ * vine xopt
+ * vipw bsd44
+ * virmf TeX
+ * virtex TeX
+ * vis bsd44
+ * vmstat bsd44
+ * vptovf TeX
+
+ * w bsd44
+ * waisgn GN
+ * wakeup Emacs
+ * wall bsd44
+ * wargames bsd44
+ * wc Textutils
+ * wdiff wdiff
+ * weave TeX
+ * what bsd44
+ * whatis bsd44
+ * whereis bsd44
+ * who Shellutils
+ * whoami Shellutils
+ * whois bsd44
+ * window bsd44
+ * winterp xopt
+ * wish DejaGnu
+ * wn WN
+ * wndex WN
+ * worm bsd44
+ * worms bsd44
+ * write bsd44
+ * wump bsd44
+
+ * x11perf xreq
+ * x2p perl
+ * xalarm xopt
+ * xancur xopt
+ * xargs Findutils
+ * xauth xreq
+ * xbfe Fontutils
+ * xbiff xopt
+ * xbiff xreq
+ * xboard xboard
+ * xboing xopt
+ * xbuffy3 xopt
+ * xcalc xopt
+ * xcalc xreq
+ * xcalendar xopt
+ * xcdplayer xopt
+ * xcell xopt
+ * xclipboard xreq
+ * xclock xreq
+ * xcmdmenu xopt
+ * xcms xopt
+ * xcmsdb xreq
+ * xcmstest xreq
+ * xco xopt
+ * xcolorize xopt
+ * xcolors xopt
+ * xconsole xreq
+ * xcrtca xopt
+ * xdaliclock xopt
+ * xdiary xopt
+ * xditview Groff
+ * xditview xopt
+ * xditview xreq
+ * xdm xreq
+ * xdpyinfo xreq
+ * xdu xopt
+ * xdvi TeX
+ * xdvi xopt
+ * xdvorak xopt
+ * xearth xopt
+ * xed xopt
+ * xedit xopt
+ * xedit xreq
+ * xev xopt
+ * xev xreq
+ * xexit xopt
+ * xeyes xopt
+ * xeyes xreq
+ * xfd xreq
+ * xfed xopt
+ * xfedor xopt
+ * xfeoak xopt
+ * xferstats HylaFAX
+ * xfig xopt
+ * xfontsel xopt
+ * xfontsel xreq
+ * xforecast xopt
+ * xgas xopt
+ * xgas xreq
+ * xgc xopt
+ * xgc xreq
+ * xgettext gettext
+ * xhearts xopt
+ * xhelp xopt
+ * xhost xreq
+ * xinit xreq
+ * xkeycaps xopt
+ * xkill xreq
+ * xlax xopt
+ * xlayout xopt
+ * xlbiff xopt
+ * xless xopt
+ * xload xopt
+ * xload xreq
+ * xlogin xopt
+ * xlogo xreq
+ * xlsatoms xreq
+ * xlsclients xreq
+ * xlsfonts xreq
+ * xmag xreq
+ * xmail xopt
+ * xmailbox xopt
+ * xmailwatcher xopt
+ * xman xopt
+ * xman xreq
+ * xmandel xopt
+ * xmessage xopt
+ * xmeter xopt
+ * xmh xreq
+ * xmh-icons xopt
+ * xmh.editor xopt
+ * xmodmap xreq
+ * xmon xopt
+ * xmove xopt
+ * xmphone xopt
+ * xpd xopt
+ * xphoon xopt
+ * xpipeman xopt
+ * xplot Graphics
+ * xpostit xopt
+ * xpr xopt
+ * xpr xreq
+ * xprompt xopt
+ * xproof xopt
+ * xprop xreq
+ * xpserv xopt
+ * xrdb xreq
+ * xrefresh xreq
+ * xrsh xopt
+ * xrubik xopt
+ * xrunclient xopt
+ * xscope xopt
+ * xscreensaver xopt
+ * xsession xopt
+ * xset xreq
+ * xsetroot xreq
+ * xshogi xshogi
+ * xstdcmap xreq
+ * xstr bsd44
+ * xtalk xopt
+ * xterm xreq
+ * xterm_color xopt
+ * xtetris xopt
+ * xTeXcad.13 xopt
+ * xtiff xopt
+ * xtokid ID Utils
+ * xtree xopt
+ * xtv xopt
+ * xwd xreq
+ * xwininfo xreq
+ * xwud xreq
+
+ * yacc bsd44
+ * yes Shellutils
+ * youbin xopt
+ * yow Emacs
+
+ * zcat gzip
+ * zcmp gzip
+ * zdiff gzip
+ * zforce gzip
+ * zgrep gzip
+ * zmore gzip
+ * znew gzip
+
+ * [ Shellutils
+
+
+
+
+
-Tape & CD-ROM Subscription Service
-**********************************
+CD-ROMs
+*******
-If you do not have net access, our subscription service enables you to stay
-current with the latest GNU developments. For a one-time cost equivalent to
-three tapes or CD-ROMs (plus shipping in some cases), we will ship you four
-new versions of the tape of your choice or the Source Code CD-ROM. The tapes
-are sent each quarter; the CD-ROMs are sent as they are issued (which is
-between two and four times a year.)
+We have two series of CD-ROMs: the Source Code CD-ROM, and the Compiler
+Tools Binaries CD-ROM.
-Regularly, we will send you a new version of an Lisps/Emacs, Languages,
-Utilities, or X Window System (X11R6) Required tape or the Source CD-ROM.
-The MIT Scheme and X Window System Optional tapes are not changed often
-enough to warrant quarterly updates. We do not yet know if we will be
-offering subscriptions to the Compiler Tools Binaries or our new CD-ROMs.
+Our CDs are in ISO 9660 format & can be mounted as a read-only file system on
+most computers. If your driver supports it, you can mount each CD with "Rock
+Ridge" extensions & it will look like a regular Unix file system, rather than
+one full of truncated & otherwise mangled names that fit vanilla ISO 9660.
-Since Emacs 19 is on the Lisps/Emacs Tape and the Source CD-ROM, a
-subscription to either is an easy way to keep current with Emacs 19 as it
-evolves.
+You can build most of the software without copying the sources off the CD.
+You only need enough disk space for object files and intermediate build
+targets.
-A subscription is an easy way to keep up with the regular bug fixes to the X
-Window System. We update the X11R6 Required tape as fixes and patches are
-issued throughout the year. Each new edition of the *Note Source Code
-CD-ROMs::, also has updated sources for the X Window System.
+
-Please note: In two cases, you must pay 4 times the normal shipping required
-for a single order when you pay for each subscription. If you're in Alaska,
-Hawaii, or Puerto Rico you must add $20.00 for shipping for each
-subscription. If you're outside of U.S., Canada, and Puerto Rico, you have
-to add $80.00 for each subscription. See "Unix and VMS Software" & "Shipping
-Instructions" on the *note Free Software Foundation Order Form::..
+Pricing of the GNU CD-ROMs
+--------------------------
+If a business or organization is ultimately paying, the current GNU Source
+CD set costs $240. The set costs $60 if you, an individual, are paying out
+of your own pocket. The current Compiler Tools Binaries CD-ROM costs $220
+for a business or organization, and $55 for an individual.
+
-The Deluxe Distribution
-***********************
+What Do the Different Prices Mean?
+..................................
-The Free Software Foundation has been asked repeatedly to create a package
-that provides executables for all of our software. Normally we offer only
-sources. In addition to providing binaries with the source code, the Deluxe
-Distribution includes a complete set of our printed manuals and reference
-cards.
+The software on our disks is free; anyone can copy it and anyone can run it.
+What we charge for is the physical disk and the service of distribution.
-The FSF Deluxe Distribution contains the binaries and sources to hundreds of
-different programs including GNU Emacs, the GNU C Compiler, the GNU Debugger,
-the complete X Window System, and all the GNU utilities.
+We charge two different prices depending on who is buying. When a company
+or other organization buys the Source CD-ROMs, we charge $240. When an
+individual buys the same CD-ROMs, we charge just $60. This distinction is
+not a matter of who is allowed to use the software. In either case, once
+you have a copy, you can distribute as many copies as you wish and there's
+no restriction on who can have or run them. The price distinction is
+entirely a matter of what kind of entity pays for the CDs.
-We will make a Deluxe Distribution for any machine, with any operating
-system. We will send someone to your office to do the compilation, if we
-can't find a suitable machine close to us! However, we can only compile the
-programs that already support your chosen machine and system - porting is a
-separate matter (if you wish to commission a port, see the GNU Service
-Directory, details in *Note Free Software Support::). Compiling all these
-programs take time; a Deluxe Distribution for an unusual machine will take
-longer to produce then one for a common machine. Please contact the FSF
-office if you have any questions.
-
-We supply the software in one of these tape formats in Unix `tar' format:
-1600 or 6250bpi 1/2in reel, Sun DC300XLP 1/4in cartridge - QIC24,
-Hewlett-Packard 16-track DC600HC 1/4in cartridge, IBM RS/6000 1/4in cartridge
-- QIC 150, Exabyte 8mm cartridge, or DAT 4mm cartridge. If your computer
-cannot read any of these, please contact us to see if we can handle your
-format.
-
-The manuals included are one each of the `Bison', `Calc', `Gawk', `GNU C
-Compiler', `GNU C Library', `GDB', `Flex', `GNU Emacs Lisp Reference',
-`Programming in Emacs Lisp: An Introduction', `Make', `Texinfo', & `Termcap'
-manuals; six copies of the `GNU Emacs' manual; and a packet of ten reference
-cards each for GNU Emacs, Bison, Calc, Flex, & GDB. Every Deluxe
-Distribution also includes a copy of the latest editions of our CD-ROMs
-(including the MS-DOS CD & the Debian GNU/Linux CD when they are available)
-that contain sources of our software & compiler tool binaries for some
-systems. The MS-DOS CD is in ISO 9660 format. The other CDs are in ISO 9660
-format with Rock Ridge extensions.
+You, the reader, are certainly an individual, not a company. If you are
+buying a disk "in person", then you are probably doing so as an individual.
+But if you expect to be reimbursed by your employer, then the disk is really
+for the company; so please pay the company price and get reimbursed for it.
+We won't try to check up on you--we use the honor system--so please cooperate.
-The price of the Deluxe Distribution is $5000 (shipping included). These
-sales provide enormous financial assistance to help the FSF develop more free
-software. To order, please fill out the "Deluxe Distribution" section on the
-*note Free Software Foundation Order Form::. and send it to:
+Buying CDs at the company price is very helpful for GNU; just
+150 Source CDs at that price support an FSF programmer or tech writer for a
+year.
- Free Software Foundation, Inc.
- 59 Temple Place -- Suite 330
- Boston, MA 02111--1307
- USA
+
- Telephone: +1-617-542-5942
- Fax (including Japan): +1-617-542-2652
- Free Dial Fax (in Japan):
- 0031-13-2473 (KDD)
- 0066-3382-0158 (IDC)
- Electronic mail: gnu@prep.ai.mit.edu
+Why Is There an Individual Price?
+.................................
+In the past, our distribution tapes were ordered mainly by companies. The CD
+at the price of $240 provides them with all of our software for a much lower
+price than they would previously have paid for six different tapes. To lower
+the price more would cut into the FSF's funds very badly and decrease the
+software development we can do.
+However, for individuals, $240 is too high a price; hardly anyone could
+afford that. So we decided to make CDs available to individuals at the lower
+price of $60.
-FSF T-shirt
-***********
+
-Our latest T-shirt has artwork by Berkeley, CA artist Etienne Suvasa. The
-front has the ever-popular picture of GNArnold from the `Flex Manual', while
-the back has the Preamble to the GNU General Public License.
+Is There a Maximum Price?
+.........................
-They are available in two colors, Natural & Black. Natural is an off-white,
-unbleached, undyed, environment-friendly cotton, printed with black ink, & is
-great for tye-dyeing or displaying as is. Black is printed with white ink &
-is perfect for late night hacking. All shirts are thick 100% cotton, & are
-available in sizes M, L, XL & XXL. This shirt makes a great gift for your
-favorite hacker!
+Our stated prices are minimum prices. Feel free to pay a higher price if you
+wish to support GNU development more. The sky's the limit; we will accept as
+high a price as you can offer. Or simply give a donation (tax-deductible in
+the U.S.) to the Free Software Foundation, a tax-exempt public charity.
-The previous version of the T-shirt will be available while supplies last,
-but please contact the FSF to see if we have what you would like before
-ordering.
+
+January 1997 Compiler Tools Binaries CD-ROM
+-------------------------------------------
+In January 1997 we released the fourth edition of our CD-ROM that has
+binaries and complete sources for GNU compiler tools for some systems which
+lack a compiler. This enables the people who use these systems to compile
+GNU and other free software without having to buy a proprietary compiler.
+You can also use these GNU tools to compile your own C/C++/Objective-C
+programs. Older editions of this CD are available while supplies last at a
+reduced price; *Note Free Software Foundation Order Form::.
-Free Software Foundation Order Form
-***********************************
+We hope to have more systems on each update of this CD. If you can help
+build binaries for new systems (especially those that don't come with a C
+compiler), or have one to suggest, please contact us at the addresses on page
+1.
-All items are distributed with permission to copy and to redistribute.
-Texinfo source for each manual and source for each reference card is on
-the appropriate tape, diskette, or CD-ROM; the prices for these magnetic
-media do not include printed documentation. All items are provided on
-an ``as is'' basis, with no warranty of any kind. Please allow six
-weeks for delivery (though it won't usually take that long).
+These packages:
+ * DJGPP
+ * GCC/G++/Objective-C
+ * GNU C Library
+ * GDB
+ * Binutils
+ * Bison
+ * Emacs (MS-DOS only)
+ * Flex
+ * Make
+ * libg++
- PRICE AND CONTENTS MAY CHANGE WITHOUT NOTICE AFTER January 31, 1996.
+On these platforms:
+ * `i386-msdos'
+ * `hppa1.1-hp-hpux9'
+ * `hppa1.1-hp-hpux10'
+ * `powerpc-ibm-aix4.2'
+ * `sparc-sun-solaris2.4'
+ * `sparc-sun-solaris2.5'
+ * `sparc-sun-sunos4.1'
+
-Unix and VMS Software
----------------------
+Source Code CD-ROMs
+-------------------
-These tapes in the formats indicated (*note Tapes::., for contents):
+We have several versions of our Source Code CD-ROMs available, including:
- Please circle the dollar amount for each tape you order.
+ * July 1997 Source Code CD-ROMs, the newest release, has programs,
+ bug fixes, & improvements. See below.
- Reel to Sun (1) HP IBM (2) Exabyte DAT
- reel RS/6000
- Unix tar Unix tar Unix tar Unix tar Unix tar Unix tar
- 9-track QIC-24 16-track QIC-150
- 1600 bpi DC300XLP DC600HC DC600A
- 1/2" reel 1/4" c.t. 1/4" c.t. 1/4" c.t. 8mm c.t. 4mm c.t.
+ * January 1997 Source Code CD-ROMs.
- (c.t. = cartridge tape)
+ * July 1996 Source Code CD-ROMss.
-Lisps/Emacs $200 $210 $230 $215 (3) $205 $225
-Languages $200 $210 $230 $215 $205 $225
-Utilities $200 $210 $230 $215 $205 $225
-4.4BSD-Lite $200 $210 $230 $215 $205 $225
-Scheme $200 $210 $230 $215 $205 $225
-X11R5-Required $200 $210 $230 $215 $205 $225
-X11R5-Optional $200 $210 $230 $215 $205 $225
-X11R6-Required $200 $210 $230 $215 $205 $225
-X11R6-Optional $200 $210 $230 $215 $205 $225
+ * December 1995 Source Code CD-ROMs.
- (1) Sun tapes can be read on some other Unix systems.
- (2) IBM RS/6000 tapes can be read on some other Unix systems.
- (3) The IBM Emacs tape also has binaries for GNU Emacs.
+ * June 1995 Source Code CD-ROM.
+ * May 1994 Source Code CD-ROM.
-Subscriptions, 4 updates for one year (*note Tape & CD-ROM Subscription Service::.):
+ * November 1993 Source Code CD-ROM.
-Emacs $600 $630 $690 $645 $615 $675
-Languages $600 $630 $690 $645 $615 $675
-Utilities $600 $630 $690 $645 $615 $675
-X11R6-Required $600 $630 $690 $645 $615 $675
+ * May 1993 Source Code CD-ROM.
- Subtotal $ ______ Please put total of the above circled amounts here.
+ * October 1992 Source Code CD-ROM.
+The older Source CDs are available while supplies last at a reduced price
+(please note that the December 1994 Source CD is permanently out of stock).
+All the Source CDs have Texinfo source for the GNU manuals listed in *Note
+Documentation::.
-These 1600 bpi reel-to-reel 9 track 1/2" tapes, in VMS BACKUP format (aka
-interchange format) (*note VMS Emacs and VMS Compiler Tapes::.):
+Much of X11 is *not* on the older Source CDs which are just one CD
+instead of two.
-____ @ $195 = $ ______ VMS Emacs, GNU Emacs source & executables only.
+There are no precompiled programs on these Source CDs. You will need a C
+compiler (programs which need some other interpreter or compiler normally
+provide the C source for a bootstrapping program). We ship C compiler
+binaries for some systems on the *Note Compiler Tools Binaries CD-ROM::.
-____ @ $195 = $ ______ VMS Compiler, GCC, GAS, and Bison source and
- executables only.
+
+
+July 1997 Source Code CD-ROMs
+.............................
+
+The 10th edition of our Source Code CD is available now with two CD-ROM disks.
+It has programs, bug fixes, & improvements not on the older Source CDs. It
+has these packages, & some manuals that are not part of packages. The
+version number of each package listed might be higher on the 10th edition CD
+due to new releases being made since this list was generated.
+
+
+ * abuse 2.0
+ * acct 6.3
+ * acm 4.8
+ * aegis 2.3
+ * apache 1.2.4
+ * Autoconf 2.12
+ * Automake 1.2
+ * BASH 2.01
+ * bc 1.04
+ * Binutils 2.8.1
+ * Bison 1.25
+ * C Library 2.0.5
+ * Calc 2.02f
+ * cfengine 1.4.1
+ * Chess 4.0.pl77
+ * CLISP 1997.08.07
+ * Common Lisp 2.2.2
+ * cook 1.10
+ * cperf 2.1a
+ * cpio 2.4.2
+ * CVS 1.9
+ * cxref 1.4
+ * ddd 2.1.1
+ * DejaGnu 1.3
+ * Diffutils 2.7
+ * dld 3.3
+ * doschk 1.1
+ * ed 0.2
+ * Elib 1.0
+ * elisp archive 1997.08.19
+ * Emacs 18.59
+ * Emacs 19.34
+ * Emacs 20.1
+ * enscript 1.5.0
+ * es 0.84
+ * Exim 1.70
+ * f2c 1997.07.13
+ * ffcall 1.1
+ * Fileutils 3.16
+ * Findutils 4.1
+ * Finger 1.37
+ * flex 2.5.4
+ * Fontutils 0.6
+ * g77 0.5.19.1
+ * gawk 3.0.3
+ * gcal 2.10
+ * GCC/G++/Objective-C 2.7.2.3
+ * GDB 4.16
+ * gdbm 1.7.3
+ * Generic NQS 3.50.2
+ * geomview 1.6.1
+ * gettext 0.10
+ * gforth 0.3.0
+ * Ghostscript 3.33
+ * Ghostview 1.5
+ * Ghostview for Windows 2.1
+ * GIT 4.3.16
+ * gmp 2.0.2
+ * GN 2.24
+ * Gnans 1.5.1
+ * gnat 3.09
+ * GNATS 3.2
+ * GNU Emacs Lisp Reference Manual 1.03
+ * GNU Emacs Lisp Reference Manual 2.4.2
+ * GNU Emacs Lisp Reference Manual 2.4.jp2.0
+ * GnuGo 1.2
+ * gnuplot 3.5
+ * gnuserv 2.1alpha
+ * gnussl 0.2.1
+ * gpc 2.0
+ * grep 2.0
+ * Groff 1.11
+ * guavac 0.3.1
+ * guile 1.2
+ * gzip 1.2.4
+ * hello 1.3
+ * hp2xx 3.1.4
+ * HylaFAX 4.0pl1
+ * Hyperbole 4.01
+ * ID Utils 3.2
+ * ilisp 5.8.a04
+ * indent 1.9.1
+ * Inetutils 1.3a
+ * Ispell 3.1.20
+ * jargon 4.0.0
+ * karma 1.6
+ * less 332
+ * LessTif 0.80
+ * libg++ 2.7.2
+ * libobjects 0.1.19
+ * libtool 1.0
+ * lynx 2.7.1
+ * m4 1.4
+ * make 3.75
+ * MandelSpawn 0.07
+ * maxima 5.2
+ * mc 4.0
+ * MCSim 4.1
+ * mesa 2.1
+ * <Meta-HTML> 5.04
+ * miscfiles 1.1
+ * mkisofs 1.11
+ * mm 1.07
+ * mtools 3.8
+ * MULE 2.3
+ * mutt 0.81
+ * NetHack 3.2.2
+ * NIHCL 3.1.4
+ * nvi 1.79
+ * Oaklisp 930720
+ * OBST 3.4.3
+ * Octave 2.0.9
+ * Oleo 1.6
+ * p2c 1.20
+ * patch 2.5
+ * pcl-gcl 2.2
+ * perl 4.036
+ * perl 5.003
+ * phttpd 0.99.76
+ * pips 1.01
+ * plotutils 1.1
+ * prcs 1.2
+ * Programming in Emacs Lisp an Introduction 1.04
+ * ptx 0.4
+ * rc 1.4
+ * RCS 5.7
+ * readline 2.1
+ * recode 3.4
+ * regex 0.12
+ * Roxen 1.1
+ * rsync 1.6.3
+ * rx 1.5
+ * SAOimage 1.20
+ * screen 3.7.4
+ * sed 2.05
+ * Sharutils 4.2
+ * Shellutils 1.16
+ * Shogi 1.2p03
+ * SIPP 3.1
+ * smail 3.2
+ * Smalltalk 1.1.5
+ * sneps 2.3.1
+ * spell 1.0
+ * stow 1.3.2
+ * Superopt 2.5
+ * swarm 1.0.2
+ * tar 1.12
+ * Termcap 1.3
+ * Termutils 2.0
+ * TeX 3.1415
+ * Texinfo 3.11
+ * Textutils 1.22
+ * tiff 3.4
+ * Tile Forth 2.1
+ * time 1.7
+ * ucblogo 4.1
+ * units 1.53
+ * UUCP 1.06.1
+ * vera 1.0
+ * vrweb 1.5
+ * W3 2.2.26
+ * wdiff 0.5
+ * wget 1.4.5
+ * windows32api 0.1.2
+ * WN 1.18.1
+ * X11R6.3
+ * xboard 3.6.2
+ * xgrabsc 2.41
+ * xinfo 1.01.01
+ * xmcd 2.2
+ * xshogi 1.2p03
+ * Ygl 3.1
+ * zlibc 0.9e
+
+
+
+January 1997 Source Code CD-ROMs
+................................
+We still have copies of the 9th edition of our Source CD with two CD-ROM
+disks. It has these packages, & some manuals that are not part of packages:
+
+
+ * acm 4.7
+ * apache 1.1.1
+ * Autoconf 2.12
+ * Automake 1.0
+ * BASH 2.0
+ * bc 1.03
+ * Binutils 2.7
+ * Bison 1.25
+ * C Library 2.0
+ * Calc 2.02f
+ * cfengine 1.3.16
+ * Chess 4.0.pl77
+ * CLISP 1996.05.30
+ * Common Lisp 2.2.1
+ * cperf 2.1a
+ * cpio 2.4.2
+ * CVS 1.9
+ * ddd 2.0
+ * DejaGnu 1.3
+ * Diffutils 2.7
+ * dld 3.3
+ * doschk 1.1
+ * ed 0.2
+ * Elib 1.0
+ * elisp archive
+ * Emacs 18.59
+ * Emacs 19.34
+ * enscript 1.4.0
+ * es 0.84
+ * Exim 1.59
+ * f2c 1996.12.09
+ * ffcall 1.1
+ * Fileutils 3.16
+ * Findutils 4.1
+ * Finger 1.37
+ * flex 2.5.4
+ * Fontutils 0.6
+ * g77 0.5.19
+ * gawk 3.0.1
+ * gcal 2.10
+ * GCC/G++/Objective-C 2.7.2.2
+ * GDB 4.16
+ * gdbm 1.7.3
+ * Generic NQS 3.50.2
+ * geomview 1.6.1
+ * gettext 0.10
+ * gforth 0.2.1
+ * Ghostscript 3.33
+ * Ghostview 1.5
+ * Ghostview for Windows 2.1
+ * GIT 4.3.16
+ * gmp 2.0.2
+ * GN 2.24
+ * Gnans 1.5.1
+ * gnat 3.07
+ * GNATS 3.2
+ * GNU Emacs Lisp Reference Manual 1.03
+ * GNU Emacs Lisp Reference Manual 2.4.2
+ * GNU Emacs Lisp Reference Manual 2.4.jp2.0
+ * GnuGo 1.2
+ * gnuplot 3.5
+ * gnuserv 2.1alpha
+ * gnussl 0.2.1
+ * gpc 2.0
+ * Graphics 0.17
+ * grep 2.0
+ * Groff 1.10
+ * guile 1.0
+ * gzip 1.2.4
+ * hello 1.3
+ * hp2xx 3.1.4
+ * HylaFAX 4.0pl1
+ * Hyperbole 4.01
+ * ID Utils 3.2
+ * ilisp 5.8.a04
+ * indent 1.9.1
+ * Inetutils 1.2j
+ * Ispell 3.1.20
+ * jargon 4.0.0
+ * karma 1.6
+ * less 321
+ * libg++ 2.7.2
+ * libobjects 0.1.19
+ * lynx 2.6
+ * m4 1.4
+ * make 3.75
+ * MandelSpawn 0.07
+ * maxima 5.2
+ * mc 3.2.1
+ * mesa 2.1
+ * <Meta-HTML> 5.01
+ * miscfiles 1.0
+ * mkisofs 1.05GNU
+ * mm 1.07
+ * mtools 3.1
+ * MULE 2.3
+ * mutt 0.57
+ * ncurses 1.9.9e
+ * NetHack 3.2.2
+ * NIHCL 3.1.4
+ * nvi 1.79
+ * Oaklisp 930720
+ * OBST 3.4.3
+ * Octave 2.0.2
+ * Oleo 1.6
+ * p2c 1.20
+ * patch 2.1
+ * pcl-gcl 2.1
+ * perl 4.036
+ * perl 5.003
+ * phttpd 0.99.72.1
+ * pine 3.91
+ * pips 1.01
+ * Programming in Emacs Lisp an Introduction 1.04
+ * ptx 0.4
+ * rc 1.4
+ * RCS 5.7
+ * readline 2.0
+ * recode 3.4
+ * regex 0.12
+ * Roxen 1.1
+ * rx 1.5
+ * SAOimage 1.19
+s * scheme 7.4
+ * screen 3.7.2
+ * sed 2.05
+ * Sharutils 4.2
+ * Shellutils 1.16
+ * Shogi 1.2p03
+ * SIPP 3.1
+ * smail 3.2
+ * Smalltalk 1.1.5
+ * sneps 2.3.1
+ * stow 1.3.2
+ * Superopt 2.5
+ * tar 1.11.8
+ * Termcap 1.3
+ * Termutils 2.0
+ * TeX 3.1415
+ * Texinfo 3.9
+ * Textutils 1.22
+ * tiff 3.4
+ * Tile Forth 2.1
+ * time 1.7
+ * ucblogo 3.6
+ * units 1.53
+ * UUCP 1.06.1
+ * vrweb 1.3
+ * W3 2.2.26
+ * wdiff 0.5
+ * wget 1.4.2b
+ * windows32api 0.1.2
+ * WN 1.17.1
+ * X11R6.3
+ * xboard 3.5.0
+ * xgrabsc 2.41
+ * xinfo 1.01.01
+ * xshogi 1.2p03
+ * Ygl 3.1
+
+
+
+CD-ROM Subscription Service
+***************************
+
+Our subscription service enables you to stay current with the latest GNU
+developments. For a one-time cost equivalent to three Source CD-ROMs (plus
+shipping in some cases), we will ship you four new versions of the *Note
+Source Code CD-ROMs::. The CD-ROMs are sent as they are issued (currently
+twice a year, but we hope to make it more frequent). We do not yet know if
+we will be offering subscriptions to the Compiler Tools Binaries CD.
-FSF Deluxe Distribution (*note Deluxe Distribution::.):
-......................................................
+A subscription is an easy way to keep up with the regular bug fixes to the X
+Window System. Each edition of the *Note Source Code CD-ROMs::, has updated
+sources for the X Window System.
+Please note: In two cases, you must pay 4 times the normal shipping required
+for a single order when you pay for each subscription. If you're in Alaska,
+Hawaii, or Puerto Rico you must add $20.00 for shipping for each
+subscription. If you're outside of the U.S., Canada, and Puerto Rico, you
+must add $80.00 for each subscription. See "CD-ROMs" and "Tax and Shipping
+Costs" on the *note Free Software Foundation Order Form::.
-____ @ $5000 = $ ______ The Deluxe Distribution, with manuals, etc.
+
-Machine: _____________________________________________________________________
+FSF T-shirt
+***********
-Operating system: ____________________________________________________________
+The front of our T-shirt has the GNU Emacs Lisp code `(USE 'GNU)' with "`()'"
+being the dancing parentheses from the cover of our `GNU Emacs Lisp Reference
+Manual' (drawn by Berkeley, CA artist Etienne Suvasa). The shirt's back has
+the Preamble to the GNU General Public License.
-Media type: __________________________________________________________________
+These shirts come in black, natural (off-white), burgundy, and blue-green.
+When you order, please give 3 choices. Black is printed in white and the
+other colors are printed in black. All shirts are thick 100% cotton; black
+and burgundy come in sizes M, L, XL, and XXL and the others in sizes L and XL
+(they run small so you may want a larger size than usual).
+GNU T-shirts often create spontaneous friendships at conferences & on
+university campuses. They also make great gifts for friends & family,
+including children!
+
-CD-ROMs, in ISO 9660 format (*note CD-ROMs::.):
-..............................................
+Free Software Foundation Order Form
+***********************************
+All items are distributed with permission to copy and to redistribute.
+Texinfo source for each manual and source for each reference card is on the
+appropriate CD-ROM; the prices for these media do not include printed
+documentation.
+All items are provided ``as is'', with no warranty of any kind.
+Please allow three weeks for delivery
+(though it won't usually take that long).
-GNU Source Code CD-ROM, Version 6 with X11R6 (*note June 1995 Source Code CD-ROM::.):
-____ @ $240 = $ ______ for corporations and other organizations.
+ PRICE AND CONTENTS MAY CHANGE WITHOUT NOTICE AFTER January 31, 1998.
-____ @ $ 60 = $ ______ for individuals.
+A possibly more current version of this order form can be found on the
+World Wide Web at `http://www.gnu.ai.mit.edu/order/order.html' or
+can be found in file `/pub/gnu/GNUinfo/ORDERS' on a GNU FTP host
+(*note How to Get GNU Software::.).
-GNU Compiler Tools Binaries CD-ROM, Version 2, December 1994 Edition
-(*note Compiler Tools Binaries CD-ROM::.):
-____ @ $220 = $ ______ for corporations and other organizations.
+FSF Deluxe Distribution
+-----------------------
+(Please contact us with any questions. *Note Deluxe Distribution::,
+for machine, operating system, and media types.)
-____ @ $55 = $ ______ for individuals.
+____ @ $5000 = $ ______ The Deluxe Distribution, with manuals, etc.
+Machine: _____________________________________________________________________
-Debian GNU/Linux Book with CD-ROM - expected late fall 1995 (*note Debian GNU/Linux CD-ROM::.):
+Operating system: ____________________________________________________________
-____ @ $200 = $ ______ for corporations and other organizations.
+Media type: __________________________________________________________________
-____ @ $50 = $ ______ for individuals.
+(Optional) Version of X Window System to link with: __________________________
-Subscriptions, next 4 updates, of the Source Code CD-ROM, in ISO 9660 format
-(*note Tape & CD-ROM Subscription Service::.):
-____ @ $720 = $ ______ for corporations and other organizations.
+CD-ROMs, in ISO 9660 format (*note CD-ROMs::.):
+----------------------------------------------
-____ @ $180 = $ ______ for individuals.
+GNU Source Code CD-ROMs, Version 10 with X11R6.3 (*note July 1997 Source Code CD-ROMs::.):
+____ @ $240 = $ ______ for corporations and other organizations.
-MS-DOS Software
----------------
+____ @ $ 60 = $ ______ for individuals.
-MS-DOS Book with CD-ROM - expected September 1995 (*note MS-DOS CD-ROM::.):
-____ @ $180 = $ ______ for corporations and other organizations.
+Subscriptions, next 4 updates of the Source Code CD-ROM, in ISO 9660 format
+(*note CD-ROM Subscription Service::.):
-____ @ $45 = $ ______ for individuals.
+____ @ $720 = $ ______ for corporations and other organizations.
+____ @ $180 = $ ______ for individuals.
-The following sources and executables for MS-DOS, on 3.5" 1.44MB diskettes
-(*note MS-DOS Diskettes::.):
+GNU Compiler Tools Binaries CD-ROM, Version 4, January 1997 Edition
+(*note Compiler Tools Binaries CD-ROM::.):
-____ @ $ 90 = $ ______ Emacs diskettes, GNU Emacs, for 80386 and up.
+____ @ $220 = $ ______ for corporations and other organizations.
-____ @ $ 80 = $ ______ DJGPP diskettes, GCC version 2, for 80386 and up
- (also on the *note Compiler Tools Binaries CD-ROM::. and *note MS-DOS CD-ROM::..)
-____ @ $ 85 = $ ______ Selected Utilities diskettes, 8086 and up.
+____ @ $55 = $ ______ for individuals.
-____ @ $ 40 = $ ______ Windows diskette, GNU Chess and gnuplot for
- Microsoft Windows.
Manuals
-------
-These manuals (*note Documentation::.). Please call for bulk purchase
-discounts.
+These manuals (*note Documentation::.). The latest version of each manual
+will be shipped. Please contact us if you want a specific version.
-____ @ $300 = $ ______ One copy each of the following 13 manuals.
+____ @ $ 30 = $ ______ GNU Emacs manual, with a reference card.
-____ @ $ 25 = $ ______ GNU Emacs version manual, with a reference card.
+____ @ $ 50 = $ ______ GNU Emacs Lisp Reference manual, in two volumes.
-____ @ $ 50 = $ ______ GNU Emacs Lisp Reference manual, in two volumes.
+____ @ $ 60 = $ ______ GNU Emacs Lisp Reference, Japanese Edition.
-____ @ $ 50 = $ ______ Using and Porting GNU CC.
+____ @ $ 50 = $ ______ Using and Porting GNU CC.
-____ @ $ 50 = $ ______ GNU C Library Reference Manual.
+____ @ $ 50 = $ ______ GNU C Library Reference Manual.
-____ @ $ 50 = $ ______ GNU Emacs Calc manual, with a reference card.
+____ @ $ 50 = $ ______ GNU Emacs Calc manual, with a reference card.
-____ @ $ 20 = $ ______ Programming in Emacs Lisp, An Introduction
+____ @ $ 20 = $ ______ Programming in Emacs Lisp: An Introduction.
-____ @ $ 20 = $ ______ Debugging with GDB, with a reference card.
+____ @ $ 20 = $ ______ Debugging with GDB, with a reference card.
-____ @ $ 20 = $ ______ Gawk manual.
+____ @ $ 25 = $ ______ GNU Awk User's Guide.
-____ @ $ 20 = $ ______ Make manual.
+____ @ $ 20 = $ ______ Make manual.
-____ @ $ 20 = $ ______ Bison manual, with a reference card.
+____ @ $ 20 = $ ______ Bison manual, with a reference card.
-____ @ $ 20 = $ ______ Flex manual, with a reference card.
+____ @ $ 20 = $ ______ Flex manual, with a reference card.
-____ @ $ 20 = $ ______ Texinfo manual.
+____ @ $ 25 = $ ______ Texinfo manual.
-____ @ $ 15 = $ ______ Termcap manual.
+____ @ $ 15 = $ ______ Termcap manual, 3rd Edition Revised.
@@ -3566,33 +3935,43 @@ Reference Cards
---------------
The following reference cards, in packets of ten. For single copies please
-call.
+contact us.
-____ @ $ 10 = $ ______ GNU Emacs version 19 reference cards.
+____ @ $ 10 = $ ______ GNU Emacs version 20 reference cards.
-____ @ $ 10 = $ ______ GNU Emacs Calc reference cards.
+____ @ $ 10 = $ ______ GNU Emacs Calc reference cards.
-____ @ $ 10 = $ ______ GDB reference cards.
+____ @ $ 10 = $ ______ GDB reference cards.
-____ @ $ 10 = $ ______ Bison reference cards.
+____ @ $ 10 = $ ______ Bison reference cards.
-____ @ $ 10 = $ ______ Flex reference cards.
+____ @ $ 10 = $ ______ Flex reference cards.
T-shirts
--------
-GNU/FSF T-shirts, thick 100% cotton (*note FSF T-shirt::.):
+GNU/FSF T-shirts (*note FSF T-shirt::.), thick 100% cotton, available in
+black or natural (off-white) in sizes M, L, XL, and XXL,
+and in burgundy or blue-green in sizes L and XL.
+Please list 1st, 2nd, and 3rd choice of color.
+
+____ @ $ 15 = $ ______ Size _____
-____ @ $ 15 = $ ______ Size M ____ natural ____ black.
+ Color choice: 1st _______ 2nd _______ 3rd _______
-____ @ $ 15 = $ ______ Size L ____ natural ____ black.
+____ @ $ 15 = $ ______ Size _____
-____ @ $ 15 = $ ______ Size XL ____ natural ____ black.
+ Color choice: 1st _______ 2nd _______ 3rd _______
-____ @ $ 15 = $ ______ Size XXL ____ natural ____ black.
+____ @ $ 15 = $ ______ Size _____
+ Color choice: 1st _______ 2nd _______ 3rd _______
+
+____ @ $ 15 = $ ______ Size _____
+
+ Color choice: 1st _______ 2nd _______ 3rd _______
Older Items
@@ -3600,40 +3979,36 @@ Older Items
Older items are only available while supplies last.
-____ @ $ 5 = $ ______ GNU Emacs version 18 reference cards, in packets
- of ten.
+____ @ $ 40 = $ ______ Using and Porting GCC, 8.5 x 11 inches, with
+ plastic binding (same text as current edition)
Please fill in the number of each older CD-ROM you order:
- for for
- corporations individuals:
- and other
- organizations:
+ GNU Compiler Tools Binaries CD-ROMs:
+
+Version 1 (December '93) ______ Version 2 (December '94) ______
-GNU Compiler Tools Binaries CD-ROM
- December 1993 Edition (Version 1) ____________ ____________
+Version 3 (December '95) ______
+ GNU Source Code CD-ROMs: (Version 5 (Dec. '94) is not available.)
-GNU Source Code CD-ROM
- May 1994 edition with X11R6 ____________ ____________
+Version 1 (October '92) ______ Version 2 (May '93) ______
-GNU Source Code CD-ROM
- November 1993 edition with X11R5 ____________ ____________
+Version 3 (November '93 - last edition with X11R5) ______
-GNU Source Code CD-ROM
- May 1993 edition with X11R5 ____________ ____________
+Version 4 (May '94 - first edition with X11R6) ______
-GNU Source Code CD-ROM
- October 1992 edition with X11R5 ____________ ____________
+Version 6 (June '95) ______ Version 7 (Dec. '95) ______
+Version 8 (July '96) ______ Version 9 (Jan. '97) ______
Please put the total count and cost of the above older CD-ROMs here:
-____ @ $ 80 = $ ______ for corporations and other organizations.
+____ @ $ 80 = $ ______ for corporations and other organizations.
-____ @ $ 20 = $ ______ for individuals.
+____ @ $ 20 = $ ______ for individuals.
- ======
+ ======
Subtotal $ ______
@@ -3642,30 +4017,43 @@ ____ @ $ 20 = $ ______ for individuals.
Tax and Shipping Costs
----------------------
- + $ ______ In Massachusetts: add 5% sales tax, or give tax
- exempt number.
- + $ ______ In Alaska, Hawaii, or Puerto Rico for shipping:
- for GNU Emacs Lisp Reference and GNU Emacs Calc
- manuals, add $5 *each*. For *each* tape or
- CD-ROM subscription, add $20. For all other
- items, add $5 base charge, then $1 per item except
- reference cards; i.e.,
- shipping for all other items = $5 + ($1 * i).
- + $ ______ Outside of U.S., Canada, and Puerto Rico for
- shipping: Add $20 base charge; then add $80 more
- for *each* tape or CD-ROM subscription; and then
- add $10 more for *each* manual in the order;
- i.e., shipping for all other items
- = $20 + ($80 * s) + ($10 * m).
- + $ ______ Optional (tax-deductible in the U.S.) donation.
- ------ We suggest 5% if paying by credit card.
-
- TOTAL $ ______ We pay for shipping via UPS ground transportation in
- the contiguous 48 states and Canada. For very
- large orders, ask about actual shipping costs for
- that order.
-
-
+ + $ ______ For addresses in Massachusetts: add 5% sales tax
+ or give tax exempt number. There is no sales tax
+ on T-shirts.
+ + $ ______ Shipping fee for addresses in Alaska, Hawaii, or
+ Puerto Rico:
+ $ 5.00 base charge;
+ + $ 5.00 for *each* Emacs Calc or Emacs Lisp
+ Reference manual ($ 5.00 * #ofMans);
+ + $ 20.00 for *each* CD-ROM subscription
+ ($20.00 * #ofSubs);
+ + $ 1.00 for *each* item other than the above
+ (shipping for all other items =
+ $ 1.00 * #ofOtherItems).
+ + $ ______ Shipping fee for most Foreign Destinations: (Please
+ do *not* use this formula for addresses in China,
+ Guam, Indonesia, Israel, Malaysia, New Zealand,
+ Philippines, and Thailand. Please contact us for
+ an exact shipping quote.)
+ $ 20.00 base charge for orders to other
+ addresses outside of U.S., Canada, & Puerto Rico:
+ + $ 10.00 for each item ordered, ($ 10.00 * #ofItems)
+ + $ 80.00 for each CD-ROM subscription
+ ($ 80.00 * #ofSubs) (don't count as an item).
+ In Europe, ordering via GNU Distribution Europe--
+ Belgium may reduce these costs
+ (*note New European Distributor::.).
+ + $ ______ Optional (tax-deductible in the U.S.) donation.
+ We suggest 5% if paying by credit card.
+
+ TOTAL $ ______ We pay for shipping via UPS ground transportation in
+ the contiguous 48 states and Canada. For very
+ large orders, ask about actual shipping costs for
+ that order.
+
+Note: The shipping fee for foreign destinations covers express courier
+ shipping. If you would like shipping via air mail, please contact
+ our distribution office for a quote on your order.
Shipping Information
--------------------
@@ -3678,47 +4066,56 @@ Organization: ________________________________________________________________
Street Address: ______________________________________________________________
-City/State/Province: _________________________________________________________
+City, State/Province: ________________________________________________________
-Zip Code/Postal Code/Country: ________________________________________________
+Zip Code/Postal Code, Country: _______________________________________________
Telephone number in case of a problem with your order.
-For international orders, please include a FAX number. _______________________
+For international orders, please include a fax number. _______________________
+
+E-mail Address: ______________________________________________________________
------------------------------------------------------------------------------
-| |
-| Orders filled only upon receipt of check, money order or credit card |
+| |
+| Orders filled only upon receipt of check, money order, or credit card |
| order in U.S. dollars. Unpaid orders will be returned to the sender. |
| We do not have the staff to handle the billing of unpaid orders. Please |
| help keep our lives simple by including your payment with your order. |
-| |
+| |
------------------------------------------------------------------------------
+
For orders from outside the U.S.:
---------------------------------
-You are responsible for paying all duties, tariffs, and taxes. If you
+You are responsible for paying all duties, tariffs, and taxes. If you
refuse to pay the charges, the shipper will return or abandon the order.
+In Europe, you may find it cheaper and more convenient to use our European
+Distributor. *Note New European Distributor::.
+
---------------------------------------------------------------------------
- | |
- | Please make checks payable to the ``Free Software Foundation''. |
- | |
+ | |
+ | Please make checks payable to the ``Free Software Foundation''. |
+ | |
+ | Checks must be in U.S. dollars, drawn on a U.S. bank. |
+ | |
---------------------------------------------------------------------------
+
For Credit Card Orders:
-----------------------
The Free Software Foundation takes these credit cards: Carte Blanche,
-Diner's Club, JCB, Mastercard, Visa, or American Express. Please note that
-we are charged about 5% of an order's total amount in credit card
-processing fees. Please consider paying by check instead, or adding on a
-5% donation to make up the difference. To place a credit card order,
-please give us this information:
+Diner's Club, Discover, JCB, MasterCard, Visa, or American Express.
+Please note that we are charged about 5% of an order's total amount in
+credit card processing fees. Please consider paying by check instead,
+or adding on a 5% donation to make up the difference. To place a credit
+card order, please give us this information:
Card type: ___________________________________________________________________
@@ -3727,31 +4124,34 @@ Account Number: ______________________________________________________________
Expiration Date: _____________________________________________________________
+Cardholder's Name: ___________________________________________________________
+
Cardholder's Signature: ______________________________________________________
------------------------------------------------------------------------------
-| |
-| If you wish to pay by wire transfer, or you are a reseller, please |
-| call or write us for details. |
-| |
+| |
+| If you wish to pay by wire transfer or you are a reseller, please |
+| contact us or write us for details. |
+| |
------------------------------------------------------------------------------
- Please mail orders to: Free Software Foundation
- 59 Temple Place -- Suite 330
- Boston, MA 02111
- +1-617-542-5942
- FAX (including Japan): +1-617-542-2652
- Free Dial FAX numbers in Japan:
-PRICES AND CONTENTS MAY CHANGE 0031-13-2473 (KDD)
-WITHOUT NOTICE AFTER January 31, 1996. 0066-3382-0158 (IDC)
-Version: June 1995 ASCII Bull to June 1995 Src CD/GNU 19.29/GCC 2.7.0
+A possibly more current version of this order form can be found on the
+World Wide Web at `http://www.gnu.ai.mit.edu/order/order.html' or
+can be found in file `/pub/gnu/GNUinfo/ORDERS' on a GNU FTP host
+(*note How to Get GNU Software::.).
+
+
+
+ Please mail orders to: Free Software Foundation
+ 59 Temple Place - Suite 330
+ Boston, MA 02111
+PRICES AND CONTENTS MAY CHANGE +1-617-542-5942
+WITHOUT NOTICE AFTER January 31, 1998 Fax (including Japan): +1-617-542-2652
+
+Version: July 1997 ASCII etc/ORDERS
----------------------------------------------------------------------
-local variables:
-mode: text
-fill-column: 78
-end:
+-----------------------------------------------------------------------------
diff --git a/gnu/usr.bin/gcc/README b/gnu/usr.bin/gcc/README
index 43ed75d6f9f..6e4fed8153a 100644
--- a/gnu/usr.bin/gcc/README
+++ b/gnu/usr.bin/gcc/README
@@ -1,4 +1,4 @@
-This directory contains the version 2.7.2 release of the GNU C
+This directory contains the version 2.8.0 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.
diff --git a/gnu/usr.bin/gcc/README.X11 b/gnu/usr.bin/gcc/README.X11
index 359dd5f9603..ade0f5ab531 100644
--- a/gnu/usr.bin/gcc/README.X11
+++ b/gnu/usr.bin/gcc/README.X11
@@ -20,7 +20,7 @@ IF YOU THINK YOU MIGHT COMPILE X FOR SOLARIS 2, then you really don't
need this patch: get /contrib/R5.SunOS5.patch.tar.Z from
export.lcs.mit.edu instead. It has everything you need to do the
build for Solaris 2, sets you up to everything with GCC, and is
-backward compatible with Sunos 4.*. Get the the README
+backward compatible with SunOS 4.*. Get the the README
(/contrib/R5.SunOS5.patch.README at export) for more info.
If you see undefined symbols _dlopen, _dlsym, or _dlclose when linking
diff --git a/gnu/usr.bin/gcc/SERVICE b/gnu/usr.bin/gcc/SERVICE
index 11e266a33c2..46441675fd0 100644
--- a/gnu/usr.bin/gcc/SERVICE
+++ b/gnu/usr.bin/gcc/SERVICE
@@ -38,7 +38,65 @@ For a current copy of this directory, or to have yourself listed, ask:
gnu@prep.ai.mit.edu
** Please keep the entries in this file alphabetical **
+
+Altrasoft <info@altrasoft.com>
+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 <magnus@itanalyse.no>
+
+GNU Emacs, GCC, the Unix tools, Linux, Jolt.
+Rates: Free, or from $50/hour.
+
+Updated: 1997-05-09
+
+AO UrbanSoft <info@usoft.spb.su>
+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 <jla@ai.mit.edu>
PO Box 460633 http://www.samsara.com/~jla
@@ -65,37 +123,110 @@ 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: 1995-10-17

-Gerd Aschemann <aschemann@Informatik.TH-Darmstadt.de>
+Gerd Aschemann <Aschemann@Informatik.TH-Darmstadt.de>
Osannstr. 49
D-64285 Darmstadt
Tel.: +49 6151 16 2259
http://www.informatik.th-darmstadt.de/~ascheman/
- 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
+- 17 years experience with CS, System administration on different platforms
+- 10 years with UNIX/Networking/FreeWare/GNU/X11
+- 8 years organizer of Operating Systems and Distributed Systems courses
- Lectures on System and Network Administration
-- Platforms: Solaris, SunOS, Ultrix, OSF1, HP-UX, Linux, FreeBSD, AIX
+- Platforms: Solaris, SunOS, Ultrix, OSF1, HP-UX, Linux, FreeBSD, AIX, SCO
+- Distributed Platforms and Information Systems (CORBA, WWW, Java, FTP)
- 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 130,-- DM (~80 US$) per hour minimum, depending on the job.
I am willing to travel for sufficiently large jobs.
-Updated: 17Oct95
+Updated: 1997-05-07
+
+
+ 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: <info@basistech.com>
+ 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: 1997-05-07

-Giuseppe Attardi <attardi@di.unipi.it>
-Dipartimento di Informatica
-Corso Italia 40
-I-56125 Pisa, Italy
-+39 50 887-244
+Laurent Bernardin
+16, rue Dicks
+L-6944 Niederanven
+Luxemburg
+<bernardin@inf.ethz.ch>
++41 1 632 7469
+
+Support and installation of all GNU software.
-GNU: help on obtaininig GNU, for italian sites.
+Expertise: C, C++, Java, Motif, X, Unix administration, network security
-Updated: 5Apr94
+Rates: ~60 US$ / hour (Flux 2000.-)
+
+Updated: 1997-05-07
+
+Philip Brown
+<phil@mitre.org>
+(703) 893-8967 (prefer email)
+Northern-VA, D.C. Area
+Rates: $40/Hr; less for educational or charitable organizations
+
+Systems Supported:
+ HP9000/7xx running HP/UX 8.07 - 10.X
+ IBM RS6000 running AIX 3.2.X
+ Also SGI/Indy and Sun/Sparcs
+
+Software Supported:
+ Most all FSF (Gnu) software
+ esp. GCC, Emacs, Binutils, GS, etc...
+
+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'd be happy 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: 1997-05-07

James Craig Burley
97 Arrowhead Circle
@@ -104,7 +235,7 @@ Ashland, MA 01721-1987
(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: <burley@gnu.ai.mit.edu> --preferred--
+Email: <burley@gnu.org> --preferred--
<burley@cygnus.com>
<burley@world.std.com>
@@ -119,14 +250,16 @@ Expertise:
Extensive experience with a variety of operating systems, hardware,
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: 1997-05-07

-Michael I. Bushnell <mib@gnu.ai.mit.edu>
-545 Technology Square, NE43-426
-Cambridge, MA 02139
-(617) 253-8568
+Thomas Bushnell, n/BSG <thomas@gnu.org>
+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.
@@ -138,96 +271,210 @@ Experience: I have done Unix and GNU programming for several years,
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: 1997-05-07
+
+ C2V Michel Delval <mfd@ccv.fr>
+ 82 bd Haussmann Jean-Alain Le Borgne <jalb@ccv.fr>
+ 75008 Paris
+ France
+ Tel (33 1) 40.08.07.07
+ Fax (33 1) 43.87.35.99
+ Compuserve 100413,1012
+ http://c2v.com
+
+ 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 D950 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.
+
+ Rates: from 2000 FF/day to 150 000 FF/year, 40% discount for
+ educational institutions, add taxes and expenses. Ask for list.
+
+Updated: 1997-05-09

-C2V Renaud Dumeur <renaud@ccv.fr>
-82 bd Haussmann Michel Delval <mfd@ccv.fr>
-75009 Paris Jean-Alain Le Borgne <jalb@ccv.fr>
-France
-Tel (1) 40.08.07.07
-Fax (1) 43.87.35.99
+Bruce Dawson - <jbd@codemeta.com>
+CodeMeta, Inc.
+Epping, NH USA
+800-468-8750
-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.
+Specializing in GNU tools such as guile, CVS, gnats, bash, gawk, fileutils...
+
+Services:
+
+ o 800 phone support.
-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.
+ o Modification and development.
-Rates: from 2000 FF/day to 150 000 FF/year, 40% discount for
-educational institutions, add taxes and expenses. Ask for list.
+ o Training.
-Entered: 5May94
+Rate: $75/hour or per quote.
+
+http://www.codemeta.com
+
+Updated: 1997-05-09

-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: <info@contrib.de>
-internet: uropax.contrib.de [192.109.39.2], login as 'guest'.
+Kevin Cosgrove <kevinc@dOink.COM>
+
-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.
+ I can help folks with porting & installation of many GNU
+ and X packages on a variety of Unix platforms.
-Free Archive login for downloading on above modem numbers.
-Updated: 5Apr94
+ My rates depend on the scope of each project but range
+ from $35 to $90 per hour.
+
+Updated: 1997-05-07
+
+Couvares Consulting
+211 W. Gilman St., Suite 3W
+Madison, WI 53703 USA
+Phone: (608) 256-6201
+EMail: <couvares@family.hampshire.edu>
+Contact: Peter F. Couvares
+
+Type of support: We offer phone/email support, installation, ongoing
+ administration, training, programming, and specialized consulting for
+ free software and other UNIX systems.
+
+Sample prices: USD75/hour commercial, 40/hour nonprofit, sliding scale
+for individuals.
+
+Updated: 1996-12-04

Stuart Cracraft <cracraft@ai.mit.edu>
25682 Cresta Loma
-Laguna Niguel, Ca.
-92677
-GNUline: 714-347-8106
-Rate: $75/hour
+Laguna Niguel, CA, 92677, USA
+GNUline: 714-308-7900
+Website: http://www.earthlink.net/~cracraft/index.html
+Rate: $90/hour
Consultation topics:
- Entire GNU suite - porting, compilation, installation,
- user-training, administrator-training
+Entire GNU suite - porting, compilation, installation,
+user-training, administrator-training
Method: telephone line support, call-in via modem to your site,
-or direct visit.
-
+work over the Internet, or in-person 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.
+to Solaris (System V Release 4). Expertise in C, Emacs Lisp, Perl,
+Expect, Oracle, Informix, SunOS, Solaris, NIS, NFS.
+
Customized programming also available.
-Entered: 5Apr94
+Updated: 1997-05-07

-Cygnus Support <info@cygnus.com>
-1937 Landings Drive ...uunet!cygint!info
-Mountain View, CA 94043 USA
-+1 415 903 1400 voice
-+1 415 903 0122 fax
+Noel Cragg <noel@cyclic.com>
+6244 Aberdeen Av
+Goleta CA 93117
+805-899-4695
+
+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.
-Cygnus Support
-48 Grove Street
-Somerville, MA 02144
-+1 617 629 3000 voice
-+1 617 629 3010 fax
+Updated: 1997-05-07
+
+Cygnus Solutions
+<info@cygnus.com>
+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: <kpowers@cygnus.com>
+
+
+ Erik Westcott
+ ph: +1 408 542 9637
+ fx: +1 408 542 9699
+ email: <westcott@cygnus.com>
+Updated: 1997-09-02 by rms
+
+Marcus G. Daniels <marcusd@gnu.org>
+31060 S. Kaufman Rd. <marcus@tdb.com>
+Canby, OR 97013-9520 <marcus@sysc.pdx.edu>
+(503) 651-2694
-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.
+I can customize, extend, port, and repair many types of free software.
+I maintain the CLISP Common Lisp implementation and contribute to
+several GNU packages (e.g. Emacs). Ten years of C and Unix
+experience. Consulting rates start at $40 US/hr.
-Updated: 2Feb95
+Updated: 1997-05-07
+
+Edgar Der-Danieliantz (Danielyan) <edd@acm.org>
+P.O. Box 10 FAX +374 2 28 50 82
+Yerevan 375009
+ARMENIA
+
+ Support for GCC, X Window System, WWW, Tcl/Tk, logic programming,
+ Internet security, TCP/IP.
+
+ Experience:
+ OS's: 4.4BSD, SVR4.2, FreeBSD, SCO, Solaris, UnixWare.
+ Languages: C, C++, Objective C, Pascal, Tcl/Tk, Perl, Prolog
+ Platforms: Intel, SPARC, Mac, VAX, NeXT.
+
+ Rates: Depending on type of work, approx. $20/hour. Contact for more
+ information.
+ Negotiable for individuals and non-profit organizations.
+ FREE for individuals who can't pay. Your 'Thanks!' just enough! :-)
+ Payment by international wire transfer or check.
+
+Updated: 1997-05-07
+
+Echo Labs <echo@iinet.net.au>
+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 area, any
+GNU/freeware software will be supported.
+
+For further details see: http://www.iinet.net.au/~echo/
+
+Experience: 12+ years C/Unix, Sun, SCO, Linux, Win/NT.
+ Systems programming, device drivers, hardware interfacing.
+ GNU tools/utilities,
+ Embedded & realtime systems, software, firmware, hardware.
+ Communications protocols and implementation.
+
+Degrees: BAppSc (CS), Curtin University, Perth
+
+Rates: AUS $50-75/hr neg.
+
+Updated: 1997-05-09

Free Software Association of Germany
Michaela Merz
@@ -249,33 +496,32 @@ organizations : 40 US$ / hour
ert (24h Emergency
response team) : 300 US$ / hour
-Entered: 14Apr94
+Entered: 1994-04-14

-Noah Friedman <friedman@prep.ai.mit.edu>
-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 <friedman@prep.ai.mit.edu>
+1111 W. El Camino Real #109-331
+Sunnyvale, CA 94087
+(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 administrator.
+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, including the Linux kernel; system design and
+administration for unix-type systems and IP networks; and I am willing to
+provide handholding for shell programming, Emacs Lisp development, and
+version control systems such as RCS and CVS.
-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 $75-$100/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: 1997-05-08

Ronald F. Guilmette <rfg@monkeys.com>
-Infinite Monkeys & Co.
+RG Consulting
1751 East Roseville Pkwy. #1828
Roseville, CA 95661
Tel: +1 916 786 7945
@@ -315,26 +561,20 @@ Other qualifications:
Rates: Variable depending upon contract duration. Call for quote.
-Updated: 23Sep95
+Updated: 1997-05-07

-Hundred Acre Consulting <info@pooh.com>
-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.
+Michael P. Deignan
+Ideamation, Inc.
+136 Nelson Street
+Providence, RI 02908
+(401) 331-3708
+(401) 272-6449 fax.
-Consulting rates: $70 to $90 per hour, or fixed bid.
-Support contracts: Several levels, from $495 to $90000 per year.
+Rate: Varies depending on complexity of task.
+ Hourly and fixed-rate contracts are available.
+Programs Supported: All
-Updated: 27Dec94
+Updated: 1997-05-07

Interactive Information Limited
@@ -359,199 +599,441 @@ You can contact us
Edinburgh EH3 9HH
Scotland
-Entered: 13Nov95
+Entered: 1997-05-09

-Scott D. Kalter <sdk@mithril.com)
+Scott D. Kalter <sdk@twinsun.com>
2032 Corral Canyon
Malibu, CA 90265-9503
Home: (310) 456-0254
-Emacs: Eoops, Elisp, and C level customization/extension training for
- general use and customization user support, installation, and
- troubleshooting.
+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 (Eoops) 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.
-Rates: $50/hr
- May answer brief and interesting questions for free.
- Prefer e-mail communication to telephone.
-
-Qualifications: BS Math/CS 1985: Carnegie Mellon University
- MS CS 1988: UCLA
+Prefer e-mail communication to telephone calls.
- 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.
-
-Updated: 6Apr94
+Updated: 1997-05-07

-KAMAN SCIENCES CORPORATION
-258 GENESEE STREET
-UTICA NY 13502
-(315) 734-3600
-
-CONTACTS: Alan Piszcz (peesh) <apiszcz@utica1.kaman.com>
- : Dennis Fitzgerald <dennis@utica.kaman.com>
-
+Kaman Sciences Corporation
+Griffiss Business & Technology Park
+775 Daedalian Drive
+Rome, NY 13441-4909
+(315) 334-4900
+
+CONTACTS:
+ Dennis Fitzgerald <dfitzgerald@rome.kaman.com>
+ Tom Robbins <trobbins@rome.kaman.com>
+
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 <sjk@aura.nbn.com>
-P.O. Box 620207
-Woodside, CA 94062
-+1 415-941-0755
-
-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.
-
-Systems Administration: Sun (SunOS & Solaris) and SGI (IRIX)
- UNIX hardware/software platforms.
-
-Rate: Task- and time-dependent; non-monetary offers accepted.
-
-Updated: 12Apr94
+Joseph R. Kiniry <kiniry@cs.caltech.edu>
+Caltech Mailstop 256-80 http://www.cs.caltech.edu/~kiniry/
+Pasadena, CA 91125 <jrk@metagenesis.com>
+Phone: 818-395-4840
+Fax: 818-792-4257
+
+Long-term high-level consultant 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 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: 1997-05-07

-Fen Labalme <fen@comedia.com)
-Broadcatch Technologies
-40 Carl St. #4 WE ARE EVERYWHERE
-San Francisco CA 94117 JUST SAY "KNOW"
-(415) 731-1174 ARE YOU KIND?
-
-Rates: $80 hour (negotiable); quick email or phone questions free.
- Lower rates -- free of barter -- for schools and non-profits.
+Bradley M. Kuhn
+<bkuhn@acm.org>
+http://www.ebb.org/bkuhn
+
+I am available for Unix system administration 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.
+
+I am particularly skilled at integration of GNU and other copy-lefted software
+into new environments that have not used such tools in the past, and porting
+the GNU software to new Unix-based platforms.
+
+Please visit my homepage for more information on my background and skills. My
+resume is also available there.
+
+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.
+
+My rate varies greatly between $25-$40/hour, depending on the circumstances.
+Rates for non-profit organizations are substantially lower, and possibly free.
+
+Please note that I have no interest in working with any Micro$oft related
+products! I want the primary focus of my work to be contributing
+to the free software community.
+
+Updated: 1997-12-04
+
+Fen Labalme <fen@comedia.com>
+CoMedia Consulting http//www.comedia.com/comedia/
+40 Carl Street #4 WE ARE EVERYWHERE
+San Francisco CA 94117 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: $75 hour & up, depending; flat rate jobs considered.
+ Lower rates, barter or free for selected non-profits.
-Updated: 6Apr94
+Updated: 1997-05-07

Greg Lehey
LEMIS
-Schellnhausen 2
-36325 Feldatal
-Germany
+PO Box 460
+Echunga SA 5153
+Australia
-Phone: +49-6637-919123
-Fax: +49-6637-919122
-Mail <grog@lemis.de>
+Phone: +61-8-8388-8250
+Fax: +61-8-8388-8250
+Mobile: +61-41-739-7062
+Mail <grog@lemis.com>
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: 20 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 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: Choice of AUD 120 per hour or hotline rates AUD 2.50 DM 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: 21Feb95
+Updated: 1997-05-09

-Marty Leisner <leisner@sdsp.mc.xerox.com>
-332 Shaftsbury Road
-Rochester, New York 14610
-Home:(716) 654-7931
+Rohan Lenard <rjl@wr.com.au>
+32 Holtermann St.
+Crows Nest, NSW 2065
+AUSTRALIA
++61 411250024
+
+* The human face behind the bug-g++@prep.ai.mit.edu mailing list - known
+ in the past as <rjl@iassf.easams.com.au> and <rjl@ot.com.au> - now
+ known as <rjl@wr.com.au>.
-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
+* 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.
+Degrees: BSc (CS), BE (Comms), University of Melbourne
-marty
-<leisner@sdsp.mc.xerox.com> <leisner@eso.mc.xerox.com>
+Rates: AUS $75+/hr neg.
-Updated: 15Apr94
+Updated: 1997-05-17
+
+Reuven M. Lerner <reuven@netvision.net.il>
+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: 1997-05-07

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: <levitte@e.kth.se> (preferred)
- <levitte@vms.stacken.kth.se>
+Tel.nr.: +46 (8) 26 52 47 (there is an answering machine)
+Cellular: +46 (10) 222 64 05
+e-mail: <levitte@lp.se>
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
+
+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
+
+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
+
+Gord Matzigkeit <gord@gnu.org>
+2220 Capitol Hill Crescent http://www.m-tech.ab.ca/~gord/
+Calgary, Alberta T2M 4B9 Voice: (403) 282-1387
+CANADA FAX: (403) 284-0137
+
+I will help install badly-behaved source code packages, and have experience
+fixing them to conform to GNU standards. I will gladly help novices and
+intermediate computer users to understand, install, 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 do not want to
+solve your problem myself.
+
+I have installed and administered free and proprietary systems in home,
+academic, and business environments. I have practical experience in most
+aspects of Unix and network security. I know how to diagnose a complex
+existing computer system and incrementally replace it with a superior free
+system without disrupting service.
+
+I have over 2 years of experience with several of the major free OSes:
+Linux/GNU (Red Hat, Debian, Slackware), NetBSD, FreeBSD, and GNU/Hurd. I am
+the maintainer of GNU Libtool and GNU DLD. Some of my specialties are:
+Emacs, Automake, Autoconf, SANE, C, Perl, and shell script programming.
+
+My rates start at $10 (Canadian dollars) per hour. When I am not starving, I
+do not charge worthy non-profit organizations.
+
+Updated: 1997-05-08
+
+Andrew McCallum
+6623 Dalzell Place
+Pittsburgh, PA 15217
+Home: (412) 422-0688
+<mccallum@cs.cmu.edu>
+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
+
+Erik Naggum <erik@naggum.no>
+P.O. Box 1570 Vika http://www.naggum.no
+0118 OSLO phone: +47 8800 8879
+NORWAY NIC handle: EN9
+
+Background: I have extensive experience with programming under Unix, in C
+in particular (since 1983), with standards and specifications for Internet
+protocols (since 1987), International Standards for character sets and
+encoding schemes (since 1988), ISO 8879 SGML (since 1990, national head of
+delegation to ISO/IEC JTC 1/SC 18/WG 8 since 1991), and ANSI X3.226 Common
+Lisp (since early 1994). I have been an Emacs user and programmer from
+1984 to 1987 (TOPS-20) and from 1991 to present (Unix). since early 1994,
+I have worked on GNU Emacs development, in both Lisp and C, and since mid
+1995, I have been tracking the development code.
+
+Services I offer the free software community include supporting Emacs users
+and programmers with expert advice (gratis on USENET or mailing lists where
+others may benefit), customizing and writing Emacs functions and packages,
+delivering courses and seminars from tutorials to writing Emacs Lisp and C
+extensions, and providing general aid with all GNU software.
+
+My standard rate is a flat USD 80 per hour or USD 2 per minute (you decide
+which time unit to apply), but to offset the cost of processing money, the
+minimum credit card charge is USD 100 and the minimum invoiced amount is
+USD 250. Discounts are available to worthy causes -- present your case.
+Time away from home is billed at USD 40 per hour around the clock to
+encourage remote work. (Courses and seminars are negotiated individually.)
+
+Please call only about actual work, I prefer mail for all other questions.
+
+Updated: 1997-07-18
+
+NET-Community <sales@net-community.com>
+522 SW 5th Avenue http://www.net-community.com
+Suite 1105
+Portland, OR 97204 USA
+1-800-919-0060 voice
+1-503-274-4423 voice
+1-503-274-5406 fax
+
+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: 1997-05-12
+
+ Open Systems Consultants a.s
+ St. Olavsgt. 24
+ N-0166 OSLO
+ NORWAY
+
+Phone: Fax:
+ +47 22 20 40 50 +47 22 20 02 85
+
+Web: E-mail:
+ http://www.osc.no <gnu-support@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. No phone support.
-Entered: 18Aug94
+Updated: 1997-05-08

-Roland McGrath <roland@frob.com>
-545 Tech Sq, Rm 426
-Cambridge, MA 02139
-Work: (617) 253-8568
+Francesco Potorti` <F.Potorti@cnuce.cnr.it>
+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.
-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.
+Qualifications: Electronic Engineering degree, Pisa. Full time
+ researcher in CNUCE-CNR.
+ Familiar with elisp programming and porting of C programs.
-Installation, maintenance, porting, enhancement of all GNU software. I can
-install GNU software and maintain its installation on call via the Internet.
+Updated: 1997-05-08
+
+Dipl.-Inform. Klaus Kaempf <kkaempf@progis.de>
+proGIS Software
+Jakobstr. 117
+D-52064 Aachen
+Germany
+http://www.progis.de
+Tel +49 241 470670
+Fax +49 241 4706729
+
+- 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.
-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.
+We do a lot of cross-platform (Unix-VMS-WindowsNT) development
+mostly with the GNU compiler environment. We are actively
+supporting GNU software on openVMS/Alpha.
-Updated: 21Jan95
+Rates start at 160.- DM / hour for support and
+installation. Larger projects are negotiable.
+
+Updated: 1997-05-08
+
+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 <wolfgang@wsrcc.com>
47 Esparito Ave.
@@ -564,86 +1046,138 @@ 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
+617.924.6437
+<acs@acm.org>
+
+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 beta testing
+team - I'm responsible for maintaining the version 19.15 patches and have
+written a few small packages/lisp hacks. My rates vary from $60 - $100 per
+hour, depending on the size of the project.
+
+Updated: 1997-05-09

Signum Support AB <info@signum.se>
-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. <postmaster@anomaly.sbs.com>
-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. <stacey@freefall.cdrom.com>
-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 <rms@prep.ai.mit.edu>
-UUCP: {mit-eddie,ucbvax,uunet,harvard,uw-beaver}!ai.mit.edu!rms
+ Jon Solomon <jsol@gnu.org>
+ 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 <jhs@freebsd.org>
+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 <rms@gnu.org>
545 Tech Sq, Rm 430
Cambridge, MA 02139
@@ -654,104 +1188,140 @@ 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 <support@spird.jos.ec.lu.se>
-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@satyr.Sylvan.COM>
+Kayvan Sylvan <kayvan@sylvan.com>
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
+
+TerraTel AB <info@netg.se>
+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: <bkis@island.net> (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 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. <tower@prep.ai.mit.edu>
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. 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 <info@usoft.spb.su>
-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: 1997-05-24

-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
<info@noris.de>
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,84 +1336,82 @@ 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 <jbw@cs.bu.edu>
-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
+ <P.vanGool@LR.TUDelft.NL>
-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: Faculty of Aerospace Engineering
+ Delft University of Technology
+ Kluyverweg 1, 2629 HS Delft
+ 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: <ru@ccnext.ucsf.edu>
-
-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. <info@yggdrasil.com>
-4880 Stevens Creek Blvd. Ste. 205
-San Jose, CA 95129
-(408) 261-6630
-(800) 261 6630
-
-Updated: 14Apr94
+Phone: +31-15-2785370
+Fax : +31-15-2786480
+
+I would like to provide unpaid support for the following things:
+
+- C
+- C++
+- f2c
+- compilation and installation of most GNU packages
+
+Updated: 1997-05-12
+
+Arne Wichmann
+
+EMail: <aw@math.uni-sb.de>
+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, <jody@sccsi.com>
+
+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: <zhou@opentech.co.jp>
+
+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:
diff --git a/gnu/usr.bin/gcc/alloca.c b/gnu/usr.bin/gcc/alloca.c
index 7020f32c882..8f98b73dbb9 100644
--- a/gnu/usr.bin/gcc/alloca.c
+++ b/gnu/usr.bin/gcc/alloca.c
@@ -25,6 +25,13 @@
#include <config.h>
#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#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/gnu/usr.bin/gcc/basic-block.h b/gnu/usr.bin/gcc/basic-block.h
index 3755388c92b..c76d8507b7c 100644
--- a/gnu/usr.bin/gcc/basic-block.h
+++ b/gnu/usr.bin/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 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. */
@@ -57,6 +113,10 @@ extern rtx *basic_block_end;
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 +126,5 @@ 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) (reg_n_info[(N)].basic_block)
diff --git a/gnu/usr.bin/gcc/bc-emit.c b/gnu/usr.bin/gcc/bc-emit.c
index 9a7c0f981b6..e67011dff7e 100644
--- a/gnu/usr.bin/gcc/bc-emit.c
+++ b/gnu/usr.bin/gcc/bc-emit.c
@@ -1,5 +1,5 @@
/* Output bytecodes for GNU C-compiler.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#ifdef __STDC__
#include <stdarg.h>
#else
@@ -38,10 +39,7 @@ Boston, MA 02111-1307, USA. */
#include "bc-typecd.h"
#include "bi-run.h"
-#include <stdio.h>
-
extern char *xmalloc (), *xrealloc ();
-extern void free ();
extern struct obstack *rtl_obstack;
@@ -56,12 +54,13 @@ extern enum machine_mode byte_mode;
/* Mode whose width is BITS_PER_WORD */
extern enum machine_mode word_mode;
-/* Vector indexed by opcode giving info about the args for each opcode. */
+/* Vector indexed by opcode giving info about the args for each opcode. */
static struct arityvec arityvec[] = {
#include "bc-arity.h"
};
/* How to print a symbol name for the assembler. */
+
static void
prsym (file, s)
FILE *file;
@@ -79,7 +78,7 @@ prsym (file, s)
}
-/* Maintain a bucket hash table for symbol names. */
+/* Maintain a bucket hash table for symbol names. */
#define HASH_BITS 32
#define HASH_SIZE 509
@@ -102,7 +101,8 @@ hash (name)
}
-/* Look up the named symbol, creating it if it doesn't exist. */
+/* Look up the named symbol, creating it if it doesn't exist. */
+
struct bc_sym *
sym_lookup (name)
char *name;
@@ -127,6 +127,7 @@ sym_lookup (name)
/* Write out .globl and common symbols to the named file. */
+
static void
bc_sym_write (file)
FILE *file;
@@ -161,7 +162,8 @@ bc_sym_write (file)
-/* Create and initialize a new segment. */
+/* Create and initialize a new segment. */
+
static struct bc_seg *
seg_create ()
{
@@ -177,7 +179,8 @@ seg_create ()
}
-/* Advance the segment index to the next alignment boundary. */
+/* Advance the segment index to the next alignment boundary. */
+
static void
seg_align (seg, log)
struct bc_seg *seg;
@@ -196,7 +199,8 @@ seg_align (seg, log)
}
-/* Append the given data to the given segment. */
+/* Append the given data to the given segment. */
+
static void
seg_data (seg, data, size)
struct bc_seg *seg;
@@ -216,6 +220,7 @@ seg_data (seg, data, size)
/* Append a zero-filled skip to the given segment. */
+
static void
seg_skip (seg, size)
struct bc_seg *seg;
@@ -235,7 +240,8 @@ seg_skip (seg, size)
/* Define the given name as the current offset in the given segment. It
is an error if the name is already defined. Return 0 or 1 indicating
- failure or success respectively. */
+ failure or success respectively. */
+
static int
seg_defsym (seg, name)
struct bc_seg *seg;
@@ -259,7 +265,8 @@ seg_defsym (seg, name)
/* Generate in seg's data a reference to the given sym, adjusted by
- the given offset. */
+ the given offset. */
+
static void
seg_refsym (seg, name, offset)
struct bc_seg *seg;
@@ -279,7 +286,8 @@ seg_refsym (seg, name, offset)
}
-/* Concatenate the contents of given segments into the first argument. */
+/* Concatenate the contents of given segments into the first argument. */
+
static void
seg_concat (result, seg)
struct bc_seg *result, *seg;
@@ -294,7 +302,7 @@ seg_concat (result, seg)
free (seg->data);
/* Go through the symbols and relocs of SEG, adjusting their offsets
- for their new location in RESULT. */
+ for their new location in RESULT. */
if (seg->syms)
{
segsym = seg->syms;
@@ -318,6 +326,7 @@ seg_concat (result, seg)
}
/* Write a segment to a file. */
+
static void
bc_seg_write (seg, file)
struct bc_seg *seg;
@@ -392,11 +401,12 @@ bc_seg_write (seg, file)
-/* Text and data segments of the object file in making. */
+/* Text and data segments of the object file in making. */
static struct bc_seg *bc_text_seg;
static struct bc_seg *bc_data_seg;
-/* Called before anything else in this module. */
+/* Called before anything else in this module. */
+
void
bc_initialize ()
{
@@ -444,25 +454,26 @@ bc_initialize ()
require us to provide hairy location info and possibly obey alignment
rules imposed by the architecture) we build an auxiliary table of
pointer constants, and encode just offsets into this table into the
- actual bytecode. */
+ actual bytecode. */
static struct bc_seg *ptrconsts;
/* Trampoline code for the function entry. */
struct bc_seg *trampoline;
-/* Actual byte code of the function. */
+/* Actual byte code of the function. */
struct bc_seg *bytecode;
-/* List of labels defined in the function. */
+/* List of labels defined in the function. */
struct bc_label *labels;
-/* List of label references in the function. */
+/* List of label references in the function. */
struct bc_labelref *labelrefs;
/* Add symbol to pointer table. Return offset into table where
pointer was stored. The offset usually goes into the bytecode
- stream as a constP literal. */
+ stream as a constP literal. */
+
int
bc_define_pointer (p)
char *p;
@@ -475,6 +486,7 @@ bc_define_pointer (p)
/* Begin a bytecoded function. */
+
int
bc_begin_function (name)
char *name;
@@ -487,6 +499,7 @@ bc_begin_function (name)
/* Force alignment in inline bytecode. */
+
void
bc_align_bytecode (align)
int align;
@@ -496,6 +509,7 @@ bc_align_bytecode (align)
/* Emit data inline into bytecode. */
+
void
bc_emit_bytecode_const (data, size)
char *data;
@@ -508,7 +522,8 @@ bc_emit_bytecode_const (data, size)
/* Create a new "bytecode label", to have its value defined later.
Bytecode labels have nothing to do with the object file symbol table,
- and are purely local to a given bytecoded function. */
+ and are purely local to a given bytecoded function. */
+
struct bc_label *
bc_get_bytecode_label ()
{
@@ -523,7 +538,8 @@ bc_get_bytecode_label ()
}
-/* Define the given label with the current location counter. */
+/* Define the given label with the current location counter. */
+
int
bc_emit_bytecode_labeldef (label)
struct bc_label *label;
@@ -546,7 +562,8 @@ bc_emit_bytecode_labeldef (label)
/* Generate a location-relative reference to the given bytecode label.
- It need not be defined yet; label references will be backpatched later. */
+ It need not be defined yet; label references will be backpatched later. */
+
void
bc_emit_bytecode_labelref (label)
struct bc_label *label;
@@ -569,7 +586,8 @@ bc_emit_bytecode_labelref (label)
/* Emit a reference to an external address; generate the reference in the
- ptrconst area, and emit an offset in the bytecode. */
+ ptrconst area, and emit an offset in the bytecode. */
+
void
bc_emit_code_labelref (name, offset)
char *name;
@@ -590,6 +608,7 @@ bc_emit_code_labelref (name, offset)
/* Backpatch label references in the byte code, and concatenate the bytecode
and pointer constant segments to the cumulative text for the object file.
Return a label name for the pointer constants region. */
+
char *
bc_end_function ()
{
@@ -599,7 +618,7 @@ bc_end_function ()
char ptrconsts_label[20];
static int nlab;
- /* Backpatch bytecode label references. */
+ /* Backpatch bytecode label references. */
for (ref = labelrefs; ref; ref = ref->next)
if (ref->label->defined)
{
@@ -607,7 +626,7 @@ bc_end_function ()
bcopy ((char *) &addr, bytecode->data + ref->offset, sizeof addr);
}
- /* Free the chains of labelrefs and labeldefs. */
+ /* Free the chains of labelrefs and labeldefs. */
for (ref = labelrefs; ref; ref = nextref)
{
nextref = ref->next;
@@ -636,7 +655,8 @@ bc_end_function ()
return sym_lookup (ptrconsts_label)->name;
}
-/* Force alignment in const data. */
+/* Force alignment in const data. */
+
void
bc_align_const (align)
int align;
@@ -644,7 +664,8 @@ bc_align_const (align)
seg_align (bc_text_seg, align);
}
-/* Emit const data. */
+/* Emit const data. */
+
void
bc_emit_const (data, size)
char *data;
@@ -653,7 +674,8 @@ bc_emit_const (data, size)
seg_data (bc_text_seg, data, size);
}
-/* Emit a zero-filled constant skip. */
+/* Emit a zero-filled constant skip. */
+
void
bc_emit_const_skip (size)
unsigned int size;
@@ -661,7 +683,8 @@ bc_emit_const_skip (size)
seg_skip (bc_text_seg, size);
}
-/* Emit a label definition in const data. */
+/* Emit a label definition in const data. */
+
int
bc_emit_const_labeldef (name)
char *name;
@@ -669,7 +692,8 @@ bc_emit_const_labeldef (name)
return seg_defsym (bc_text_seg, name);
}
-/* Emit a label reference in const data. */
+/* Emit a label reference in const data. */
+
void
bc_emit_const_labelref (name, offset)
char *name;
@@ -678,7 +702,8 @@ bc_emit_const_labelref (name, offset)
seg_refsym (bc_text_seg, name, offset);
}
-/* Force alignment in data. */
+/* Force alignment in data. */
+
void
bc_align_data (align)
int align;
@@ -686,7 +711,8 @@ bc_align_data (align)
seg_align (bc_data_seg, align);
}
-/* Emit data. */
+/* Emit data. */
+
void
bc_emit_data (data, size)
char *data;
@@ -696,6 +722,7 @@ bc_emit_data (data, size)
}
/* Emit a zero-filled data skip. */
+
void
bc_emit_data_skip (size)
unsigned int size;
@@ -703,7 +730,8 @@ bc_emit_data_skip (size)
seg_skip (bc_data_seg, size);
}
-/* Emit label definition in data. */
+/* Emit label definition in data. */
+
int
bc_emit_data_labeldef (name)
char *name;
@@ -711,7 +739,8 @@ bc_emit_data_labeldef (name)
return seg_defsym (bc_data_seg, name);
}
-/* Emit label reference in data. */
+/* Emit label reference in data. */
+
void
bc_emit_data_labelref (name, offset)
char *name;
@@ -723,6 +752,7 @@ bc_emit_data_labelref (name, offset)
/* Emit a common block of the given name and size. Note that
when the .o file is actually written non-global "common"
blocks will have to be turned into space in the data section. */
+
int
bc_emit_common (name, size)
char *name;
@@ -740,7 +770,8 @@ bc_emit_common (name, size)
return 1;
}
-/* Globalize the given label. */
+/* Globalize the given label. */
+
void
bc_globalize_label (name)
char *name;
@@ -847,6 +878,7 @@ bc_gen_rtx (label, offset, bc_label)
/* Print bytecode rtx */
+
void
bc_print_rtl (fp, r)
FILE *fp;
@@ -861,6 +893,7 @@ bc_print_rtl (fp, r)
/* Emit a bytecode, keeping a running tally of the stack depth. */
+
void
bc_emit_bytecode (bytecode)
enum bytecode_opcode bytecode;
@@ -884,7 +917,7 @@ bc_emit_bytecode (bytecode)
will cause an interpreter stack undeflow when executed. Instead of
dumping core on such occasions, we omit the bytecode. Erroneous code
should not be executed, regardless. This makes life much easier, since
- we don't have to deceive ourselves about the known stack depth. */
+ we don't have to deceive ourselves about the known stack depth. */
bc_emit_bytecode_const (&byte, 1);
@@ -908,7 +941,8 @@ bc_emit_bytecode (bytecode)
/* Emit a complete bytecode instruction, expecting the correct number
of literal values in the call. First argument is the instruction, the
- remaining arguments are literals of size HOST_WIDE_INT or smaller. */
+ remaining arguments are literals of size HOST_WIDE_INT or smaller. */
+
void
bc_emit_instruction VPROTO((enum bytecode_opcode opcode, ...))
{
@@ -955,6 +989,8 @@ bc_emit_instruction VPROTO((enum bytecode_opcode opcode, ...))
}
}
+ va_end (arguments);
+
#ifdef BCDEBUG_PRINT_CODE
fputc ('\n', stderr);
#endif
@@ -964,6 +1000,7 @@ bc_emit_instruction VPROTO((enum bytecode_opcode opcode, ...))
coded function. The argument is a label name of the interpreter
bytecode callinfo structure; the return value is a label name for
the beginning of the actual bytecode. */
+
char *
bc_emit_trampoline (callinfo)
char *callinfo;
@@ -978,15 +1015,3 @@ bc_emit_trampoline (callinfo)
seg_defsym (bytecode, mylab);
return sym_lookup (mylab)->name;
}
-
-
-/* Simple strdup */
-char *
-bc_xstrdup (str)
- char *str;
-{
- char *tmp = xmalloc (strlen (str) + 1);
-
- strcpy (tmp, str);
- return tmp;
-}
diff --git a/gnu/usr.bin/gcc/bc-optab.c b/gnu/usr.bin/gcc/bc-optab.c
index b7ff4865237..4837d33850f 100644
--- a/gnu/usr.bin/gcc/bc-optab.c
+++ b/gnu/usr.bin/gcc/bc-optab.c
@@ -1,5 +1,5 @@
/* Bytecode conversion definitions for GNU C-compiler.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,10 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
#include "tree.h"
#include "rtl.h"
#include "machmode.h"
@@ -33,7 +37,6 @@ Boston, MA 02111-1307, USA. */
#define obstack_chunk_free free
extern char *xmalloc ();
-extern void free ();
/* Table relating interpreter typecodes to machine modes. */
#define GET_TYPECODE_MODE(CODE) (typecode_mode[((int) CODE)])
@@ -56,8 +59,8 @@ static enum typecode unsigned_mode_to_code_map[MAX_MACHINE_MODE+1];
static struct conversion_recipe
{
unsigned char *opcodes; /* Bytecodes to emit in order. */
- int nopcodes; /* Count of bytecodes. */
- int cost; /* A rather arbitrary cost function. */
+ int nopcodes; /* Count of bytecodes. */
+ int cost; /* A rather arbitrary cost function. */
} conversion_recipe[NUM_TYPECODES][NUM_TYPECODES];
/* Binary operator tables. */
@@ -406,6 +409,7 @@ struct conversion_list
* Either sign extensions or zero extensions may be present, but not both.
* No widening conversions occur after a signed/unsigned conversion.
* The sequence of sizes must be strict nonincreasing or nondecreasing. */
+
static int
conversion_reasonable_p (conversion, list)
struct conversion_info *conversion;
@@ -518,6 +522,7 @@ conversion_reasonable_p (conversion, list)
/* Exhaustively search all reasonable conversions to find one to
convert the given types. */
+
static struct conversion_recipe
deduce_conversion (from, to)
enum typecode from, to;
@@ -535,9 +540,9 @@ deduce_conversion (from, to)
obstack_init (&recipe_obstack);
curr.next = (struct rl *) obstack_alloc (&recipe_obstack, sizeof (struct rl));
- curr.next->list =
- (struct conversion_list *) obstack_alloc (&recipe_obstack,
- sizeof (struct conversion_list));
+ curr.next->list
+ = (struct conversion_list *) obstack_alloc (&recipe_obstack,
+ sizeof (struct conversion_list));
curr.next->list->opcode = -1;
curr.next->list->to = from;
curr.next->list->cost = 0;
@@ -615,6 +620,7 @@ deduce_conversion (from, to)
/* Emit a conversion between the given scalar types. */
+
void
emit_typecode_conversion (from, to)
enum typecode from, to;
@@ -628,6 +634,7 @@ emit_typecode_conversion (from, to)
/* Initialize mode_to_code_map[] */
+
void
bc_init_mode_to_code_map ()
{
@@ -635,9 +642,9 @@ bc_init_mode_to_code_map ()
for (mode = 0; mode < MAX_MACHINE_MODE + 1; mode++)
{
- signed_mode_to_code_map[mode] =
- unsigned_mode_to_code_map[mode] =
- LAST_AND_UNUSED_TYPECODE;
+ signed_mode_to_code_map[mode]
+ = unsigned_mode_to_code_map[mode]
+ = LAST_AND_UNUSED_TYPECODE;
}
#define DEF_MODEMAP(SYM, CODE, UCODE, CONST, LOAD, STORE) \
@@ -651,6 +658,7 @@ bc_init_mode_to_code_map ()
}
/* Given a machine mode return the preferred typecode. */
+
enum typecode
preferred_typecode (mode, unsignedp)
enum machine_mode mode;
@@ -669,6 +677,7 @@ preferred_typecode (mode, unsignedp)
/* Expand a conversion between the given types. */
+
void
bc_expand_conversion (from, to)
tree from, to;
@@ -682,6 +691,7 @@ bc_expand_conversion (from, to)
}
/* Expand a conversion of the given type to a truth value. */
+
void
bc_expand_truth_conversion (from)
tree from;
@@ -693,6 +703,7 @@ bc_expand_truth_conversion (from)
}
/* Emit an appropriate binary operation. */
+
void
bc_expand_binary_operation (optab, resulttype, arg0, arg1)
struct binary_operator optab[];
@@ -734,6 +745,7 @@ bc_expand_binary_operation (optab, resulttype, arg0, arg1)
}
/* Emit an appropriate unary operation. */
+
void
bc_expand_unary_operation (optab, resulttype, arg0)
struct unary_operator optab[];
@@ -770,6 +782,7 @@ bc_expand_unary_operation (optab, resulttype, arg0)
/* Emit an appropriate increment. */
+
void
bc_expand_increment (optab, type)
struct increment_operator optab[];
diff --git a/gnu/usr.bin/gcc/bi-arity.c b/gnu/usr.bin/gcc/bi-arity.c
index da3607fbf5d..ea1f3e1de08 100644
--- a/gnu/usr.bin/gcc/bi-arity.c
+++ b/gnu/usr.bin/gcc/bi-arity.c
@@ -63,7 +63,8 @@ main ()
}
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
- memory. */
+ memory. */
+
char *
xmalloc (nbytes)
int nbytes;
@@ -78,3 +79,13 @@ xmalloc (nbytes)
return tmp;
}
+
+/* More 'friendly' abort that prints the line and file.
+ config.h can #define abort fancy_abort if you like that sort of thing. */
+
+void
+fancy_abort ()
+{
+ fprintf (stderr, "Internal gcc abort.\n");
+ exit (FATAL_EXIT_CODE);
+}
diff --git a/gnu/usr.bin/gcc/bi-lexer.c b/gnu/usr.bin/gcc/bi-lexer.c
index 6601c52c05b..0ec0b1d56d3 100644
--- a/gnu/usr.bin/gcc/bi-lexer.c
+++ b/gnu/usr.bin/gcc/bi-lexer.c
@@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
- memory. */
+ memory. */
static char *
xmalloc (nbytes)
@@ -43,7 +43,7 @@ xmalloc (nbytes)
/* Safely reallocate BLOCK so its size becomes NBYTES.
- The block returned may be different from the one supplied. */
+ The block returned may be different from the one supplied. */
static char *
xrealloc (block, nbytes)
@@ -68,7 +68,7 @@ xrealloc (block, nbytes)
purposes here, a sequence of characters that starts with the regexp
``[^ #\t\n(),]'' and is then followed by the regexp ``[^#(),]*''. Any
character is accepted if preceded by a backslash, "\\". It is assumed
- that the first character has already been checked by the main loop. */
+ that the first character has already been checked by the main loop. */
static char *
scan_string ()
diff --git a/gnu/usr.bin/gcc/bi-opcode.c b/gnu/usr.bin/gcc/bi-opcode.c
index 6b1ebe4a69e..795bb6fb275 100644
--- a/gnu/usr.bin/gcc/bi-opcode.c
+++ b/gnu/usr.bin/gcc/bi-opcode.c
@@ -61,7 +61,8 @@ main(argc, argv)
}
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
- memory. */
+ memory. */
+
char *
xmalloc (nbytes)
int nbytes;
@@ -76,3 +77,13 @@ xmalloc (nbytes)
return tmp;
}
+
+/* More 'friendly' abort that prints the line and file.
+ config.h can #define abort fancy_abort if you like that sort of thing. */
+
+void
+fancy_abort ()
+{
+ fprintf (stderr, "Internal gcc abort.\n");
+ exit (FATAL_EXIT_CODE);
+}
diff --git a/gnu/usr.bin/gcc/bi-opname.c b/gnu/usr.bin/gcc/bi-opname.c
index 1862e7120fb..2f41dd27dbc 100644
--- a/gnu/usr.bin/gcc/bi-opname.c
+++ b/gnu/usr.bin/gcc/bi-opname.c
@@ -42,7 +42,8 @@ main()
}
/* Safely allocate NBYTES bytes of memory. Returns pointer to block of
- memory. */
+ memory. */
+
char *
xmalloc (nbytes)
int nbytes;
@@ -57,3 +58,13 @@ xmalloc (nbytes)
return tmp;
}
+
+/* More 'friendly' abort that prints the line and file.
+ config.h can #define abort fancy_abort if you like that sort of thing. */
+
+void
+fancy_abort ()
+{
+ fprintf (stderr, "Internal gcc abort.\n");
+ exit (FATAL_EXIT_CODE);
+}
diff --git a/gnu/usr.bin/gcc/build-make b/gnu/usr.bin/gcc/build-make
index 1d6e18be6f8..116d579ba66 100644
--- a/gnu/usr.bin/gcc/build-make
+++ b/gnu/usr.bin/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,6 +24,9 @@ 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
diff --git a/gnu/usr.bin/gcc/bytecode.h b/gnu/usr.bin/gcc/bytecode.h
index f2233aa880d..a029f93f602 100644
--- a/gnu/usr.bin/gcc/bytecode.h
+++ b/gnu/usr.bin/gcc/bytecode.h
@@ -1,5 +1,5 @@
/* Bytecode definitions for GNU C-compiler.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -57,6 +57,7 @@ extern void bc_init_mode_to_code_map ();
#define BC_NOP (0)
#define BC_GLOBALIZE_LABEL(FP, NAME) BC_NOP
#define BC_OUTPUT_COMMON(FP, NAME, SIZE, ROUNDED) BC_NOP
+#define BC_OUTPUT_BSS(FP, NAME, SIZE, ROUNDED) BC_NOP
#define BC_OUTPUT_LOCAL(FP, NAME, SIZE, ROUNDED) BC_NOP
#define BC_OUTPUT_ALIGN(FP, ALIGN) BC_NOP
#define BC_OUTPUT_LABEL(FP, NAME) BC_NOP
diff --git a/gnu/usr.bin/gcc/c-aux-info.c b/gnu/usr.bin/gcc/c-aux-info.c
index d8caa6af194..a14d6225664 100644
--- a/gnu/usr.bin/gcc/c-aux-info.c
+++ b/gnu/usr.bin/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, 1991, 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@segfault.us.com).
This file is part of GNU CC.
@@ -21,13 +21,13 @@ 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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "flags.h"
#include "tree.h"
#include "c-tree.h"
-extern char* xmalloc ();
+extern char *xmalloc ();
enum formals_style_enum {
ansi,
@@ -37,26 +37,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 +73,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 +113,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 +156,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 +172,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 +278,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,9 +353,9 @@ gen_formal_list_for_func_def (fndecl, style)
to do at this point is for the initial caller to prepend the "data_type"
string onto the returned "seed". */
-static char*
+static char *
gen_type (ret_val, t, style)
- char* ret_val;
+ char *ret_val;
tree t;
formals_style style;
{
@@ -517,13 +517,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 +581,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 +591,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/gnu/usr.bin/gcc/c-common.c b/gnu/usr.bin/gcc/c-common.c
index 78b4d858acb..e7d7f71ac8b 100644
--- a/gnu/usr.bin/gcc/c-common.c
+++ b/gnu/usr.bin/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, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,24 +19,92 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "c-lex.h"
#include "c-tree.h"
#include "flags.h"
#include "obstack.h"
-#include <stdio.h>
#include <ctype.h>
+#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};
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_international_format PROTO((tree, tree, int));
+
+/* Keep a stack of if statements. The value recorded is the number of
+ compound statements seen up to the if keyword. */
+static int *if_stack;
+
+/* Amount of space in the if statement stack. */
+static int if_stack_space = 0;
+
+/* Stack pointer. */
+static int if_stack_pointer = 0;
+
+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 = (int *)xmalloc (10 * sizeof (int));
+ }
+ else if (if_stack_space == if_stack_pointer)
+ {
+ if_stack_space += 10;
+ if_stack = (int *)xrealloc (if_stack, if_stack_space * sizeof (int));
+ }
+
+ /* Record this if statement. */
+ if_stack[if_stack_pointer++] = compstmt_count;
+
+ expand_start_cond (cond, exitflag);
+}
+
+void
+c_expand_end_cond ()
+{
+ if_stack_pointer--;
+ expand_end_cond ();
+}
+
+void
+c_expand_start_else ()
+{
+ if (warn_parentheses
+ && if_stack_pointer > 1
+ && if_stack[if_stack_pointer - 1] == if_stack[if_stack_pointer - 2])
+ warning ("suggest explicit braces to avoid ambiguous `else'");
+
+ /* This if statement can no longer cause a dangling else. */
+ if_stack[if_stack_pointer - 1]--;
+
+ expand_start_else ();
+}
/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
@@ -52,15 +120,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);
@@ -157,7 +222,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;
}
}
@@ -250,9 +320,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 +332,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,7 +340,7 @@ 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)
@@ -308,6 +380,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,6 +419,13 @@ 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;
@@ -359,8 +440,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 +467,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
@@ -472,7 +557,8 @@ decl_attributes (node, attributes, prefix_attributes)
&& TREE_CODE (TREE_VALUE (args)) == STRING_CST)
{
if (TREE_CODE (decl) == VAR_DECL
- && current_function_decl != NULL_TREE)
+ && 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 +583,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. */
@@ -556,9 +643,15 @@ decl_attributes (node, attributes, prefix_attributes)
|| !strcmp (IDENTIFIER_POINTER (format_type),
"__scanf__")))
is_scan = 1;
+ else if (TREE_CODE (format_type) == IDENTIFIER_NODE)
+ {
+ error ("`%s' is an unrecognized format function type",
+ IDENTIFIER_POINTER (format_type));
+ continue;
+ }
else
{
- error ("unrecognized format specifier for `%s'");
+ error ("unrecognized format specifier");
continue;
}
@@ -612,7 +705,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)
@@ -629,13 +722,77 @@ decl_attributes (node, attributes, prefix_attributes)
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;
+ }
+
case A_WEAK:
declare_weak (decl);
break;
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)
@@ -654,6 +811,76 @@ 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;
+}
/* Check a printf/fprintf/sprintf/scanf/fscanf/sscanf format against
a parameter list. */
@@ -702,7 +929,7 @@ static format_char_info print_char_table[] = {
/* 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 +#" },
+ { "feEgGaA", 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" },
@@ -715,7 +942,7 @@ static format_char_info print_char_table[] = {
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, "*" },
+ { "efgEGaA", 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, "*" },
@@ -725,7 +952,8 @@ static format_char_info scan_char_table[] = {
{ NULL }
};
-typedef struct function_format_info {
+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++) */
@@ -736,14 +964,27 @@ typedef struct 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 <stdio.h> is
included or not), since it is common to call printf without
including <stdio.h>. 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 ()
@@ -757,6 +998,10 @@ init_function_format_info ()
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_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
@@ -765,7 +1010,7 @@ init_function_format_info ()
false indicates printf-style 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
@@ -801,6 +1046,43 @@ record_function_format (name, assembler_name, is_scan,
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.
@@ -871,9 +1153,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");
@@ -974,9 +1290,12 @@ check_format_info (info, params)
*format_chars);
warning (message);
}
- i = strlen (flag_chars);
- flag_chars[i++] = *format_chars++;
- flag_chars[i] = 0;
+ else
+ {
+ i = strlen (flag_chars);
+ flag_chars[i++] = *format_chars++;
+ flag_chars[i] = 0;
+ }
}
/* "If the space and + flags both appear,
the space flag will be ignored." */
@@ -1067,18 +1386,33 @@ check_format_info (info, params)
}
}
}
- if (*format_chars == 'h' || *format_chars == 'l' || *format_chars == 'q' ||
- *format_chars == 'L')
+ 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)
+ pedwarn ("ANSI C does not support the `%c' length modifier",
+ length_char);
+ }
else
length_char = 0;
if (length_char == 'l' && *format_chars == 'l')
- length_char = 'q', format_chars++;
+ {
+ length_char = 'q', format_chars++;
+ if (pedantic)
+ pedwarn ("ANSI C does not support the `ll' length modifier");
+ }
aflag = 0;
- if (*format_chars == 'a')
+ if (*format_chars == 'a' && info->is_scan)
{
- aflag = 1;
- format_chars++;
+ 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)
{
@@ -1088,7 +1422,7 @@ check_format_info (info, params)
warning (message);
}
format_char = *format_chars;
- if (format_char == 0)
+ if (format_char == 0 || format_char == '%')
{
warning ("conversion lacks type at end of format");
continue;
@@ -1128,6 +1462,8 @@ check_format_info (info, params)
sprintf (message, "`a' flag used with `%c' format",
format_char);
warning (message);
+ /* To simplify the following code. */
+ aflag = 0;
}
if (info->is_scan && format_char == '[')
{
@@ -1170,7 +1506,7 @@ check_format_info (info, params)
|| format_char == 'x' || format_char == 'x'))
{
sprintf (message,
- "precision and `0' flag not both allowed with `%c' format",
+ "`0' flag ignored with precision specifier and `%c' format",
format_char);
warning (message);
}
@@ -1215,28 +1551,52 @@ 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 (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"),
+ ((fci->pointer_count + aflag == 1)
+ ? "pointer" : "pointer to a pointer"),
arg_num);
warning (message);
}
break;
}
+ /* See if this is an attempt to write into a const type with
+ scanf. */
+ if (info->is_scan && 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))))))
+ {
+ sprintf (message, "writing into constant object (arg %d)", arg_num);
+ warning (message);
+ }
+
/* 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.
@@ -1335,7 +1695,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 +1704,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 +1721,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,10 +1757,11 @@ 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)))
- warning ("overflow in implicit constant conversion");
+ if ((pedantic
+ || TREE_UNSIGNED (type)
+ || ! int_fits_type_p (expr, unsigned_type (type)))
+ && skip_evaluation == 0)
+ warning ("overflow in implicit constant conversion");
}
else
unsigned_conversion_warning (t, expr);
@@ -1581,7 +1945,7 @@ void
binary_op_error (code)
enum tree_code code;
{
- register char *opname = "unknown";
+ register char *opname;
switch (code)
{
@@ -1634,6 +1998,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 +2086,8 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
case GE_EXPR:
code = LE_EXPR;
break;
+ default:
+ break;
}
*rescode_ptr = code;
}
@@ -1850,6 +2218,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 +2318,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 +2423,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);
@@ -2090,7 +2471,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 +2485,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,6 +2509,9 @@ 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)
@@ -2149,7 +2533,10 @@ truthvalue_conversion (expr)
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. */
+ 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 +2580,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';
@@ -2229,27 +2617,8 @@ c_build_type_variant (type, constp, volatilep)
int constp, volatilep;
{
if (TREE_CODE (type) == ARRAY_TYPE)
- {
- tree real_main_variant = TYPE_MAIN_VARIANT (type);
-
- push_obstacks (TYPE_OBSTACK (real_main_variant),
- TYPE_OBSTACK (real_main_variant));
- type = build_array_type (c_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
- TYPE_DOMAIN (type));
-
- /* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
- make a copy. (TYPE might have come from the hash table and
- REAL_MAIN_VARIANT might be in some function's obstack.) */
-
- if (TYPE_OBSTACK (type) != TYPE_OBSTACK (real_main_variant))
- {
- type = copy_node (type);
- TYPE_POINTER_TO (type) = TYPE_REFERENCE_TO (type) = 0;
- }
-
- TYPE_MAIN_VARIANT (type) = real_main_variant;
- pop_obstacks ();
- }
+ return build_array_type (c_build_type_variant (TREE_TYPE (type),
+ constp, volatilep),
+ TYPE_DOMAIN (type));
return build_type_variant (type, constp, volatilep);
}
diff --git a/gnu/usr.bin/gcc/c-decl.c b/gnu/usr.bin/gcc/c-decl.c
index ca33a4c99f3..7688dd23d67 100644
--- a/gnu/usr.bin/gcc/c-decl.c
+++ b/gnu/usr.bin/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, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,12 +27,12 @@ Boston, MA 02111-1307, USA. */
line numbers. For example, the CONST_DECLs for enum values. */
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "flags.h"
#include "output.h"
#include "c-tree.h"
#include "c-lex.h"
-#include <stdio.h>
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -411,16 +411,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 +454,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 +471,14 @@ 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 message about use of implicit function declarations;
+ 1 means warning; 2 means error. */
-int warn_implicit;
+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 +534,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,13 +554,21 @@ 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 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 `$' 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);
@@ -561,24 +582,29 @@ c_decode_option (p)
{
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 +652,25 @@ 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, "-Wwrite-strings"))
warn_write_strings = 1;
else if (!strcmp (p, "-Wno-write-strings"))
@@ -703,6 +743,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 +755,14 @@ 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, "-Wall"))
{
/* We save the value of warn_uninitialized, since if they put
@@ -718,7 +770,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,6 +779,9 @@ 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;
}
else
return 0;
@@ -772,13 +828,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 +949,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 +1055,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 +1118,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 +1376,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 +1388,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
@@ -1404,8 +1489,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 +1507,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 +1758,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 +1777,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 +1795,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 +1833,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 +1883,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 +1899,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 +1912,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,33 +1927,50 @@ 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);
-
- 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);
+ 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 for this declaration. */
+ TREE_ASM_WRITTEN (newdecl) = 1;
+ return 0;
}
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
@@ -1900,15 +2021,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 +2049,28 @@ 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));
+ }
+
+ if (t != 0 && duplicate_decls (x, t, different_binding_level))
{
if (TREE_CODE (t) == PARM_DECL)
{
@@ -1934,32 +2079,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
@@ -2015,7 +2135,7 @@ pushdecl (x)
else if (TREE_TYPE (x) != error_mark_node)
{
tree tt = TREE_TYPE (x);
-
+ DECL_ORIGINAL_TYPE (x) = tt;
tt = build_type_copy (tt);
TYPE_NAME (tt) = x;
TREE_TYPE (x) = tt;
@@ -2145,6 +2265,10 @@ 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));
@@ -2217,11 +2341,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 +2487,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 +2861,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 +2874,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,6 +2923,14 @@ 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',
@@ -2835,18 +2950,12 @@ init_decl_processing ()
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;
+ TREE_TYPE (TYPE_SIZE (short_integer_type_node)) = sizetype;
+ TREE_TYPE (TYPE_SIZE (short_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"),
@@ -3074,6 +3183,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 +3213,42 @@ 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", 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 +3340,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, NULL_PTR);
builtin_function ("__builtin_strcmp", int_ftype_string_string,
BUILT_IN_STRCMP, "strcmp");
builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
@@ -3206,6 +3366,19 @@ 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);
/* In an ANSI C program, it is okay to supply built-in meanings
for these functions, since applications cannot validly use them
@@ -3222,6 +3395,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,
@@ -3467,6 +3641,9 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
/* The corresponding pop_obstacks is in finish_decl. */
push_obstacks_nochange ();
+ if (warn_main && !strcmp (IDENTIFIER_POINTER (declarator), "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 +3728,13 @@ 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;
/* Set attributes here so if duplicate decl, will have proper attributes. */
decl_attributes (decl, attributes, prefix_attributes);
@@ -3703,10 +3884,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 +3906,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 +3933,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 ();
}
@@ -3990,12 +4177,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. */
@@ -4201,10 +4382,20 @@ 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))))
+ {
+ /* 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 +4405,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 +4419,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 +4429,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 +4738,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);
@@ -4713,6 +4925,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 +4944,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 +5128,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");
@@ -5248,7 +5474,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 +5577,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 +5591,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 +5626,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 +5681,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 +5793,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,8 +5811,9 @@ 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
}
}
@@ -5675,27 +5922,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 +5929,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 +6031,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 +6090,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);
@@ -6007,7 +6243,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 +6259,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 +6355,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 +7029,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 +7068,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);
diff --git a/gnu/usr.bin/gcc/c-gperf.h b/gnu/usr.bin/gcc/c-gperf.h
index edaaf22e8bf..361b9d971df 100644
--- a/gnu/usr.bin/gcc/c-gperf.h
+++ b/gnu/usr.bin/gcc/c-gperf.h
@@ -1,5 +1,6 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ c-parse.gperf */
+/* Command-line: gperf -p -j1 -i 1 -g -o -t -G -N is_reserved_word -k1,3,$ ./c-parse.gperf */
+/* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
struct resword { char *name; short token; enum rid rid; };
#define TOTAL_KEYWORDS 79
@@ -10,7 +11,7 @@ struct resword { char *name; short token; enum rid rid; };
/* maximum key range = 135, duplicates = 0 */
#ifdef __GNUC__
-__inline
+inline
#endif
static unsigned int
hash (str, len)
@@ -43,125 +44,126 @@ hash (str, len)
case 2:
case 1:
hval += asso_values[str[0]];
+ break;
}
return hval + asso_values[str[len - 1]];
}
static struct resword wordlist[] =
{
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",},
- {"int", TYPESPEC, RID_INT},
- {"",}, {"",},
- {"__typeof__", TYPEOF, NORID},
- {"__signed__", TYPESPEC, RID_SIGNED},
- {"__imag__", IMAGPART, NORID},
- {"switch", SWITCH, NORID},
- {"__inline__", SCSPEC, RID_INLINE},
- {"else", ELSE, NORID},
- {"__iterator__", SCSPEC, RID_ITERATOR},
- {"__inline", SCSPEC, RID_INLINE},
- {"__extension__", EXTENSION, NORID},
- {"struct", STRUCT, NORID},
- {"__real__", REALPART, NORID},
- {"__const", TYPE_QUAL, RID_CONST},
- {"while", WHILE, NORID},
- {"__const__", TYPE_QUAL, RID_CONST},
- {"case", CASE, NORID},
- {"__complex__", TYPESPEC, RID_COMPLEX},
- {"__iterator", SCSPEC, RID_ITERATOR},
- {"bycopy", TYPE_QUAL, RID_BYCOPY},
- {"",}, {"",}, {"",},
- {"__complex", TYPESPEC, RID_COMPLEX},
- {"",},
- {"in", TYPE_QUAL, RID_IN},
- {"break", BREAK, NORID},
- {"@defs", DEFS, NORID},
- {"",}, {"",}, {"",},
- {"extern", SCSPEC, RID_EXTERN},
- {"if", IF, NORID},
- {"typeof", TYPEOF, NORID},
- {"typedef", SCSPEC, RID_TYPEDEF},
- {"__typeof", TYPEOF, NORID},
- {"sizeof", SIZEOF, NORID},
- {"",},
- {"return", RETURN, NORID},
- {"const", TYPE_QUAL, RID_CONST},
- {"__volatile__", TYPE_QUAL, RID_VOLATILE},
- {"@private", PRIVATE, NORID},
- {"@selector", SELECTOR, NORID},
- {"__volatile", TYPE_QUAL, RID_VOLATILE},
- {"__asm__", ASM_KEYWORD, NORID},
- {"",}, {"",},
- {"continue", CONTINUE, NORID},
- {"__alignof__", ALIGNOF, NORID},
- {"__imag", IMAGPART, NORID},
- {"__attribute__", ATTRIBUTE, NORID},
- {"",}, {"",},
- {"__attribute", ATTRIBUTE, NORID},
- {"for", FOR, NORID},
- {"",},
- {"@encode", ENCODE, NORID},
- {"id", OBJECTNAME, RID_ID},
- {"static", SCSPEC, RID_STATIC},
- {"@interface", INTERFACE, NORID},
- {"",},
- {"__signed", TYPESPEC, RID_SIGNED},
- {"",},
- {"__label__", LABEL, NORID},
- {"",}, {"",},
- {"__asm", ASM_KEYWORD, NORID},
- {"char", TYPESPEC, RID_CHAR},
- {"",},
- {"inline", SCSPEC, RID_INLINE},
- {"out", TYPE_QUAL, RID_OUT},
- {"register", SCSPEC, RID_REGISTER},
- {"__real", REALPART, NORID},
- {"short", TYPESPEC, RID_SHORT},
- {"",},
- {"enum", ENUM, NORID},
- {"inout", TYPE_QUAL, RID_INOUT},
- {"",},
- {"oneway", TYPE_QUAL, RID_ONEWAY},
- {"union", UNION, NORID},
- {"",},
- {"__alignof", ALIGNOF, NORID},
- {"",},
- {"@implementation", IMPLEMENTATION, NORID},
- {"",},
- {"@class", CLASS, NORID},
- {"",},
- {"@public", PUBLIC, NORID},
- {"asm", ASM_KEYWORD, NORID},
- {"",}, {"",}, {"",}, {"",}, {"",},
- {"default", DEFAULT, NORID},
- {"",},
- {"void", TYPESPEC, RID_VOID},
- {"",},
- {"@protected", PROTECTED, NORID},
- {"@protocol", PROTOCOL, NORID},
- {"",}, {"",}, {"",},
- {"volatile", TYPE_QUAL, RID_VOLATILE},
- {"",}, {"",},
- {"signed", TYPESPEC, RID_SIGNED},
- {"float", TYPESPEC, RID_FLOAT},
- {"@end", END, NORID},
- {"",}, {"",},
- {"unsigned", TYPESPEC, RID_UNSIGNED},
- {"@compatibility_alias", ALIAS, NORID},
- {"double", TYPESPEC, RID_DOUBLE},
- {"",}, {"",},
- {"auto", SCSPEC, RID_AUTO},
- {"",},
- {"goto", GOTO, NORID},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"do", DO, NORID},
- {"",}, {"",}, {"",}, {"",},
- {"long", TYPESPEC, RID_LONG},
+ {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"",},
+ {"int", TYPESPEC, RID_INT},
+ {"",}, {"",},
+ {"__typeof__", TYPEOF, NORID},
+ {"__signed__", TYPESPEC, RID_SIGNED},
+ {"__imag__", IMAGPART, NORID},
+ {"switch", SWITCH, NORID},
+ {"__inline__", SCSPEC, RID_INLINE},
+ {"else", ELSE, NORID},
+ {"__iterator__", SCSPEC, RID_ITERATOR},
+ {"__inline", SCSPEC, RID_INLINE},
+ {"__extension__", EXTENSION, NORID},
+ {"struct", STRUCT, NORID},
+ {"__real__", REALPART, NORID},
+ {"__const", TYPE_QUAL, RID_CONST},
+ {"while", WHILE, NORID},
+ {"__const__", TYPE_QUAL, RID_CONST},
+ {"case", CASE, NORID},
+ {"__complex__", TYPESPEC, RID_COMPLEX},
+ {"__iterator", SCSPEC, RID_ITERATOR},
+ {"bycopy", TYPE_QUAL, RID_BYCOPY},
+ {"",}, {"",}, {"",},
+ {"__complex", TYPESPEC, RID_COMPLEX},
+ {"",},
+ {"in", TYPE_QUAL, RID_IN},
+ {"break", BREAK, NORID},
+ {"@defs", DEFS, NORID},
+ {"",}, {"",}, {"",},
+ {"extern", SCSPEC, RID_EXTERN},
+ {"if", IF, NORID},
+ {"typeof", TYPEOF, NORID},
+ {"typedef", SCSPEC, RID_TYPEDEF},
+ {"__typeof", TYPEOF, NORID},
+ {"sizeof", SIZEOF, NORID},
+ {"",},
+ {"return", RETURN, NORID},
+ {"const", TYPE_QUAL, RID_CONST},
+ {"__volatile__", TYPE_QUAL, RID_VOLATILE},
+ {"@private", PRIVATE, NORID},
+ {"@selector", SELECTOR, NORID},
+ {"__volatile", TYPE_QUAL, RID_VOLATILE},
+ {"__asm__", ASM_KEYWORD, NORID},
+ {"",}, {"",},
+ {"continue", CONTINUE, NORID},
+ {"__alignof__", ALIGNOF, NORID},
+ {"__imag", IMAGPART, NORID},
+ {"__attribute__", ATTRIBUTE, NORID},
+ {"",}, {"",},
+ {"__attribute", ATTRIBUTE, NORID},
+ {"for", FOR, NORID},
+ {"",},
+ {"@encode", ENCODE, NORID},
+ {"id", OBJECTNAME, RID_ID},
+ {"static", SCSPEC, RID_STATIC},
+ {"@interface", INTERFACE, NORID},
+ {"",},
+ {"__signed", TYPESPEC, RID_SIGNED},
+ {"",},
+ {"__label__", LABEL, NORID},
+ {"",}, {"",},
+ {"__asm", ASM_KEYWORD, NORID},
+ {"char", TYPESPEC, RID_CHAR},
+ {"",},
+ {"inline", SCSPEC, RID_INLINE},
+ {"out", TYPE_QUAL, RID_OUT},
+ {"register", SCSPEC, RID_REGISTER},
+ {"__real", REALPART, NORID},
+ {"short", TYPESPEC, RID_SHORT},
+ {"",},
+ {"enum", ENUM, NORID},
+ {"inout", TYPE_QUAL, RID_INOUT},
+ {"",},
+ {"oneway", TYPE_QUAL, RID_ONEWAY},
+ {"union", UNION, NORID},
+ {"",},
+ {"__alignof", ALIGNOF, NORID},
+ {"",},
+ {"@implementation", IMPLEMENTATION, NORID},
+ {"",},
+ {"@class", CLASS, NORID},
+ {"",},
+ {"@public", PUBLIC, NORID},
+ {"asm", ASM_KEYWORD, NORID},
+ {"",}, {"",}, {"",}, {"",}, {"",},
+ {"default", DEFAULT, NORID},
+ {"",},
+ {"void", TYPESPEC, RID_VOID},
+ {"",},
+ {"@protected", PROTECTED, NORID},
+ {"@protocol", PROTOCOL, NORID},
+ {"",}, {"",}, {"",},
+ {"volatile", TYPE_QUAL, RID_VOLATILE},
+ {"",}, {"",},
+ {"signed", TYPESPEC, RID_SIGNED},
+ {"float", TYPESPEC, RID_FLOAT},
+ {"@end", END, NORID},
+ {"",}, {"",},
+ {"unsigned", TYPESPEC, RID_UNSIGNED},
+ {"@compatibility_alias", ALIAS, NORID},
+ {"double", TYPESPEC, RID_DOUBLE},
+ {"",}, {"",},
+ {"auto", SCSPEC, RID_AUTO},
+ {"",},
+ {"goto", GOTO, NORID},
+ {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"do", DO, NORID},
+ {"",}, {"",}, {"",}, {"",},
+ {"long", TYPESPEC, RID_LONG},
};
#ifdef __GNUC__
-__inline
+inline
#endif
struct resword *
is_reserved_word (str, len)
diff --git a/gnu/usr.bin/gcc/c-iterate.c b/gnu/usr.bin/gcc/c-iterate.c
index b35a167a46c..2176ab4d3e3 100644
--- a/gnu/usr.bin/gcc/c-iterate.c
+++ b/gnu/usr.bin/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.
@@ -30,20 +30,6 @@ Boston, MA 02111-1307, USA. */
#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;
/*
KEEPING TRACK OF EXPANSIONS
@@ -96,11 +82,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 +255,8 @@ collect_iterators (exp, list)
break;
case RTL_EXPR:
return list;
+ default:
+ break;
}
for (i = 0; i < num_args; i++)
@@ -343,7 +346,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 +414,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 +447,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 +476,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 +582,7 @@ pixl (head)
return head;
}
-/* Print Iterator Stack*/
+/* Print Iterator Stack. */
void
pis ()
diff --git a/gnu/usr.bin/gcc/c-lang.c b/gnu/usr.bin/gcc/c-lang.c
index ef9f184880d..b5ed3deb652 100644
--- a/gnu/usr.bin/gcc/c-lang.c
+++ b/gnu/usr.bin/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 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -37,10 +37,12 @@ lang_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
@@ -129,12 +131,12 @@ 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 ();
extern tree build_function_call PROTO((tree, tree));
tree void_list_node = build_tree_list (NULL_TREE, void_type_node);
#ifndef ASM_OUTPUT_CONSTRUCTOR
diff --git a/gnu/usr.bin/gcc/c-lex.c b/gnu/usr.bin/gcc/c-lex.c
index 007b3634384..77d40a40573 100644
--- a/gnu/usr.bin/gcc/c-lex.c
+++ b/gnu/usr.bin/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-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,12 +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. */
+#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <setjmp.h>
-#include "config.h"
#include "rtl.h"
#include "tree.h"
#include "input.h"
@@ -35,6 +35,13 @@ Boston, MA 02111-1307, USA. */
#include <ctype.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 <stdlib.h>
#include <locale.h>
@@ -44,6 +51,13 @@ Boston, MA 02111-1307, USA. */
extern int errno;
#endif
+#if USE_CPPLIB
+#include "cpplib.h"
+cpp_reader parse_in;
+cpp_options parse_options;
+static enum cpp_token cpp_token;
+#endif
+
/* The elements of `ridpointers' are identifier nodes
for the reserved type names and storage classes.
It is indexed by a RID_... value. */
@@ -52,6 +66,32 @@ tree ridpointers[(int) RID_MAX];
/* Cause the `yydebug' variable to be defined. */
#define YYDEBUG 1
+#if USE_CPPLIB
+static unsigned char *yy_cur, *yy_lim;
+
+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++;
+ }
+}
+
+#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
@@ -85,12 +125,19 @@ 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
+static int skip_which_space PROTO((int));
+static char *extend_token_buffer PROTO((char *));
+static int readescape PROTO((int *));
int check_newline ();
/* Do not insert generated code into the source, instead, include it.
@@ -142,6 +189,31 @@ remember_protocol_qualifiers ()
wordlist[i].name = "oneway";
}
+#if USE_CPPLIB
+void
+init_parse (filename)
+ char *filename;
+{
+ init_lex ();
+ yy_cur = "\n";
+ yy_lim = yy_cur+1;
+
+ cpp_reader_init (&parse_in);
+ parse_in.data = &parse_options;
+ cpp_options_init (&parse_options);
+ cpp_handle_options (&parse_in, 0, NULL); /* FIXME */
+ parse_in.show_column = 1;
+ if (! cpp_start_read (&parse_in, filename))
+ abort ();
+}
+
+void
+finish_parse ()
+{
+ cpp_finish (&parse_in);
+}
+#endif
+
void
init_lex ()
{
@@ -261,7 +333,6 @@ yyprint (file, yychar, yylval)
break;
}
}
-
/* If C is not whitespace, return C.
Otherwise skip whitespace and return first nonwhite char read. */
@@ -289,7 +360,7 @@ skip_white_space (c)
case '\f':
case '\v':
case '\b':
- c = getc (finput);
+ c = GETC();
break;
case '\r':
@@ -301,16 +372,16 @@ skip_white_space (c)
warning ("(we only warn about the first carriage return)");
newline_warning = 1;
}
- c = getc (finput);
+ 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 +398,14 @@ 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));
}
/* Make the token buffer longer, preserving the data in it.
@@ -352,6 +425,88 @@ extend_token_buffer (p)
return token_buffer + offset;
}
+#if !USE_CPPLIB
+#define GET_DIRECTIVE_LINE() get_directive_line (finput)
+#else /* 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.
+ 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. */
+
+static 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);
+ }
+}
+#endif /* USE_CPPLIB */
+
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
@@ -367,9 +522,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 +534,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,72 +546,86 @@ 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'))
{
+ while (c == ' ' || c == '\t')
+ 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 (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. */
@@ -464,13 +633,13 @@ check_newline ()
A string constant should follow. */
while (c == ' ' || c == '\t')
- c = getc (finput);
+ c = GETC();
/* 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)
@@ -500,7 +669,7 @@ linenum:
In either case, it should be a line number; a digit should follow. */
while (c == ' ' || c == '\t')
- c = getc (finput);
+ c = GETC();
/* If the # is the only nonwhite char on the line,
just ignore it. Check the new newline. */
@@ -509,7 +678,7 @@ linenum:
/* Something follows the #; read a token. */
- ungetc (c, finput);
+ UNGETC (c);
token = yylex ();
if (token == CONSTANT
@@ -523,16 +692,16 @@ linenum:
int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
/* Is this the last nonwhite stuff on the line? */
- c = getc (finput);
+ c = GETC();
while (c == ' ' || c == '\t')
- c = getc (finput);
+ c = GETC();
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 +727,9 @@ linenum:
main_input_filename = input_filename;
/* Is this the last nonwhite stuff on the line? */
- c = getc (finput);
+ c = GETC();
while (c == ' ' || c == '\t')
- c = getc (finput);
+ c = GETC();
if (c == '\n')
{
/* Update the name in the top element of input_file_stack. */
@@ -569,7 +738,7 @@ linenum:
return c;
}
- ungetc (c, finput);
+ UNGETC (c);
token = yylex ();
used_up = 0;
@@ -588,14 +757,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 +769,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 +799,12 @@ linenum:
if (used_up)
{
/* Is this the last nonwhite stuff on the line? */
- c = getc (finput);
+ c = GETC();
while (c == ' ' || c == '\t')
- c = getc (finput);
+ c = GETC();
if (c == '\n')
return c;
- ungetc (c, finput);
+ UNGETC (c);
token = yylex ();
used_up = 0;
@@ -651,12 +820,12 @@ linenum:
if (used_up)
{
/* Is this the last nonwhite stuff on the line? */
- c = getc (finput);
+ c = GETC();
while (c == ' ' || c == '\t')
- c = getc (finput);
+ c = GETC();
if (c == '\n')
return c;
- ungetc (c, finput);
+ UNGETC (c);
}
warning ("unrecognized text at end of #line");
@@ -666,37 +835,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;
+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 +872,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 +902,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 +922,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 +964,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 +1090,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 +1107,7 @@ yylex ()
case '\f':
case '\v':
case '\b':
- c = getc (finput);
+ c = GETC();
break;
case '\r':
@@ -956,15 +1135,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 +1149,7 @@ yylex ()
wide_flag = 1;
goto string_constant;
}
- ungetc (c, finput);
+ UNGETC (c);
}
goto letter;
@@ -988,13 +1162,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,6 +1185,7 @@ 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 == '@')
@@ -1018,18 +1193,27 @@ yylex ()
/* 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;
@@ -1109,7 +1293,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 +1338,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')
@@ -1181,7 +1381,7 @@ 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
@@ -1190,7 +1390,7 @@ yylex ()
{
if (c == '.')
{
- c = getc (finput);
+ c = GETC();
if (c == '.')
{
*p++ = c;
@@ -1199,7 +1399,7 @@ yylex ()
}
error ("parse error at `..'");
}
- ungetc (c, finput);
+ UNGETC (c);
token_buffer[1] = 0;
value = '.';
goto done;
@@ -1258,7 +1458,7 @@ yylex ()
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
- *p++ = (c = getc (finput));
+ *p++ = (c = GETC());
}
}
@@ -1274,7 +1474,7 @@ yylex ()
if (floatflag != NOT_FLOAT)
{
tree type = double_type_node;
- int garbage_chars = 0, exceeds_double = 0;
+ int exceeds_double = 0;
int imag = 0;
REAL_VALUE_TYPE value;
jmp_buf handler;
@@ -1286,11 +1486,11 @@ 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))
error ("floating constant exponent has no digits");
@@ -1299,7 +1499,7 @@ yylex ()
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
*p++ = c;
- c = getc (finput);
+ c = GETC();
}
}
@@ -1361,7 +1561,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
@@ -1410,19 +1610,6 @@ yylex ()
}
}
#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 +1619,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
{
@@ -1479,46 +1664,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 +1746,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 +1772,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 +1785,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 +1803,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 +1840,7 @@ yylex ()
{
tryagain:
- c = getc (finput);
+ c = GETC();
if (c == '\'' || c == EOF)
break;
@@ -1781,7 +1950,7 @@ yylex ()
case '"':
string_constant:
{
- c = getc (finput);
+ c = GETC();
p = token_buffer + 1;
while (c != '"' && c >= 0)
@@ -1809,7 +1978,7 @@ yylex ()
*p++ = c;
skipnewline:
- c = getc (finput);
+ c = GETC();
}
*p = 0;
@@ -1836,15 +2005,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;
@@ -1923,7 +2086,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 +2135,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 +2158,16 @@ yylex ()
value = 1;
break;
+ case '{':
+ indent_level++;
+ value = c;
+ break;
+
+ case '}':
+ indent_level--;
+ value = c;
+ break;
+
default:
value = c;
}
diff --git a/gnu/usr.bin/gcc/c-pragma.c b/gnu/usr.bin/gcc/c-pragma.c
index 480cfca8154..83b9802075f 100644
--- a/gnu/usr.bin/gcc/c-pragma.c
+++ b/gnu/usr.bin/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,9 +18,10 @@ 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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "tree.h"
+#include "except.h"
#include "function.h"
#include "defaults.h"
#include "c-pragma.h"
@@ -29,7 +30,7 @@ Boston, MA 02111-1307, USA. */
/* 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 +65,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;
diff --git a/gnu/usr.bin/gcc/c-tree.h b/gnu/usr.bin/gcc/c-tree.h
index 02f57c3b9dc..3e0e10a401f 100644
--- a/gnu/usr.bin/gcc/c-tree.h
+++ b/gnu/usr.bin/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. */
@@ -174,7 +177,7 @@ 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 *));
+extern char *get_directive_line PROTO((FILE *));
/* 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. */
@@ -285,12 +288,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));
@@ -382,6 +382,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 +400,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 +467,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,6 +487,10 @@ extern int warn_parentheses;
extern int warn_missing_braces;
+/* Warn about comparison of signed and unsigned values. */
+
+extern int warn_sign_compare;
+
/* Nonzero means this is a function to call to perform comptypes
on two record types. */
diff --git a/gnu/usr.bin/gcc/caller-save.c b/gnu/usr.bin/gcc/caller-save.c
index 6dc90189ee6..a6d45ac4c11 100644
--- a/gnu/usr.bin/gcc/caller-save.c
+++ b/gnu/usr.bin/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, 1994, 1995, 1997 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 <stdio.h>
#include "rtl.h"
#include "insn-config.h"
#include "flags.h"
@@ -182,7 +183,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 +263,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 +309,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,7 +317,7 @@ 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.
@@ -334,7 +336,7 @@ setup_save_areas (pchanged)
for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
if (regno_save_mem[i][j] != 0)
ok &= strict_memory_address_p (GET_MODE (regno_save_mem[i][j]),
- XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX), 0));
+ XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX, 1), 0));
return ok;
}
@@ -356,8 +358,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 +367,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
diff --git a/gnu/usr.bin/gcc/cccp.1 b/gnu/usr.bin/gcc/cccp.1
index 8664c61f7be..84eb19ede54 100644
--- a/gnu/usr.bin/gcc/cccp.1
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/cccp.c b/gnu/usr.bin/gcc/cccp.c
index 39f1a5ae7c8..368298b90cb 100644
--- a/gnu/usr.bin/gcc/cccp.c
+++ b/gnu/usr.bin/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-96, 1997 Free Software Foundation, Inc.
Written by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -16,100 +16,27 @@ 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
-#else
-#define PTR_INT_TYPE long
-#endif
-#endif /* 0 */
-
-#include "pcp.h"
-
-/* By default, colon separates directories in a path. */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
-#endif
-
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>
#include <signal.h>
-/* 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
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
# include <time.h>
#else
-# if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
# else
-# if HAVE_SYS_TIME_H
-# include <sys/time.h>
-# else
-# include <time.h>
-# endif
-# endif
+# include <time.h>
+#endif
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
#endif
@@ -117,100 +44,75 @@ typedef unsigned char U_CHAR;
# include <fcntl.h>
#endif
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
#include <errno.h>
#if HAVE_STDLIB_H
# include <stdlib.h>
-#else
-char *getenv ();
#endif
-#if STDC_HEADERS
+#ifdef HAVE_STRING_H
# include <string.h>
-# 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))
+#else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#endif
-# 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;
+typedef unsigned char U_CHAR;
- return 0;
-}
-# endif /* !defined (bcmp) */
+#include "gansidecl.h"
+#include "pcp.h"
-# 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) */
+#ifdef NEED_DECLARATION_INDEX
+extern char *index ();
+#endif
-# 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) */
+#ifdef NEED_DECLARATION_RINDEX
+extern char *rindex ();
+#endif
-# endif /* !defined (BSTRING) && (defined (USG) || defined (VMS)) */
-#endif /* ! STDC_HEADERS */
+#ifdef NEED_DECLARATION_GETENV
+extern char *getenv ();
+#endif
-#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6)
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
# define __attribute__(x)
#endif
-#ifndef PROTO
-# if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-# define PROTO(ARGS) ARGS
-# else
-# define PROTO(ARGS) ()
-# endif
+#ifndef STANDARD_INCLUDE_DIR
+# define STANDARD_INCLUDE_DIR "/usr/include"
+#endif
+
+/* By default, colon separates directories in a path. */
+#ifndef PATH_SEPARATOR
+# define PATH_SEPARATOR ':'
+#endif
+
+/* By default, the suffix for object files is ".o". */
+#ifdef OBJECT_SUFFIX
+# define HAVE_OBJECT_SUFFIX
+#else
+# define OBJECT_SUFFIX ".o"
#endif
#if defined (__STDC__) && defined (HAVE_VPRINTF)
# include <stdarg.h>
-# 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)))
+# define PRINTF_PROTO(ARGS, m, n) PROTO (ARGS) __attribute__ ((format (__printf__, m, n)))
#else
# include <varargs.h>
-# 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 PRINTF_PROTO(ARGS, m, n) () __attribute__ ((format (__printf__, m, n)))
# define vfprintf(file, msg, args) \
{ \
char *a0 = va_arg(args, char *); \
@@ -225,38 +127,28 @@ my_bzero (b, length)
#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 <unistd.h>
-#endif
-
/* VMS-specific definitions */
#ifdef VMS
#include <descrip.h>
-#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)
#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 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__ */
+#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 */
+/* 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
+
#ifndef O_RDONLY
#define O_RDONLY 0
#endif
@@ -266,18 +158,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 <inttypes.h>
+# define HOST_WIDE_INT intmax_t
+# else
+# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
+# define HOST_WIDE_INT int
+# else
+# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
+# define HOST_WIDE_INT long
+# else
+# define HOST_WIDE_INT long long
+# endif
+# endif
+# endif
#endif
#ifndef S_ISREG
@@ -288,22 +186,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,22 +201,19 @@ typedef struct { unsigned :16, :16, :16; } vms_ino_t;
/* External declarations. */
extern char *version_string;
+extern char *update_path PROTO((char *, char *));
#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 *));
+HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
+HOST_WIDE_INT parse_c_expression PROTO((char *, int));
#ifndef errno
extern int errno;
@@ -414,6 +299,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 +318,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 +338,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 +352,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 +368,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 +406,8 @@ static struct file_buf {
char *fname;
/* Filename specified with #line directive. */
char *nominal_fname;
+ /* 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 +424,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 <FILENAME>. */
+ /* True if this is a system header file; see is_system_include. */
char system_header_p;
} instack[INPUT_STACK_MAX];
@@ -546,7 +449,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 +464,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 <file> 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 <file> just looks in the stack. */
+/* -I directories are added to the end, then the defaults are added. */
/* The */
static struct default_include {
char *fname; /* The name of the directory. */
+ char *component; /* The component containing the directory */
int cplusplus; /* Only look here if we're compiling C++. */
int cxx_aware; /* Includes in this directory don't need to
be wrapped in extern "C" when compiling
@@ -590,33 +496,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
+#ifndef STANDARD_INCLUDE_COMPONENT
+#define STANDARD_INCLUDE_COMPONENT 0
#endif
- { STANDARD_INCLUDE_DIR, 0, 0 },
+ { 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 +559,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 +633,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 {
@@ -736,7 +667,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 +694,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 +743,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 +757,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 +831,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 +846,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 +863,11 @@ 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) (T_INCLUDE <= (t) && (t) <= 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 +894,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 +902,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 +922,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 +941,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). */
@@ -1081,22 +999,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 void finclude PROTO((int, char *, FILE_BUF *, int, struct file_name_list *));
-static void record_control_macro PROTO((char *, U_CHAR *));
+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 int import_hash PROTO((char *));
-static int lookup_import PROTO((char *, struct file_name_list *));
-static void add_import PROTO((int, 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 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,7 +1043,7 @@ 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 *));
@@ -1185,8 +1102,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 +1119,10 @@ 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 *));
/* 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 +1132,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 +1159,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 +1168,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
@@ -1262,8 +1195,7 @@ 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 +1230,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 +1268,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;
@@ -1383,13 +1302,13 @@ main (argc, argv)
if (i + 1 == argc)
fatal ("Filename missing after `-include' option");
else
- pend_includes[i] = argv[i+1], i++;
+ simplify_filename (pend_includes[i] = argv[++i]);
}
if (!strcmp (argv[i], "-imacros")) {
if (i + 1 == argc)
fatal ("Filename missing after `-imacros' option");
else
- pend_files[i] = argv[i+1], i++;
+ simplify_filename (pend_files[i] = argv[++i]);
}
if (!strcmp (argv[i], "-iprefix")) {
if (i + 1 == argc)
@@ -1403,17 +1322,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 +1348,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 +1373,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 +1413,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 +1427,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 +1434,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 +1474,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 +1552,9 @@ main (argc, argv)
case 'D':
dump_macros = dump_definitions;
break;
+ case 'I':
+ dump_includes = 1;
+ break;
}
}
}
@@ -1746,7 +1635,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 +1648,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 +1667,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. */
@@ -1819,9 +1703,6 @@ main (argc, argv)
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);
@@ -1938,8 +1819,8 @@ 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)
{
@@ -1959,7 +1840,6 @@ main (argc, argv)
/* 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 +1853,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 +1900,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 +1916,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 +1939,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 +2011,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 +2043,47 @@ 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->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 +2091,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 +2108,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 +2148,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 +2221,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 +2276,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 +2327,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 +2341,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 +2422,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 +2431,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;
@@ -2773,7 +2626,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,7 +2753,10 @@ 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)
+ /* Handle any pending identifier;
+ but the L in L'...' or L"..." is not an identifier. */
+ if (ident_length
+ && ! (ident_length == 1 && hash == HASHSTEP (0, 'L')))
goto specialchar;
start_line = ip->lineno;
@@ -2942,12 +2798,12 @@ 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 '\\':
@@ -2993,10 +2849,10 @@ do { ip = &instack[indepth]; \
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 +2868,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 +2887,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 +2938,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 +2957,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':
@@ -3143,16 +3006,17 @@ 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') {
+ if it follows an `e' or `p'. */
+ if (c == 'e' || c == 'E' || c == 'p' || c == 'P') {
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 +3115,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--;
@@ -3493,9 +3358,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. */
@@ -3615,6 +3480,7 @@ expand_to_temp_buffer (buf, limit, output_marks, assertions)
ip = &instack[indepth];
ip->fname = 0;
ip->nominal_fname = 0;
+ ip->inc = 0;
ip->system_header_p = 0;
ip->macro = 0;
ip->free_ptr = 0;
@@ -3773,7 +3639,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)))
@@ -3818,7 +3684,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 +3707,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 +3743,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 +3797,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++;
@@ -3998,13 +3872,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 ? dump_names <= dump_macros
+ : IS_INCLUDE_DIRECTIVE_TYPE (kt->type) ? dump_includes
+ : kt->type == T_PRAGMA)) {
int len;
/* Output directive name. */
@@ -4013,13 +3886,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 +3896,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 +3928,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;
@@ -4164,6 +4037,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 +4077,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 +4135,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,21 +4189,19 @@ 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++;
@@ -4326,48 +4217,35 @@ 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;
- }
-#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';
+ dsp = ((struct file_name_list *)
+ alloca (sizeof (struct file_name_list) + strlen (nam)));
+ strcpy (dsp->fname, nam);
+ simplify_filename (dsp->fname);
+ nam = base_name (dsp->fname);
+ *nam = 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 +4255,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,15 +4273,15 @@ 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++;
+ if (retried && isalpha(*(U_CHAR *) (--fbeg))) {
+ while (fin != limit && (!isspace(*fin)))
+ *fend++ = *fin++;
warning ("VAX-C-style include specification found, use '#include <filename.h>' !");
- 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;
}
}
@@ -4463,7 +4340,8 @@ get_filename:
}
}
- flen = fend - fbeg;
+ *fend = 0;
+ flen = simplify_filename (fbeg);
if (flen == 0)
{
@@ -4473,121 +4351,117 @@ 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);
+
+ strcpy (fname, searchptr->fname);
+ strcat (fname, fbeg);
#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)) {
+ if (searchptr->fname[0]) {
/* Fix up the filename */
- hack_vms_include_specification (fname);
+ hack_vms_include_specification (fname, vaxc_include);
} else {
- /* This is a normal VMS filespec, so use it unchanged. */
- strncpy (fname, fbeg, flen);
- fname[flen] = 0;
+ /* This is a normal VMS filespec, so use it unchanged. */
+ strcpy (fname, fbeg);
/* if it's '#include filename', add the missing .h */
- if (index(fname,'.')==NULL) {
+ if (vaxc_include && index(fname,'.')==NULL) {
strcat (fname, ".h");
}
}
#endif /* VMS */
- /* ??? There are currently 3 separate mechanisms for avoiding processing
- of redundant include files: #import, #pragma once, and
- redundant_include_p. It would be nice if they were unified. */
- if (redundant_include_p (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)
+ 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 +4469,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. */
+ error ("No include path in which to find %s", fbeg);
- struct file_name_list* ptr;
-
- 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 +4486,6 @@ get_filename:
if (!no_precomp)
{
- struct stat stat_f;
-
- fstat (f, &stat_f);
-
do {
sprintf (pcftry, "%s%d", fname, pcfnum++);
@@ -4665,12 +4494,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 +4521,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 +4548,121 @@ 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
+ 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 (;;) {
+ if (from[0] == '.' && from[1] == '/')
+ from += 2;
+ else {
+ /* 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 +4714,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 +4735,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 +4747,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 +4761,7 @@ read_name_map (dirname)
{
char *from, *to;
struct file_name_map *ptr;
+ size_t tolen;
if (is_space[ch])
continue;
@@ -4877,19 +4770,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 +4805,153 @@ 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;
+ 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 (!inc
+ || ! inc->control_macro
+ || (inc->control_macro[0] && ! lookup (inc->control_macro, -1, -1))) {
+
+ fd = open (fname, O_RDONLY, 0);
+
+ if (fd < 0)
+ 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 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;
- char *p, *dir;
- if (searchptr && ! searchptr->got_name_map)
+ if (searchptr)
{
- searchptr->name_map = read_name_map (searchptr->fname
- ? searchptr->fname : ".");
- searchptr->got_name_map = 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 (! searchptr->got_name_map)
{
- if (! strcmp (map->map_from, from))
- {
- /* Found a match. */
- return open (map->map_to, O_RDONLY, 0666);
- }
+ searchptr->name_map = read_name_map (searchptr->fname);
+ searchptr->got_name_map = 1;
}
- }
- /* Try to find a mapping file for the particular directory we are
- looking in. Thus #include <sys/types.h> will look up sys/types.h
- in /usr/include/header.gcc and look up types.h in
- /usr/include/sys/header.gcc. */
- p = rindex (filename, '/');
-#ifdef DIR_SEPARATOR
- if (! p) p = rindex (filename, DIR_SEPARATOR);
- else {
- char *tmp = rindex (filename, DIR_SEPARATOR);
- if (tmp != NULL && tmp > p) p = tmp;
- }
-#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);
+ /* 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;
}
- if (p == filename)
+ from = base_name (filename);
+
+ if (from != filename || !searchptr)
{
- dir = ".";
- from = filename;
+ /* Try to find a mapping file for the particular directory we are
+ looking in. Thus #include <sys/types.h> will look up sys/types.h
+ in /usr/include/header.gcc and look up types.h in
+ /usr/include/sys/header.gcc. */
+
+ 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;
}
- else
- {
- dir = (char *) alloca (p - filename + 1);
- bcopy (filename, dir, p - filename);
- dir[p - filename] = '\0';
- from = p + 1;
+
+ 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 +4960,54 @@ 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->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 +5066,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;
+ struct stat *st;
char *fname;
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 +5125,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 +5147,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 +5206,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 +5224,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 +5236,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 +5253,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 +5266,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 +5286,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 +5317,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 +5335,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 +5347,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;
@@ -5565,7 +5423,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 +5434,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;
@@ -5605,7 +5464,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 +5495,8 @@ 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) {
rest_args = 1;
temp->rest_args = 1;
break;
@@ -5669,8 +5528,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 +5539,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 +5568,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,7 +5586,7 @@ 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 *) "";
}
@@ -5831,7 +5690,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 +5699,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 +5712,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 +5810,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 +5918,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;
@@ -6097,9 +5958,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 +5982,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) {
@@ -6244,7 +6109,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'");
@@ -6323,7 +6188,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 +6402,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 +6440,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 +6476,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;
@@ -6693,7 +6556,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--;
@@ -6744,8 +6607,7 @@ 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) {
@@ -6773,11 +6635,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,11 +6675,9 @@ 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)
@@ -6828,7 +6686,7 @@ do_error (buf, limit, op, keyword)
struct directive *keyword;
{
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,11 +6694,9 @@ 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)
@@ -6849,11 +6705,13 @@ do_warning (buf, limit, op, keyword)
struct directive *keyword;
{
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);
+ /* 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,28 +6722,15 @@ 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)
@@ -6901,22 +6746,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;
}
@@ -6941,25 +6781,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 +6809,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 ()
@@ -7007,18 +6847,16 @@ 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)
@@ -7034,10 +6872,8 @@ 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)
@@ -7055,8 +6891,8 @@ 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)
+ if (if_stack->fname != NULL && ip->fname != NULL
+ && strcmp (if_stack->fname, ip->nominal_fname) != 0)
fprintf (stderr, ", file %s", if_stack->fname);
fprintf (stderr, ")\n");
}
@@ -7077,10 +6913,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 +6932,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 +7000,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;
@@ -7232,11 +7069,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;
@@ -7357,23 +7193,33 @@ 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] == '*') {
+ for (bp += 2; ; bp++) {
+ if (*bp == '\n')
+ ip->lineno++;
+ else if (*bp == '*') {
+ if (bp[-1] == '/' && warn_comments)
+ warning ("`/*' within comment");
+ 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;
@@ -7454,7 +7300,7 @@ skip_if_group (ip, any, op)
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);
@@ -7514,12 +7360,10 @@ 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)
@@ -7562,9 +7406,7 @@ do_else (buf, limit, op, keyword)
return 0;
}
-/*
- * unstack after #endif directive
- */
+/* Unstack after #endif directive. */
static int
do_endif (buf, limit, op, keyword)
@@ -7615,7 +7457,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 +7468,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 +7517,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 +7530,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 +7574,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 +7598,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;
@@ -7824,12 +7654,12 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
} 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 +7670,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;
}
@@ -7850,6 +7684,7 @@ skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p,
/* Place into DST a quoted string representing the string SRC.
Return the address of DST's terminating null. */
+
static char *
quote_string (dst, src)
char *dst, *src;
@@ -7934,13 +7769,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,9 +7807,9 @@ 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++;
}
@@ -8096,7 +7929,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);
@@ -8374,8 +8207,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 +8243,7 @@ macroexpand (hp, op)
ip2->fname = 0;
ip2->nominal_fname = 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 +8264,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)
@@ -8605,29 +8437,33 @@ macarg1 (start, limit, depthptr, newlines, comments, rest_args)
case '/':
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 '\'':
@@ -8828,9 +8664,8 @@ 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 *
my_strerror (errnum)
@@ -8861,9 +8696,7 @@ 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))
@@ -9052,7 +8885,7 @@ vwarning_with_line (line, 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))
@@ -9200,6 +9033,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 +9075,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;
@@ -9296,6 +9131,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 +9182,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 +9206,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 +9223,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 +9405,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 +9463,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)
{
@@ -9865,12 +9704,111 @@ 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 (dir->fname[len - 1] != DIR_SEPARATOR) {
+ if (len == 1 && dir->fname[len - 1] == '.')
+ len = 0;
+ else
+ dir->fname[len++] = DIR_SEPARATOR;
+ 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 +9842,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 +9912,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;
@@ -9938,7 +9937,7 @@ deps_output (string, 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 == ':') {
@@ -10052,66 +10051,31 @@ 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. */
-
-static int
-file_size_and_mode (fd, mode_pointer, size_pointer)
- int fd;
- int *mode_pointer;
- long int *size_pointer;
-{
- struct stat sbuf;
-
- 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
-/* 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. */
+/* 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. */
static void
-hack_vms_include_specification (fname)
+hack_vms_include_specification (fname, vaxc_include)
char *fname;
+ int vaxc_include;
{
register char *cp, *cp1, *cp2;
- int f, check_filename_before_returning, no_prefix_seen;
+ int f, check_filename_before_returning;
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 "/" */
- }
+
+ cp = base_name (fname);
/*
* 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");
- }
+ if (vaxc_include && !index (cp,'.'))
+ strcat (cp, ".h");
cp2 = Local; /* initialize */
@@ -10124,7 +10088,7 @@ 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). */
/* See if we found that 1st slash */
if (cp == 0) return; /* Nothing to do!!! */
@@ -10174,14 +10138,14 @@ hack_vms_include_specification (fname)
/* If there are no other slashes then the filename will be
in the "root" directory. Otherwise, we need to add
- directory specifications. */
+ 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. */
+ /* 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] == '/')) {
@@ -10210,7 +10174,7 @@ hack_vms_include_specification (fname)
/* Now add the filename */
while (*cp1) *cp2++ = *cp1++;
*cp2 = 0;
- /* Now append it to the original VMS spec. */
+ /* Now append it to the original VMS spec. */
strcpy (cp, Local);
/* If we put a [000000] in the filename, try to open it first. If this fails,
@@ -10218,7 +10182,7 @@ hack_vms_include_specification (fname)
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) {
+ if (check_filename_before_returning) {
f = open (fname, O_RDONLY, 0666);
if (f >= 0) {
/* The file name is OK as it is, so return it as is. */
@@ -10237,86 +10201,33 @@ hack_vms_include_specification (fname)
#ifdef VMS
-/* 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 */
-
-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);
-}
-
/* The following wrapper functions supply additional arguments to the VMS
I/O routines to optimize performance with file handling. The arguments
are:
"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,34 +10241,14 @@ 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 <fab.h>
@@ -10377,7 +10268,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)
diff --git a/gnu/usr.bin/gcc/cexp.y b/gnu/usr.bin/gcc/cexp.y
index d83de803364..5269c5bae7e 100644
--- a/gnu/usr.bin/gcc/cexp.y
+++ b/gnu/usr.bin/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, 1994, 1995, 1996, 1997 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
@@ -29,8 +29,20 @@ Boston, MA 02111-1307, USA.
#include <setjmp.h>
/* #define YYDEBUG 1 */
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
#ifdef MULTIBYTE_CHARS
-#include <stdlib.h>
#include <locale.h>
#endif
@@ -60,27 +72,87 @@ struct arglist {
#endif
#endif
-/* Find the largest host integer type and set its size and type. */
+#ifndef NULL_PTR
+#define NULL_PTR ((GENERIC_PTR) 0)
+#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 <inttypes.h>
+# define HOST_WIDE_INT intmax_t
+# define unsigned_HOST_WIDE_INT uintmax_t
+# else
+# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
+# define HOST_WIDE_INT int
+# else
+# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
+# define HOST_WIDE_INT long
+# else
+# define HOST_WIDE_INT long long
+# endif
+# endif
+# endif
+#endif
+
+#ifndef unsigned_HOST_WIDE_INT
+#define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT
+#endif
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
#ifndef HOST_BITS_PER_WIDE_INT
+#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
+#endif
-#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
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __attribute__(x)
#endif
+#ifndef PROTO
+# if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
+# define PROTO(ARGS) ARGS
+# else
+# define PROTO(ARGS) ()
+# endif
#endif
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
+#if defined (__STDC__) && defined (HAVE_VPRINTF)
+# include <stdarg.h>
+# 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)))
+#else
+# include <varargs.h>
+# 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
-int yylex ();
-void yyerror ();
-HOST_WIDE_INT expression_value;
+#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
+
+HOST_WIDE_INT parse_c_expression PROTO((char *, int));
+
+static int yylex PROTO((void));
+static void yyerror PROTO((char *)) __attribute__ ((noreturn));
+static HOST_WIDE_INT expression_value;
+#ifdef TEST_EXP_READER
+static int expression_signedp;
+#endif
static jmp_buf parse_return_error;
@@ -91,10 +163,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 +175,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 +210,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 +279,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 +298,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 +345,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 +362,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 +454,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 +501,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 +541,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 +572,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 +616,7 @@ static struct token tokentab2[] = {
/* Read one token, getting characters through lexptr. */
-int
+static int
yylex ()
{
register int c;
@@ -509,6 +624,7 @@ yylex ()
register unsigned char *tokstart;
register struct token *toktab;
int wide_flag;
+ HOST_WIDE_INT mask;
retry:
@@ -529,13 +645,12 @@ yylex ()
}
switch (c) {
- case 0:
+ case '\n':
return 0;
case ' ':
case '\t':
case '\r':
- case '\n':
lexptr++;
goto retry;
@@ -545,18 +660,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 +682,7 @@ yylex ()
while (1) {
c = *lexptr++;
if (c == '\\')
- c = parse_escape (&lexptr);
+ c = parse_escape (&lexptr, mask);
else if (c == '\'')
break;
}
@@ -577,8 +695,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 +724,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 +759,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 +785,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 +793,7 @@ yylex ()
}
/* This is always a signed type. */
- yylval.integer.unsignedp = 0;
+ yylval.integer.signedp = SIGNED;
return CHAR;
@@ -712,6 +830,7 @@ yylex ()
return c;
case '"':
+ mask = MAX_CHAR_TYPE_MASK;
string_constant:
if (keyword_parsing) {
char *start_ptr = lexptr;
@@ -719,7 +838,7 @@ yylex ()
while (1) {
c = *lexptr++;
if (c == '\\')
- c = parse_escape (&lexptr);
+ c = parse_escape (&lexptr, mask);
else if (c == '"')
break;
}
@@ -733,10 +852,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 +869,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 +898,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 +910,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 +952,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 +965,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 +996,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 +1008,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 +1024,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 +1075,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 +1181,79 @@ initialize_random_junk ()
++is_idchar[i];
++is_idchar['_'];
++is_idstart['_'];
-#if DOLLARS_IN_IDENTIFIERS
++is_idchar['$'];
++is_idstart['$'];
-#endif
- /* horizontal space table */
- ++is_hor_space[' '];
- ++is_hor_space['\t'];
+ ++is_space[' '];
+ ++is_space['\t'];
+ ++is_space['\v'];
+ ++is_space['\f'];
+ ++is_space['\n'];
+ ++is_space['\r'];
+}
+
+void
+error (PRINTF_ALIST (msg))
+ PRINTF_DCL (msg)
+{
+ va_list args;
+
+ VA_START (args, msg);
+ fprintf (stderr, "error: ");
+ vfprintf (stderr, msg, args);
+ fprintf (stderr, "\n");
+ va_end (args);
}
-error (msg)
+void
+pedwarn (PRINTF_ALIST (msg))
+ PRINTF_DCL (msg)
+{
+ va_list args;
+
+ VA_START (args, msg);
+ fprintf (stderr, "pedwarn: ");
+ vfprintf (stderr, msg, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+}
+
+void
+warning (PRINTF_ALIST (msg))
+ PRINTF_DCL (msg)
{
- printf ("error: %s\n", msg);
+ va_list args;
+
+ VA_START (args, msg);
+ fprintf (stderr, "warning: ");
+ vfprintf (stderr, msg, args);
+ fprintf (stderr, "\n");
+ va_end (args);
}
-warning (msg)
+int
+check_assertion (name, sym_length, tokens_specified, tokens)
+ U_CHAR *name;
+ int sym_length;
+ int tokens_specified;
+ struct arglist *tokens;
{
- printf ("warning: %s\n", msg);
+ 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/gnu/usr.bin/gcc/conditions.h b/gnu/usr.bin/gcc/conditions.h
index c92226c14ce..80d604790cc 100644
--- a/gnu/usr.bin/gcc/conditions.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/1750a/1750a.c b/gnu/usr.bin/gcc/config/1750a/1750a.c
index e7a98dd3a08..134f69de740 100644
--- a/gnu/usr.bin/gcc/config/1750a/1750a.c
+++ b/gnu/usr.bin/gcc/config/1750a/1750a.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for MIL-STD-1750.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de)
This file is part of GNU CC.
@@ -19,19 +19,17 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#ifndef FILE
-#include <stdio.h>
-#endif
-#include <string.h>
-
#define __datalbl
#include "config.h"
+#include <stdio.h>
+#include <string.h>
#include "rtl.h"
#include "tree.h"
#include "expr.h"
#define HAVE_cc0
#include "conditions.h"
#include "real.h"
+#include "regs.h"
struct datalabel_array datalbl[DATALBL_ARRSIZ];
int datalbl_ndx = -1;
@@ -111,7 +109,6 @@ function_arg (cum, mode, type, named)
int named;
{
int size;
- rtx result;
if (MUST_PASS_IN_STACK (mode, type))
return (rtx) 0;
@@ -126,25 +123,6 @@ function_arg (cum, mode, type, named)
}
-#ifndef STRDUP
-char *
-strdup (str)
- char *str;
-{
- char *p;
- if (str == NULL)
- return NULL;
- if ((p = (char *) malloc (strlen (str) + 1)) == NULL)
- {
- fprintf (stderr, "dynamic memory exhausted");
- abort ();
- }
- return strcpy (p, str);
-}
-
-#endif
-
-
double
get_double (x)
rtx x;
@@ -179,7 +157,7 @@ float_label (code, value)
(*p == '-') ? 'm' : *p;
p++;
}
- return strdup (label);
+ return xstrdup (label);
}
@@ -187,21 +165,30 @@ char *
movcnt_regno_adjust (op)
rtx *op;
{
- static char outstr[40];
- int cntreg = REGNO (op[2]), cntreg_1750 = REGNO (op[0]) + 1;
- int dstreg = REGNO (op[0]), srcreg = REGNO (op[1]);
+ static char outstr[80];
+ int op0r = REGNO (op[0]), op1r = REGNO (op[1]), op2r = REGNO (op[2]);
+#define dstreg op0r
+#define srcreg op1r
+#define cntreg op2r
+#define cntreg_1750 (op0r + 1)
if (cntreg == cntreg_1750)
- sprintf (outstr, "mov r%%0,r%%1");
- else if (dstreg + 1 == srcreg && srcreg == cntreg + 2)
- sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", cntreg, dstreg);
- else if (dstreg + 1 == srcreg && srcreg < cntreg)
- sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, cntreg);
- else if (srcreg + 1 == cntreg && dstreg > cntreg)
- sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,r%%1", srcreg, dstreg);
+ sprintf (outstr, "mov r%d,r%d", op0r, op1r);
+ else if (dstreg + 1 == srcreg && cntreg > srcreg)
+ sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op2r, op1r, op0r, op2r);
+ else if (dstreg == cntreg + 1)
+ sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op2r, op2r, op1r);
+ else if (dstreg == srcreg + 1)
+ sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
+ op0r, op1r, op0r, op2r, op1r, op2r);
+ else if (cntreg + 1 == srcreg)
+ sprintf (outstr, "xwr r%d,r%d\n\txwr r%d,r%d\n\tmov r%d,r%d",
+ op2r, op1r, op0r, op2r, op2r, op0r);
+ else if (cntreg == srcreg + 1)
+ sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d", op0r, op1r, op1r, op0r);
else
- sprintf (outstr, "xwr r%d,r%d\n\tmov r%%0,%%1\n\txwr r%d,r%d",
- cntreg, cntreg_1750, cntreg_1750, cntreg);
+ sprintf (outstr, "xwr r%d,r%d\n\tmov r%d,r%d\n\txwr r%d,r%d",
+ op2r, cntreg_1750, op0r, op1r, op2r, cntreg_1750);
return outstr;
}
@@ -214,35 +201,48 @@ mod_regno_adjust (instr, op)
char *r = (!strncmp (instr, "dvr", 3) ? "r" : "");
int modregno_gcc = REGNO (op[3]), modregno_1750 = REGNO (op[0]) + 1;
- if (modregno_gcc == modregno_1750)
+ if (modregno_gcc == modregno_1750
+ || (reg_renumber != NULL
+ && reg_renumber[modregno_gcc] >= 0
+ && reg_renumber[modregno_gcc] == reg_renumber[modregno_1750]))
sprintf (outstr, "%s r%%0,%s%%2", instr, r);
else
sprintf (outstr, "lr r%d,r%d\n\t%s r%%0,%s%%2\n\txwr r%d,r%d",
- modregno_gcc, modregno_1750, instr, r, modregno_1750, modregno_gcc);
+ modregno_gcc, modregno_1750, instr, r, modregno_1750,
+ modregno_gcc);
return outstr;
}
-/* Auxiliary to `nonindirect_operand':
- Check if op is a valid memory operand for 1750A arith./logic (non-move)
- instructions. */
+/* Check if op is a valid memory operand for 1750A Load/Store instructions
+ (memory indirection permitted.) */
+
int
memop_valid (op)
rtx op;
{
- if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode)
+ static int recurred = 0;
+ int valid;
+
+ if (GET_MODE (op) != Pmode && GET_MODE (op) != VOIDmode
+ && GET_MODE (op) != QImode)
return 0;
switch (GET_CODE (op))
{
case MEM:
+ if (!recurred && GET_CODE (XEXP (op, 0)) == REG)
+ return 1;
case MINUS:
case MULT:
case DIV:
return 0;
case PLUS:
- if (!memop_valid (XEXP (op, 0)))
- return 0;
- return memop_valid (XEXP (op, 1));
+ recurred = 1;
+ valid = memop_valid (XEXP (op, 0));
+ if (valid)
+ valid = memop_valid (XEXP (op, 1));
+ recurred = 0;
+ return valid;
case REG:
if (REGNO (op) > 0)
return 1;
@@ -258,26 +258,14 @@ memop_valid (op)
}
}
-/* extra predicate for recog: */
+
+/* predicate for the MOV instruction: */
int
-nonindirect_operand (op, mode)
+mov_memory_operand (op, mode)
rtx op;
enum machine_mode mode;
{
- int retval;
-
- switch (GET_CODE (op))
- {
- case MEM:
- retval = memop_valid (XEXP (op, 0));
- return retval;
- case REG:
- return 1;
- default:
- if (!CONSTANT_P (op))
- return 0;
- }
- return 1;
+ return (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG);
}
/* predicate for the STC instruction: */
@@ -291,6 +279,15 @@ small_nonneg_const (op, mode)
return 0;
}
+/* predicate for constant zero: */
+int
+zero_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return op == CONST0_RTX (mode);
+}
+
/* predicate for 1750 `B' addressing mode (Base Register with Offset)
memory operand */
@@ -301,6 +298,8 @@ b_mode_operand (op)
if (GET_CODE (op) == MEM)
{
rtx inner = XEXP (op, 0);
+ if (GET_CODE (inner) == REG && REG_OK_FOR_INDEX_P (inner))
+ return 1;
if (GET_CODE (inner) == PLUS)
{
rtx plus_op0 = XEXP (inner, 0);
@@ -317,6 +316,7 @@ b_mode_operand (op)
return 0;
}
+
/* Decide whether to output a conditional jump as a "Jump Conditional"
or as a "Branch Conditional": */
@@ -390,40 +390,93 @@ next_cc_user_is_unsigned (insn)
}
+static int addr_inc;
+
+/* A C compound statement to output to stdio stream STREAM the
+ assembler syntax for an instruction operand X. X is an RTL
+ expression.
+
+ CODE is a value that can be used to specify one of several ways
+ of printing the operand. It is used when identical operands
+ must be printed differently depending on the context. CODE
+ comes from the `%' specification that was used to request
+ printing of the operand. If the specification was just `%DIGIT'
+ then CODE is 0; if the specification was `%LTR DIGIT' then CODE
+ is the ASCII code for LTR.
+
+ If X is a register, this macro should print the register's name.
+ The names can be found in an array `reg_names' whose type is
+ `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
-/* The PRINT_OPERAND and PRINT_OPERAND_ADDRESS macros have been
- made functions: */
+ When the machine description has a specification `%PUNCT' (a `%'
+ followed by a punctuation character), this macro is called with
+ a null pointer for X and the punctuation character for CODE.
-print_operand (file, x, kode)
+ The 1750 specific codes are:
+ 'J' for the negative of a constant
+ 'Q' for printing addresses in B mode syntax
+ 'd' for the second register in a pair
+ 't' for the third register in a triple
+ 'b' for the bit number (using 1750 test bit convention)
+ 'B' for the bit number of the 1's complement (for bit clear)
+ 'w' for int - 16
+*/
+
+print_operand (file, x, letter)
FILE *file;
rtx x;
- enum rtx_code kode;
+ int letter;
{
switch (GET_CODE (x))
{
case REG:
- fprintf (file, "%d", REGNO (x));
+ if (letter == 'd')
+ fprintf (file, "%d", REGNO (x) + 1);
+ else if (letter == 't')
+ fprintf (file, "%d", REGNO (x) + 2);
+ else
+ fprintf (file, "%d", REGNO (x));
break;
+
case SYMBOL_REF:
fprintf (file, "%s", XSTR (x, 0));
+ if (letter == 'A')
+ fprintf (file, "+1");
break;
+
case LABEL_REF:
case CONST:
case MEM:
- if (kode == 'Q')
- fprintf (file, "r%d,%d",
- REGNO (XEXP (XEXP (x, 0), 0)),
- INTVAL (XEXP (XEXP (x, 0), 1)));
+ if (letter == 'Q')
+ {
+ rtx inner = XEXP (x, 0);
+ switch (GET_CODE (inner))
+ {
+ case REG:
+ fprintf (file, "r%d,0", REGNO (inner));
+ break;
+ case PLUS:
+ fprintf (file, "r%d,%d", REGNO (XEXP (inner, 0)),
+ INTVAL (XEXP (inner, 1)));
+ break;
+ default:
+ fprintf (file, "[ill Q code=%d]", GET_CODE (inner));
+ }
+ }
else
- output_address (XEXP (x, 0));
+ {
+ addr_inc = (letter == 'A' ? 1 : 0);
+ output_address (XEXP (x, 0));
+ }
break;
+
case CONST_DOUBLE:
/* {
double value = get_double (x);
char fltstr[32];
sprintf (fltstr, "%lf", value);
- if (kode == 'D' || kode == 'E')
+ if (letter == 'D' || letter == 'E')
{
int i, found = 0;
for (i = 0; i <= datalbl_ndx; i++)
@@ -435,15 +488,15 @@ print_operand (file, x, kode)
if (!found)
{
strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
- datalbl[i].name = float_label (kode, value);
- datalbl[i].size = (kode == 'E') ? 3 : 2;
+ datalbl[i].name = float_label (letter, value);
+ datalbl[i].size = (letter == 'E') ? 3 : 2;
check_section (Konst);
fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
- (kode == 'E' ? "ef" : "f"), fltstr);
+ (letter == 'E' ? "ef" : "f"), fltstr);
check_section (Normal);
}
}
- else if (kode == 'F' || kode == 'G')
+ else if (letter == 'F' || letter == 'G')
{
int i, found = 0;
for (i = 0; i <= datalbl_ndx; i++)
@@ -457,11 +510,11 @@ print_operand (file, x, kode)
fprintf (stderr,
"float value %lfnot found upon label reference\n", value);
strcpy (datalbl[i = ++datalbl_ndx].value, fltstr);
- datalbl[i].name = float_label (kode, value);
- datalbl[i].size = (kode == 'G') ? 3 : 2;
+ datalbl[i].name = float_label (letter, value);
+ datalbl[i].size = (letter == 'G') ? 3 : 2;
check_section (Konst);
fprintf (file, "K%s \tdata%s %s ;p_o\n", datalbl[i].name,
- (kode == 'G' ? "ef" : "f"), fltstr);
+ (letter == 'G' ? "ef" : "f"), fltstr);
check_section (Normal);
}
fprintf (file, "%s ;P_O 'F'", datalbl[i].name);
@@ -472,22 +525,29 @@ print_operand (file, x, kode)
*/
fprintf (file, "%lf", get_double (x));
break;
+
case CONST_INT:
- if (kode == 'J')
+ if (letter == 'J')
fprintf (file, "%d", -INTVAL (x));
- else if (INTVAL (x) > 0x7FFF)
- fprintf (file, "%d ; range correction (val>0x7FFF) applied",
- INTVAL (x) - 0x10000);
+ else if (letter == 'b')
+ fprintf (file, "%d", which_bit (INTVAL (x)));
+ else if (letter == 'B')
+ fprintf (file, "%d", which_bit (~INTVAL (x)));
+ else if (letter == 'w')
+ fprintf (file, "%d", INTVAL (x) - 16);
else
fprintf (file, "%d", INTVAL (x));
break;
+
case CODE_LABEL:
fprintf (file, "L%d", XINT (x, 3));
break;
+
case CALL:
fprintf (file, "CALL nargs=%d, func is either '%s' or '%s'",
XEXP (x, 1), XSTR (XEXP (XEXP (x, 0), 1), 0), XSTR (XEXP (x, 0), 1));
break;
+
case PLUS:
{
rtx op0 = XEXP (x, 0), op1 = XEXP (x, 1);
@@ -496,7 +556,7 @@ print_operand (file, x, kode)
switch (op0code)
{
case REG:
- fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST",
+ fprintf (file, "%d,r%d ; p_o_PLUS for REG and CONST_INT",
INTVAL (op1), REGNO (op0));
break;
case SYMBOL_REF:
@@ -518,9 +578,12 @@ print_operand (file, x, kode)
fprintf (file, "p_o_+: op0code=%d, op1code=%d", op0code, op1code);
}
break;
+
default:
fprintf (file, "p_o_UFO code=%d", GET_CODE (x));
}
+
+ addr_inc = 0;
}
print_operand_address (file, addr)
@@ -530,7 +593,7 @@ print_operand_address (file, addr)
switch (GET_CODE (addr))
{
case REG:
- fprintf (file, "0,r%d ; P_O_A", REGNO (addr));
+ fprintf (file, "%d,r%d ; P_O_A", addr_inc, REGNO (addr));
break;
case PLUS:
{
@@ -545,11 +608,13 @@ print_operand_address (file, addr)
fprintf (file, ",r%d ;P_O_A reg + const expr", REGNO (x));
break;
case CONST_INT:
- fprintf (file, "%d,r%d", INTVAL (y), REGNO (x));
+ fprintf (file, "%d,r%d", INTVAL (y) + addr_inc, REGNO (x));
break;
case SYMBOL_REF:
- fprintf (file, "%s,r%d ; P_O_A reg + sym",
- XSTR (y, 0), REGNO (x));
+ fprintf (file, "%s", XSTR (y, 0));
+ if (addr_inc)
+ fprintf (file, "+%d", addr_inc);
+ fprintf (file, ",r%d ; P_O_A reg + sym", REGNO (x));
break;
case LABEL_REF:
output_address (XEXP (y, 0));
@@ -567,7 +632,7 @@ print_operand_address (file, addr)
switch (GET_CODE (y))
{
case CONST_INT:
- fprintf (file, "%d+%s", INTVAL (y), XSTR (x, 0));
+ fprintf (file, "%d+%s", INTVAL (y) + addr_inc, XSTR (x, 0));
break;
case REG:
fprintf (file, "%s,r%d ;P_O_A sym + reg",
@@ -609,6 +674,8 @@ print_operand_address (file, addr)
case LABEL_REF:
case SYMBOL_REF:
fprintf (file, "%s", XSTR (addr, 0));
+ if (addr_inc)
+ fprintf (file, "+%d", addr_inc);
break;
case MEM:
fprintf (file, "[memUFO:");
@@ -627,5 +694,41 @@ print_operand_address (file, addr)
(int) GET_CODE (addr), INTVAL (addr));
break;
}
+ addr_inc = 0;
+}
+
+
+/*
+ * Return non zero if the LS 16 bits of the given value has just one bit set,
+ * otherwise return zero. Note this function may be used to detect one
+ * bit clear by inverting the param.
+ */
+int
+one_bit_set_p (x)
+ int x;
+{
+ x &= 0xffff;
+ return x && (x & (x - 1)) == 0;
}
+
+/*
+ * Return the number of the least significant bit set, using the same
+ * convention for bit numbering as in the MIL-STD-1750 sb instruction.
+ */
+int
+which_bit (x)
+ int x;
+{
+ int b = 15;
+
+ while (b > 0 && (x & 1) == 0)
+ {
+ b--;
+ x >>= 1;
+ }
+
+ return b;
+}
+
+
diff --git a/gnu/usr.bin/gcc/config/1750a/1750a.h b/gnu/usr.bin/gcc/config/1750a/1750a.h
index 997b6c61ca2..fd2a7c6afa3 100644
--- a/gnu/usr.bin/gcc/config/1750a/1750a.h
+++ b/gnu/usr.bin/gcc/config/1750a/1750a.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
- Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de)
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by O.M.Kellogg, DASA (oliver.kellogg@space.otn.dasa.de)
This file is part of GNU CC.
@@ -66,7 +66,11 @@ extern struct jumplabel_array jmplbl[];
extern int datalbl_ndx, jmplbl_ndx, label_pending, program_counter;
extern enum section current_section;
extern char *sectname[4];
-extern char *strdup(), *float_label();
+extern char *xstrdup(), *float_label();
+extern struct rtx_def *function_arg ();
+extern char *movcnt_regno_adjust ();
+extern char *mod_regno_adjust ();
+extern char *branch_or_jump ();
#endif
/*--------------------------------------------------------------------*/
@@ -206,8 +210,9 @@ extern char *strdup(), *float_label();
registers listed in CALL_USED_REGISTERS, keeping the others
available for storage of persistent values. */
-#define REG_ALLOC_ORDER \
+/* #define REG_ALLOC_ORDER \
{ 2, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
+ */
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
@@ -242,7 +247,7 @@ extern char *strdup(), *float_label();
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 1
+#define FRAME_POINTER_REQUIRED 0
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM 14
@@ -255,8 +260,18 @@ extern char *strdup(), *float_label();
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 13
+/* Place in which caller passes the structure value address.
+ 0 means push the value on the stack like an argument.
+ #define STRUCT_VALUE 0
+*/
+
+/* Register in which address to store a structure value
+ arrives in the function.
+ #define STRUCT_VALUE_INCOMING 0
+*/
+
/* Register in which address to store a structure value
- is passed to a function. */
+ is passed to a function. */
#define STRUCT_VALUE_REGNUM 12
/* Define this to be 1 if all structure return values must be in memory. */
@@ -362,7 +377,9 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
/* Similar, but for floating constants, and defining letter 'G'.
Here VALUE is the CONST_DOUBLE rtx itself. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ((C) == 'G' ? ((VALUE) == CONST0_RTX (HFmode) \
+ || (VALUE) == CONST0_RTX (TQFmode)) : 0)
/* Optional extra constraints for this machine.
@@ -377,11 +394,9 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
/* 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.
- For the 1750A, we force an immediate CONST_DOUBLE value to memory. */
+ in some cases it is preferable to use a more restrictive class. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- (GET_CODE(X) == CONST_DOUBLE ? NO_REGS : CLASS)
+#define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
@@ -504,7 +519,7 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
For 1750A, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) ((CUM) = 0)
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0)
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.
@@ -529,15 +544,7 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis). */
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- (rtx) function_arg(CUM,MODE,TYPE,NAMED)
-/*
- (! MUST_PASS_IN_STACK(MODE,TYPE) && \
- 14 >= (CUM) + \
- ((MODE)==BLKmode ? int_size_in_bytes(TYPE) : GET_MODE_SIZE (MODE)) \
- ? gen_rtx (REG, MODE, CUM) \
- : 0)
-*/
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) function_arg (CUM,MODE,TYPE,NAMED)
/* Define the following macro if function calls on the target machine
do not preserve any registers; in other words, if `CALL_USED_REGISTERS'
@@ -558,23 +565,38 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
#define FUNCTION_PROLOGUE(FILE, SIZE) { \
- register int regno, none_used=1; \
- extern char call_used_regs[]; \
- fprintf(FILE, "; regs used in this function: "); \
- for (regno = 0; regno < 15; regno++) \
- if (regs_ever_live[regno]) { \
- fprintf(FILE," %s",reg_names[regno]); \
- none_used = 0; \
+ if (flag_verbose_asm) \
+ { \
+ int regno, regs_used = 0; \
+ fprintf (FILE, "\t; registers used: "); \
+ for (regno = 0; regno < 14; regno++) \
+ if (regs_ever_live[regno]) \
+ { \
+ fprintf (FILE, " %s", reg_names[regno]); \
+ regs_used++; \
+ } \
+ if (regs_used == 0) \
+ fprintf (FILE, "(none)"); \
} \
- if (none_used) \
- fprintf(FILE," (none)"); \
- fprintf(FILE,"\n"); \
if (SIZE > 0) \
- fprintf(FILE,"\t%s\tr15,%d ; reserve local-variable space\n",\
- (SIZE <= 16 ? "sisp" : "sim"),SIZE); \
- fprintf(FILE,"\tpshm\tr14,r14 ; push old frame\n"); \
- fprintf(FILE,"\tlr\tr14,r15 ; set new frame\n"); \
- program_counter = 0; jmplbl_ndx = -1; \
+ { \
+ fprintf (FILE, "\n\t%s\tr15,%d", \
+ (SIZE <= 16 ? "sisp" : "sim"), SIZE); \
+ if (flag_verbose_asm) \
+ fprintf (FILE, " ; reserve local-variable space"); \
+ } \
+ if (frame_pointer_needed) \
+ { \
+ fprintf(FILE, "\n\tpshm\tr14,r14"); \
+ if (flag_verbose_asm) \
+ fprintf (FILE, " ; push old frame"); \
+ fprintf (FILE, "\n\tlr\tr14,r15"); \
+ if (flag_verbose_asm) \
+ fprintf (FILE, " ; set new frame"); \
+ } \
+ fprintf (FILE, "\n"); \
+ program_counter = 0; \
+ jmplbl_ndx = -1; \
}
/************* 1750: PROFILER HANDLING NOT YET DONE !!!!!!! *************/
@@ -599,7 +621,7 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
functions that have frame pointers.
No definition is equivalent to always zero. */
-#define EXIT_IGNORE_STACK 1
+#define EXIT_IGNORE_STACK 0
/* This macro generates the assembly code for function exit,
on machines that need it. If FUNCTION_EPILOGUE is not defined
@@ -612,39 +634,51 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
before returning. */
#define FUNCTION_EPILOGUE(FILE, SIZE) { \
- fprintf(FILE,"\tlr\tr15,r14 ; set stack ptr to frame ptr\n"); \
- fprintf(FILE,"\tpopm\tr14,r14 ; restore previous frame ptr\n"); \
+ if (frame_pointer_needed) \
+ { \
+ fprintf (FILE, "\tlr\tr15,r14"); \
+ if (flag_verbose_asm) \
+ fprintf (FILE, " ; set stack ptr to frame ptr"); \
+ fprintf (FILE, "\n\tpopm\tr14,r14"); \
+ if (flag_verbose_asm) \
+ fprintf (FILE, " ; restore previous frame ptr"); \
+ fprintf (FILE, "\n"); \
+ } \
if (SIZE > 0) \
- fprintf(FILE,"\t%s\tr15,%d ; free up local-var space\n", \
- (SIZE <= 16 ? "aisp" : "aim"),SIZE); \
- fprintf(FILE,"\turs\tr15\n"); }
+ { \
+ fprintf (FILE, "\t%s\tr15,%d", \
+ (SIZE <= 16 ? "aisp" : "aim"), SIZE); \
+ if (flag_verbose_asm) \
+ fprintf (FILE, " ; free up local-var space"); \
+ fprintf (FILE, "\n"); \
+ } \
+ fprintf (FILE, "\turs\tr15\n\n"); \
+}
/* If the memory address ADDR is relative to the frame pointer,
correct it to be relative to the stack pointer instead.
This is for when we don't use a frame pointer.
- ADDR should be a variable name. */
+ ADDR should be a variable name.
-#define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH) \
- fprintf(stderr,"FIX_FRAME_POINTER_ADDRESS called, DEPTH=%d\n"), \
- DEPTH), abort()
+ #define FIX_FRAME_POINTER_ADDRESS(ADDR,DEPTH)
+*/
/* Store in the variable DEPTH the initial difference between the
frame pointer reg contents and the stack pointer reg contents,
as of the start of the function body. This depends on the layout
of the fixed parts of the stack frame and on how registers are saved.
-*/
#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) DEPTH = 0
+*/
-/* 1750: not needed 'cause we have INITIAL_FRAME_POINTER_OFFSET.
- #define ELIMINABLE_REGS { \
+#define ELIMINABLE_REGS { \
{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM }, \
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM } }
- #define CAN_ELIMINATE(FROM, TO) 1
+#define CAN_ELIMINATE(FROM, TO) 1
- #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) { OFFSET = 0; }
-*/
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ OFFSET = (TO == STACK_POINTER_REGNUM) ? -1 : 0
/* Output assembler code for a block containing the constant parts
@@ -732,9 +766,9 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
#ifdef REG_OK_STRICT
/* Nonzero if X is a hard reg that can be used as an index. */
-#define REG_OK_FOR_INDEX_P(X) (REGNO (X) >= 12 && REGNO (X) <= 15)
+#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 (X) > 0 && REGNO (X) <= 15)
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P(REGNO(X))
#else
@@ -817,8 +851,11 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
/* Max number of bytes we can move from memory to memory
in one reasonably fast instruction. */
-/* (was: "1750: not counting the MOV instruction") */
-#define MOVE_MAX 16
+#define MOVE_MAX 65536
+
+/* MOVE_RATIO is the number of move instructions that is better than a
+ block move. */
+#define MOVE_RATIO 4
/* Define this if zero-extension is slow (more than one real instruction). */
/* #define SLOW_ZERO_EXTEND */
@@ -857,23 +894,22 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
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. */
-/* 1750 note: haven't paid attention to this yet. */
-#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
case CONST_INT: \
return (INTVAL(RTX) >= -16 && INTVAL(RTX) <= 16) ? 1 : 3; \
case CONST: \
case LABEL_REF: \
case SYMBOL_REF: \
- return 5; \
+ return 3; \
case CONST_DOUBLE: \
- return 7;
+ return 4;
-#define ADDRESS_COST(ADDRESS) (memop_valid(ADDRESS) ? 3 : 1000)
+#define ADDRESS_COST(ADDRESS) (memop_valid (ADDRESS) ? 3 : 10)
#define REGISTER_MOVE_COST(FROM,TO) 2
-#define MEMORY_MOVE_COST(M) 5
+#define MEMORY_MOVE_COST(M) 4
/* Tell final.c how to eliminate redundant test instructions. */
@@ -949,12 +985,12 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
/* Output to assembler file text saying following lines
may contain character constants, extra white space, comments, etc. */
-#define ASM_APP_ON "\n\tif 0\n; by ASM_APP_ON\n"
+#define ASM_APP_ON "; ASM_APP_ON\n"
/* Output to assembler file text saying following lines
no longer contain unusual constructs. */
-#define ASM_APP_OFF "\n\tendif\n"
+#define ASM_APP_OFF "; ASM_APP_OFF\n"
#define EXTRA_SECTIONS in_readonly_data
@@ -1054,7 +1090,7 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
check_section(Konst); \
fprintf(FILE,"K%s\n",NAME); \
fflush(FILE); \
- datalbl[++datalbl_ndx].name = (char *)strdup (NAME); \
+ datalbl[++datalbl_ndx].name = (char *)xstrdup (NAME);\
datalbl[datalbl_ndx].size = 0; \
label_pending = 1; \
} \
@@ -1068,11 +1104,9 @@ enum reg_class { NO_REGS, R2, R0_1, INDEX_REGS, BASE_REGS, ALL_REGS, LIM_REG_CLA
fprintf (FILE, "\tglobal %s\t; export\n", NAME); \
} 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. */
diff --git a/gnu/usr.bin/gcc/config/1750a/1750a.md b/gnu/usr.bin/gcc/config/1750a/1750a.md
index e2d4f2644c6..161d75d9bda 100644
--- a/gnu/usr.bin/gcc/config/1750a/1750a.md
+++ b/gnu/usr.bin/gcc/config/1750a/1750a.md
@@ -1,7 +1,7 @@
;;- Machine description for GNU compiler
;;- MIL-STD-1750A version.
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-;; Contributed by O.M.Kellogg, DASA (kellogg@space.otn.dasa.de).
+;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Contributed by O.M.Kellogg, DASA (oliver.kellogg@space.otn.dasa.de).
;; This file is part of GNU CC.
@@ -55,49 +55,25 @@
[(set (match_operand:QI 0 "push_operand" "=<")
(match_operand:QI 1 "general_operand" "r"))]
""
- "pshm r%1,r%1 ; stackptr = R%0")
+ "pshm r%1,r%1")
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "general_operand" "r"))]
""
- "*
- {
- rtx new_operands[3];
- new_operands[2] = operands[0];
- new_operands[0] = operands[1];
- new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+1);
- output_asm_insn(\"pshm r%0,r%1 ; stackptr = r%2\",new_operands);
- return \";\";
- } ")
+ "pshm r%1,r%d1")
(define_insn ""
[(set (match_operand:HF 0 "push_operand" "=<")
(match_operand:HF 1 "general_operand" "r"))]
""
- "*
- {
- rtx new_operands[3];
- new_operands[2] = operands[0];
- new_operands[0] = operands[1];
- new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+1);
- output_asm_insn(\"pshm r%0,r%1 ; stackptr = r%2\",new_operands);
- return \";\";
- } ")
+ "pshm r%1,r%d1")
(define_insn ""
[(set (match_operand:TQF 0 "push_operand" "=<")
(match_operand:TQF 1 "general_operand" "r"))]
""
- "*
- {
- rtx new_operands[3];
- new_operands[2] = operands[0];
- new_operands[0] = operands[1];
- new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[1])+2);
- output_asm_insn(\"pshm r%0,r%1 ; stackptr = r%2\",new_operands);
- return \";\";
- } ")
+ "pshm r%1,r%t1")
;; stackpop
(define_insn ""
@@ -110,43 +86,22 @@
[(set (match_operand:HI 0 "general_operand" "=r")
(match_operand:HI 1 "push_operand" ">"))]
""
- "*
- {
- rtx new_operands[2];
- new_operands[0] = operands[0];
- new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+1);
- output_asm_insn(\"popm r%0,r%1\",new_operands);
- return \";\";
- } ")
+ "popm r%1,r%d1")
(define_insn ""
[(set (match_operand:HF 0 "general_operand" "=r")
(match_operand:HF 1 "push_operand" ">"))]
""
- "*
- {
- rtx new_operands[2];
- new_operands[0] = operands[0];
- new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+1);
- output_asm_insn(\"popm r%0,r%1\",new_operands);
- return \";\";
- } ")
-
+ "popm r%1,r%d1")
+
(define_insn ""
[(set (match_operand:TQF 0 "general_operand" "=r")
(match_operand:TQF 1 "push_operand" ">"))]
""
- "*
- {
- rtx new_operands[2];
- new_operands[0] = operands[0];
- new_operands[1] = gen_rtx(CONST_INT,VOIDmode,REGNO(operands[0])+2);
- output_asm_insn(\"popm r%0,r%1\",new_operands);
- return \";\";
- } ")
+ "popm r%1,r%t1")
+
-;; Test operations. These shouldn't really occur for 1750:
-;; all important instructions set the cc's (see NOTICE_UPDATE_CC)
+;; Test operations.
(define_insn "tstqi"
[(set (cc0)
@@ -160,35 +115,42 @@
""
"dlr r%0,r%0 ; from tsthi")
+; With 1750A floats, testing the most significant word suffices.
+
(define_insn "tsthf"
[(set (cc0)
(match_operand:HF 0 "register_operand" "r"))]
""
- "dlr r%0,r%0 ; from tsthf")
+ "lr r%0,r%0 ; tsthf")
-;; This one is happy with "roughly zero" :-) (should be improved)
(define_insn "tsttqf"
[(set (cc0)
(match_operand:TQF 0 "register_operand" "r"))]
""
- "dlr r%0,r%0 ; from tsttqf")
+ "lr r%0,r%0 ; tsttqf")
;; block move.
-; there is a problem with this insn in gcc-2.2.3
-; (clobber (match_dup 2)) does not prevent use of this operand later
-;
(define_insn "movstrqi"
- [(set (mem:BLK (match_operand:QI 0 "register_operand" "r"))
- (mem:BLK (match_operand:QI 1 "register_operand" "r")))
- (use (match_operand:QI 2 "register_operand" "r"))
- (use (match_operand:QI 3 "immediate_operand" ""))
+ [(set (match_operand:BLK 0 "mov_memory_operand" "m")
+ (match_operand:BLK 1 "mov_memory_operand" "m"))
+ (use (match_operand:QI 2 "general_operand" "r"))
+ (match_operand 3 "" "")
(clobber (match_dup 0))
(clobber (match_dup 1))
(clobber (match_dup 2))]
""
- "* return (char *)movcnt_regno_adjust(operands); ")
+ "*
+ {
+ rtx regops[3];
+
+ regops[0] = XEXP (operands[0], 0);
+ regops[1] = XEXP (operands[1], 0);
+ regops[2] = operands[2];
+
+ return movcnt_regno_adjust (regops);
+ } ")
;; compare instructions.
@@ -233,18 +195,29 @@
(compare (match_operand:HI 0 "general_operand" "r,r")
(match_operand:HI 1 "general_operand" "r,m")))]
""
- "@
- dcr r%0,r%1
- dc r%0,%1 ")
+ "*
+ {
+ if (next_cc_user_is_unsigned (insn))
+ {
+ if (which_alternative == 0)
+ return \"ducr.m %0,%1\";
+ return \"duc.m %0,%1\";
+ }
+ else
+ {
+ if (which_alternative == 0)
+ return \"dcr r%0,r%1\";
+ return \"dc r%0,%1\";
+ }
+ } ")
(define_insn "cmphf"
[(set (cc0)
- (compare (match_operand:HF 0 "general_operand" "r,z,r")
- (match_operand:HF 1 "general_operand" "r,Q,m")))]
+ (compare (match_operand:HF 0 "general_operand" "r,r")
+ (match_operand:HF 1 "general_operand" "r,m")))]
""
"@
fcr r%0,r%1
- fcb %Q1
fc r%0,%1 ")
(define_insn "cmptqf"
@@ -262,55 +235,29 @@
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "register_operand" "=r")
- (truncate:QI
- (match_operand:HI 1 "register_operand" "r")))]
+ (truncate:QI (match_operand:HI 1 "register_operand" "r")))]
""
- "*
- {
- rtx new_operands[2];
- new_operands[0] = operands[0];
- new_operands[1] = gen_rtx (REG, HImode, REGNO(operands[1]) + 1);
- output_asm_insn(\"lr r%0,r%1 ;trunchiqi2\",new_operands);
- return \";\";
- } ")
+ "lr r%0,r%d1")
-;; zero extension instructions
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
- (zero_extend:HI (match_operand:QI 1 "general_operand" "r,m,i")))]
- ""
- "*
- {
- rtx new_opnds[2];
- output_asm_insn(\"xorr r%0,r%0 ;zero_extendqihi2\",operands);
- new_opnds[0] = gen_rtx (REG, HImode, REGNO(operands[0]) + 1);
- new_opnds[1] = operands[1];
- switch (which_alternative)
- {
- case 0:
- output_asm_insn(\"lr r%0,r%1\",new_opnds);
- break;
- case 1:
- output_asm_insn(\"l r%0,%1\",new_opnds);
- break;
- case 2:
- output_asm_insn(\"lim r%0,%1\",new_opnds);
- break;
- }
- return \";\";
- } ")
+;; zero extension instructions: not defined, GCC can synthesize
;; sign extension instructions
(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r,r,r")
- (sign_extend:HI (match_operand:QI 1 "general_operand" "r,m,i")) )]
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (sign_extend:HI (match_operand:QI 1 "general_operand" "r,m")) )]
""
- "@
- lr r%0,r%1 ;extendqihi2\;dsra r%0,16
- l r%0,%1 ;extendqihi2\;dsra r%0,16
- lim r%0,%1 ;extendqihi2\;dsra r%0,16 ")
+ "*
+ if (which_alternative == 0)
+ {
+ if (REGNO (operands [0]) != REGNO (operands [1]))
+ output_asm_insn (\"lr r%0,r%1\", operands);
+ }
+ else
+ output_asm_insn (\"l r%0,%1\", operands);
+ return \"dsra r%0,16 ;extendqihi2\";
+ ")
;; Conversions between float and double.
@@ -321,16 +268,17 @@
(float_extend:TQF (match_operand:HF 1 "general_operand" "r,m")))]
""
"*
+ output_asm_insn(\"xorr r%t0,r%t0 ;extendhftqf2\", operands);
+ if (which_alternative == 0)
{
- rtx new_opnds[2];
- new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0]) + 2);
- new_opnds[1] = operands[1];
- output_asm_insn(\"xorr r%0,r%0 ;extendhftqf2\",new_opnds);
- if (which_alternative == 0)
- return \"dlr r%0,r%1 ; put condition codes back on track\";
+ if (REGNO (operands[1]) != REGNO (operands[0]))
+ return \"dlr r%0,r%1\";
else
- return \"dl r%0,%1 ; put condition codes back on track\";
- } ")
+ return \";\";
+ }
+ else
+ return \"dl r%0,%1\";
+ ")
; 1750 TQF-to-HF truncate is a no-op: just leave away the least signif. 16 bits
(define_insn "trunctqfhf2"
@@ -381,112 +329,120 @@
;; 16-bit moves
+; memory indirect to reg
+(define_insn ""
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (match_operand 1 "memory_operand" "m")))]
+ ""
+ "li r%0,%1")
+
+; reg/const to memory indirect
+(define_insn ""
+ [(set (mem:QI (match_operand 0 "memory_operand" "=m,m"))
+ (match_operand:QI 1 "nonmemory_operand" "r,K"))]
+ ""
+ "@
+ sti r%1,%0
+ stci %1,%0")
+
+; general case
(define_insn "movqi"
- [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,r,t,r,Q,m,m")
- (match_operand:QI 1 "general_operand" "O,I,J,M,i,r,Q,m,t,r,K"))]
+ [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,r,m,m")
+ (match_operand:QI 1 "general_operand" "O,I,J,i,r,m,r,K"))]
""
"@
xorr r%0,r%0
lisp r%0,%1
lisn r%0,%J1
- lim r%0,%1 ; 'M' constraint
- lim r%0,%1 ; 'i' constraint
+ lim r%0,%1
lr r%0,r%1
- lb %Q1
l r%0,%1
- stb %Q0
st r%1,%0
stc %1,%0 ")
;; 32-bit moves
-; Set HIreg to constant
+; memory indirect to reg
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
- (match_operand:HI 1 "immediate_operand" "i"))]
+ (mem:HI (match_operand 1 "memory_operand" "m")))]
""
- "*
- {
- rtx new_opnds[2];
- int val = INTVAL(operands[1]);
- if (val >= 0)
- {
- if (val <= 65535)
- {
- new_opnds[0] = gen_rtx(REG,QImode,REGNO(operands[0]));
- new_opnds[1] = operands[1];
- output_asm_insn(\"xorr r%0,r%0 ;movhi cst->reg\",new_opnds);
- REGNO(new_opnds[0]) += 1;
- if (val == 0)
- output_asm_insn(\"xorr r%0,r%0\",new_opnds);
- else if (val <= 16)
- output_asm_insn(\"lisp r%0,%1\",new_opnds);
- else
- output_asm_insn(\"lim r%0,%1\",new_opnds);
- return \";\";
- }
- }
- else if (val >= -16)
- return \"lisn r%0,%J1\;dsra r%0,16 ;movhi cst\";
- new_opnds[0] = gen_rtx(REG, QImode, REGNO(operands[0]));
- new_opnds[1] = gen_rtx(CONST_INT,VOIDmode,(INTVAL(operands[1])) >> 16);
- output_asm_insn(\"lim r%0,%1 ;movhi cst->reg\",new_opnds);
- INTVAL(new_opnds[1]) = val & 0xFFFF;
- REGNO(new_opnds[0]) += 1;
- output_asm_insn(\"lim r%0,%1\",new_opnds);
- return \";\";
- }
- ")
+ "dli r%0,%1")
+
+; reg to memory indirect
+(define_insn ""
+ [(set (mem:HI (match_operand 0 "memory_operand" "=m"))
+ (match_operand:HI 1 "register_operand" "r"))]
+ ""
+ "dsti r%1,%0")
-(define_insn "movhi"
- [(set (match_operand:HI 0 "general_operand" "=r,z,r,Q,m")
- (match_operand:HI 1 "general_operand" "r,Q,m,z,r"))]
+; general case
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=r,r,r,r,r,m,m")
+ (match_operand:HI 1 "general_operand" "O,I,J,r,m,r,K"))]
""
"@
+ xorr r%0,r%0\;xorr r%d0,r%d0
+ xorr r%0,r%0\;lisp r%d0,%1
+ lisn r%0,1 \;lisn r%d0,%J1
dlr r%0,r%1
- dlb %Q1
dl r%0,%1
- dstb %Q0
- dst r%1,%0 ")
+ dst r%1,%0
+ stc 0,%0 \;stc %1,%A0 ")
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=g")
+ (match_operand:HI 1 "general_operand" "g"))]
+ ""
+ "
+ {
+ rtx op1 = operands[1];
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (op1) == MEM
+ || (GET_CODE (op1) == CONST_INT
+ && (INTVAL (op1) < 0 || INTVAL (op1) > 15)))
+ operands[1] = force_reg (HImode, operands[1]);
+ }
+ else if (GET_CODE (op1) == CONST_INT
+ && (INTVAL (op1) < -16 || INTVAL (op1) > 16))
+ operands[1] = force_const_mem (HImode, operands[1]);
+ }")
-;; Single-Float moves are *same* as HImode moves:
-;(define_insn "movhf"
-; [(set (match_operand:HF 0 "general_operand" "=r,r,r,m")
-; (match_operand:HF 1 "general_operand" "F,r,m,r"))]
-; ""
-; "@
-; %D1\;dl r%0,%F1
-; dlr r%0,r%1
-; dl r%0,%1
-; dst r%1,%0 ")
+;; Single-Float moves
-(define_insn "movhf"
- [(set (match_operand:HF 0 "general_operand" "=r,z,r,Q,m")
- (match_operand:HF 1 "general_operand" "r,Q,m,z,r"))]
+(define_insn ""
+ [(set (match_operand:HF 0 "general_operand" "=r,r,m,m")
+ (match_operand:HF 1 "general_operand" "r,m,r,G"))]
""
"@
dlr r%0,r%1
- dlb %Q1
dl r%0,%1
- dstb %Q0
- dst r%1,%0 ")
+ dst r%1,%0
+ stc 0,%0 \;stc 0,%A0 ")
+
+(define_expand "movhf"
+ [(set (match_operand:HF 0 "general_operand" "")
+ (match_operand:HF 1 "general_operand" ""))]
+ ""
+ "
+ {
+ enum rtx_code op1code = GET_CODE (operands[1]);
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (op1code == MEM || (op1code == CONST_DOUBLE
+ && !rtx_equal_p (operands[1], CONST0_RTX (HFmode))))
+ operands[1] = force_reg (HFmode, operands[1]);
+ }
+ else if (op1code == CONST_DOUBLE)
+ operands[1] = force_const_mem (HFmode, operands[1]);
+ }")
;; Longfloat moves
-;(define_insn "movtqf"
-; [(set (match_operand:TQF 0 "general_operand" "=r,r,r,m")
-; (match_operand:TQF 1 "general_operand" "F,r,m,r"))]
-; ""
-; "@
-; %E1\;efl r%0,%G1
-; eflr.m %0,%1
-; efl r%0,%1
-; efst r%1,%0 ")
-
-(define_insn "movtqf"
+(define_insn ""
[(set (match_operand:TQF 0 "general_operand" "=r,r,m")
(match_operand:TQF 1 "general_operand" "r,m,r"))]
""
@@ -495,15 +451,31 @@
efl r%0,%1
efst r%1,%0 ")
+(define_expand "movtqf"
+ [(set (match_operand:TQF 0 "general_operand" "")
+ (match_operand:TQF 1 "general_operand" ""))]
+ ""
+ "
+ {
+ enum rtx_code op1code = GET_CODE (operands[1]);
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (op1code == MEM || op1code == CONST_DOUBLE)
+ operands[1] = force_reg (TQFmode, operands[1]);
+ }
+ else if (op1code == CONST_DOUBLE)
+ operands[1] = force_const_mem (TQFmode, operands[1]);
+ }")
+
;; add instructions
;; single integer
(define_insn "addqi3"
- [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,t,r,m,m")
- (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "I,J,i,r,Q,m,I,J")))]
+ [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,r,m,m")
+ (plus:QI (match_operand:QI 1 "general_operand" "%0,0,0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "I,J,i,r,m,I,J")))]
""
"*
switch (which_alternative)
@@ -520,12 +492,10 @@
case 3:
return \"ar r%0,r%2\";
case 4:
- return \"ab %Q2\";
- case 5:
return \"a r%0,%2\";
- case 6:
+ case 5:
return \"incm %2,%0\";
- case 7:
+ case 6:
return \"decm %J2,%0\";
} ")
@@ -540,13 +510,12 @@
da r%0,%2 ")
(define_insn "addhf3"
- [(set (match_operand:HF 0 "register_operand" "=r,z,r")
- (plus:HF (match_operand:HF 1 "register_operand" "%0,0,0")
- (match_operand:HF 2 "general_operand" "r,Q,m")))]
+ [(set (match_operand:HF 0 "register_operand" "=r,r")
+ (plus:HF (match_operand:HF 1 "register_operand" "%0,0")
+ (match_operand:HF 2 "general_operand" "r,m")))]
""
"@
far r%0,r%2
- fab %Q2
fa r%0,%2 ")
(define_insn "addtqf3"
@@ -563,15 +532,14 @@
;; single integer
(define_insn "subqi3"
- [(set (match_operand:QI 0 "general_operand" "=r,r,r,t,r,m")
- (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0,0,0")
- (match_operand:QI 2 "general_operand" "I,i,r,Q,m,I")))]
+ [(set (match_operand:QI 0 "general_operand" "=r,r,r,r,m")
+ (minus:QI (match_operand:QI 1 "general_operand" "0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "I,i,r,m,I")))]
""
"@
sisp r%0,%2
sim r%0,%2
sr r%0,r%2
- sbb %Q2
s r%0,%2
decm %2,%0 ")
@@ -586,13 +554,12 @@
ds r%0,%2 ")
(define_insn "subhf3"
- [(set (match_operand:HF 0 "register_operand" "=r,z,r")
- (minus:HF (match_operand:HF 1 "register_operand" "0,0,0")
- (match_operand:HF 2 "general_operand" "r,Q,m")))]
+ [(set (match_operand:HF 0 "register_operand" "=r,r")
+ (minus:HF (match_operand:HF 1 "register_operand" "0,0")
+ (match_operand:HF 2 "general_operand" "r,m")))]
""
"@
fsr r%0,r%2
- fsb %Q2
fs r%0,%2 ")
(define_insn "subtqf3"
@@ -622,15 +589,25 @@
; 32-bit product
(define_insn "mulqihi3"
- [(set (match_operand:HI 0 "register_operand" "=r,r,t,r")
- (mult:HI (match_operand:QI 1 "register_operand" "%0,0,0,0")
- (match_operand:QI 2 "general_operand" "M,r,Q,m")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r")
+ (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%r,r,r"))
+ (sign_extend:HI (match_operand:QI 2 "general_operand" "r,m,i"))))]
""
- "@
- mim r%0,%1
- mr r%0,r%2
- mb %Q2
- m r%0,%2 ")
+ "*
+ if (REGNO (operands[1]) != REGNO (operands[0]))
+ output_asm_insn (\"lr r%0,r%1\", operands);
+
+ switch (which_alternative)
+ {
+ case 0:
+ return \"mr r%0,r%2\";
+ case 1:
+ return \"m r%0,%2\";
+ case 2:
+ return \"mim r%0,%2\";
+ }
+ ")
+
(define_insn "mulhi3"
[(set (match_operand:HI 0 "register_operand" "=r,r")
@@ -644,13 +621,12 @@
; not available on 1750: "umulhi3","umulhisi3","umulsi3" (unsigned multiply's)
(define_insn "mulhf3"
- [(set (match_operand:HF 0 "register_operand" "=r,z,r")
- (mult:HF (match_operand:HF 1 "register_operand" "%0,0,0")
- (match_operand:HF 2 "general_operand" "r,Q,m")))]
+ [(set (match_operand:HF 0 "register_operand" "=r,r")
+ (mult:HF (match_operand:HF 1 "register_operand" "%0,0")
+ (match_operand:HF 2 "general_operand" "r,m")))]
""
"@
fmr r%0,r%2
- fmb %Q2
fm r%0,%2 ")
(define_insn "multqf3"
@@ -696,7 +672,7 @@
new_opnds[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL(operands[2]));
new_opnds[3] = operands[3];
istr = \"disn\";
- return (char *)mod_regno_adjust(istr,new_opnds);
+ return mod_regno_adjust (istr, new_opnds);
}
break;
case 2:
@@ -709,7 +685,7 @@
istr = \"dv \";
break;
}
- return (char *)mod_regno_adjust(istr,operands);
+ return mod_regno_adjust (istr, operands);
}")
;; Division for other types is straightforward.
@@ -724,13 +700,12 @@
dd r%0,%2 ")
(define_insn "divhf3"
- [(set (match_operand:HF 0 "register_operand" "=r,z,r")
- (div:HF (match_operand:HF 1 "register_operand" "0,0,0")
- (match_operand:HF 2 "general_operand" "r,Q,m")))]
+ [(set (match_operand:HF 0 "register_operand" "=r,r")
+ (div:HF (match_operand:HF 1 "register_operand" "0,0")
+ (match_operand:HF 2 "general_operand" "r,m")))]
""
"@
fdr r%0,r%2
- fdb %Q2
fd r%0,%2 ")
(define_insn "divtqf3"
@@ -801,17 +776,55 @@
;; bit-logical instructions
+;; Set Bit
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=r,m")
+ (ior:QI (match_operand:QI 1 "general_operand" "0,0")
+ (match_operand:QI 2 "const_int_operand" "i,i")))]
+ "one_bit_set_p (INTVAL (operands [2]))"
+ "@
+ sbr %b2,r%0
+ sb %b2,%0")
+
+;; Reset Bit
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=r,m")
+ (and:QI (match_operand:QI 1 "general_operand" "0,0")
+ (match_operand:QI 2 "const_int_operand" "i,i")))]
+ "one_bit_set_p ((~INTVAL (operands [2])) & 0xffff)"
+ "@
+ rbr %B2,r%0
+ rb %B2,%0")
+
+;; Set Variable Bit
+(define_insn ""
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (ior:QI (match_operand:QI 1 "register_operand" "0")
+ (lshiftrt:QI (const_int 0x8000)
+ (match_operand:QI 2 "register_operand" "r"))))]
+ ""
+ "svbr r%2,%r0")
+
+;; Reset Variable Bit
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=r")
+ (and:QI (match_operand:QI 1 "general_operand" "0")
+ (not:QI (lshiftrt:QI (const_int 0x8000)
+ (match_operand:QI 2 "register_operand" "r")))))]
+ ""
+ "rvbr r%2,%r0")
+
+
;; AND
(define_insn "andqi3"
- [(set (match_operand:QI 0 "general_operand" "=r,r,t,r")
- (and:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
- (match_operand:QI 2 "general_operand" "M,r,Q,m")))]
+ [(set (match_operand:QI 0 "general_operand" "=r,r,r")
+ (and:QI (match_operand:QI 1 "general_operand" "%0,0,0")
+ (match_operand:QI 2 "general_operand" "M,r,m")))]
""
"@
andm r%0,%2
andr r%0,r%2
- andb %Q2
and r%0,%2 ")
; This sets incorrect condition codes. See notice_update_cc()
@@ -825,14 +838,13 @@
;; OR
(define_insn "iorqi3"
- [(set (match_operand:QI 0 "general_operand" "=r,r,t,r")
- (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0,0")
- (match_operand:QI 2 "general_operand" "M,r,Q,m")))]
+ [(set (match_operand:QI 0 "general_operand" "=r,r,r")
+ (ior:QI (match_operand:QI 1 "general_operand" "%0,0,0")
+ (match_operand:QI 2 "general_operand" "M,r,m")))]
""
"@
orim r%0,%2
orr r%0,r%2
- orb %Q2
or r%0,%2 ")
; This sets incorrect condition codes. See notice_update_cc()
@@ -917,20 +929,16 @@
(match_operand:QI 2 "nonmemory_operand" "L,r")))]
"" ; the 'L' constraint is a slight imprecise...
"*
- if (which_alternative == 1)
- return \"dslr r%0,r%2\";
- else if (INTVAL(operands[2]) <= 16)
- return \"dsll r%0,%2\";
- else
- {
- rtx new_opnds[2];
- new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0]));
- new_opnds[1] = gen_rtx (REG, QImode, REGNO(operands[0]) + 1);
- output_asm_insn(\"lr r%0,r%1 ; ashlhi3 shiftcount > 16\",new_opnds);
- new_opnds[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL(operands[2]) - 16);
- output_asm_insn(\"sll r%0,%1\",new_opnds);
- return \";\";
- } ")
+ if (which_alternative == 1)
+ return \"dslr r%0,r%2\";
+ else if (INTVAL(operands[2]) <= 16)
+ return \"dsll r%0,%2\";
+ else
+ {
+ output_asm_insn (\"dsll r%0,16 ; ashlhi3 shiftcnt > 16\", operands);
+ return \"sll r%0,%w2\";
+ }
+ ")
;; Right shift by a variable shiftcount works by negating the shift count,
@@ -939,8 +947,8 @@
;; prevents converting shifts to ZERO_EXTRACTs with negative positions,
;; which isn't valid.
(define_expand "lshrqi3"
- [(set (match_operand:QI 0 "general_operand" "=r")
- (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "g")))]
""
"
@@ -982,17 +990,11 @@
(match_operand:QI 2 "immediate_operand" "L")))]
""
"*
- {
- rtx new_opnds[2];
- int amount = INTVAL(operands[2]);
- if (amount <= 16)
+ if (INTVAL (operands[2]) <= 16)
return \"dsrl r%0,%2\";
- output_asm_insn(\"dsrl r%0,16 ; lshrhi3 shiftcount > 16\",operands);
- new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0]) + 1);
- new_opnds[1] = gen_rtx (CONST_INT, VOIDmode, amount - 16);
- output_asm_insn(\"srl r%0,%1\",new_opnds);
- return \";\";
- } ")
+ output_asm_insn (\"dsrl r%0,16 ; lshrhi3 shiftcount > 16\", operands);
+ return \"srl r%d0,%w2\";
+ ")
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1003,8 +1005,8 @@
;; Same applies for arithmetic shift right.
(define_expand "ashrqi3"
- [(set (match_operand:QI 0 "general_operand" "=r")
- (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "g")))]
""
"
@@ -1029,8 +1031,8 @@
;; HImode arithmetic shift right.
(define_expand "ashrhi3"
- [(set (match_operand:HI 0 "general_operand" "=r")
- (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "g")))]
""
"
@@ -1045,17 +1047,11 @@
(match_operand:QI 2 "immediate_operand" "L")))]
""
"*
- {
- rtx new_opnds[2];
- int amount = INTVAL(operands[2]);
- if (amount <= 16)
+ if (INTVAL (operands[2]) <= 16)
return \"dsra r%0,%2\";
- output_asm_insn(\"dsra r%0,16 ; ashrhi3 shiftcount > 16\",operands);
- new_opnds[0] = gen_rtx (REG, QImode, REGNO(operands[0]) + 1);
- new_opnds[1] = gen_rtx (CONST_INT, VOIDmode, amount - 16);
- output_asm_insn(\"sra r%0,%1\",new_opnds);
- return \";\";
- } ")
+ output_asm_insn (\"dsra r%0,16 ; ashrhi3 shiftcount > 16\", operands);
+ return \"sra r%d0,%w2\";
+ ")
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1109,7 +1105,7 @@
;********************
;; Bit field instructions, general cases.
-;; "o,d" constraint causes a nonoffsetable memref to match the "o"
+;; "o,d" constraint causes a nonoffsettable memref to match the "o"
;; so that its address is reloaded.
;; (define_insn "extv" ...
@@ -1142,7 +1138,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "* return (char *)branch_or_jump(\"ez\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"ez\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn "bne"
@@ -1152,7 +1148,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "* return (char *)branch_or_jump(\"nz\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"nz\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn "bgt"
@@ -1162,7 +1158,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "* return (char *)branch_or_jump(\"gt\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"gt\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn "blt"
@@ -1172,7 +1168,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "* return (char *)branch_or_jump(\"lt\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"lt\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn "bge"
@@ -1182,7 +1178,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "* return (char *)branch_or_jump(\"ge\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"ge\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn "ble"
@@ -1192,7 +1188,7 @@
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "* return (char *)branch_or_jump(\"le\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"le\", CODE_LABEL_NUMBER (operands[0]));
")
@@ -1244,7 +1240,7 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "* return (char *)branch_or_jump(\"nz\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"nz\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn ""
@@ -1254,7 +1250,7 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "* return (char *)branch_or_jump(\"ez\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"ez\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn ""
@@ -1264,7 +1260,7 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "* return (char *)branch_or_jump(\"le\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"le\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn ""
@@ -1274,7 +1270,7 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "* return (char *)branch_or_jump(\"ge\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"ge\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn ""
@@ -1284,7 +1280,7 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "* return (char *)branch_or_jump(\"lt\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"lt\", CODE_LABEL_NUMBER (operands[0]));
")
(define_insn ""
@@ -1294,7 +1290,7 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
""
- "* return (char *)branch_or_jump(\"gt\",CODE_LABEL_NUMBER(operands[0]));
+ "* return branch_or_jump (\"gt\", CODE_LABEL_NUMBER (operands[0]));
")
diff --git a/gnu/usr.bin/gcc/config/1750a/ms1750.inc b/gnu/usr.bin/gcc/config/1750a/ms1750.inc
index da2f5a57871..cb41e95b649 100644
--- a/gnu/usr.bin/gcc/config/1750a/ms1750.inc
+++ b/gnu/usr.bin/gcc/config/1750a/ms1750.inc
@@ -112,3 +112,47 @@ HI SET `1` + 2
POPM R10,R13
ENDMACRO
+
+; Double Unsigned Compare Register with register
+
+ MACRO DUCR.M
+ PSHM R13,R14 ; R13 and R14 are assumed not to be input parameters
+LOW1 SET `1` + 1
+LOW2 SET `2` + 1
+ PSHM R`1`,R`LOW1`
+ PSHM R`2`,R`LOW2`
+ LR R13,R`LOW1`
+ LR R14,R`LOW2`
+ DSRL R`1`,1
+ DSRL R`2`,1
+ DCR R`1`,R`2`
+ BNE +6
+ ANDM R13,1
+ ANDM R14,1
+ CR R13,R14
+ POPM R`2`,R`LOW2`
+ POPM R`1`,R`LOW1`
+ POPM R13,R14
+ ENDMACRO
+
+
+; Double Unsigned Compare register with memory
+
+ MACRO DUC.M
+ PSHM R13,R14 ; R13 and R14 are assumed not to be input parameters
+LOW1 SET `1` + 1
+ PSHM R`1`,R`LOW1`
+ DL R13,`2`
+ DSRL R`1`,1
+ DSRL R13,1
+ DCR R`1`,R13
+ BNE +10 ; done, go pop the saved regs
+ DL R13,`2` ; interested in the *low* word (R14)
+ L R13,1,R15
+ ANDM R13,1
+ ANDM R14,1
+ CR R13,R14
+ POPM R`1`,R`LOW1`
+ POPM R13,R14
+ ENDMACRO
+
diff --git a/gnu/usr.bin/gcc/config/a29k/a29k.c b/gnu/usr.bin/gcc/config/a29k/a29k.c
index e30340b49ce..4b28bba00bd 100644
--- a/gnu/usr.bin/gcc/config/a29k/a29k.c
+++ b/gnu/usr.bin/gcc/config/a29k/a29k.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on AMD Am29000.
- Copyright (C) 1987, 88, 90-94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 90-94, 1995, 1997 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@nyu.edu)
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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -44,6 +44,10 @@ Boston, MA 02111-1307, USA. */
static int a29k_regstack_size;
+/* True if the current procedure has a call instruction. */
+
+static int a29k_makes_calls;
+
/* This points to the last insn of the insn prologue. It is set when
an insn without a filled delay slot is found near the start of the
function. */
@@ -1189,29 +1193,24 @@ print_operand (file, x, code)
/* This page contains routines to output function prolog and epilog code. */
-/* Output function prolog code to file FILE. Memory stack size is SIZE.
-
- Also sets register names for incoming arguments and frame pointer. */
+/* Compute the size of the register stack, and determine if there are any
+ call instructions. */
-void
-output_prolog (file, size)
- FILE *file;
- int size;
+static void
+compute_regstack_size ()
{
- int makes_calls = 0;
- int arg_count = 0;
- rtx insn;
int i;
- unsigned int tag_word;
+ rtx insn;
/* See if we make any calls. We need to set lr1 if so. */
+ a29k_makes_calls = 0;
for (insn = get_insns (); insn; insn = next_insn (insn))
if (GET_CODE (insn) == CALL_INSN
|| (GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == SEQUENCE
&& GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == CALL_INSN))
{
- makes_calls = 1;
+ a29k_makes_calls = 1;
break;
}
@@ -1223,21 +1222,24 @@ output_prolog (file, size)
a29k_regstack_size = i - (R_LR (0) - 1);
/* If calling routines, ensure we count lr0 & lr1. */
- if (makes_calls && a29k_regstack_size < 2)
+ if (a29k_makes_calls && a29k_regstack_size < 2)
a29k_regstack_size = 2;
/* Count frame pointer and align to 8 byte boundary (even number of
registers). */
a29k_regstack_size += frame_pointer_needed;
if (a29k_regstack_size & 1) a29k_regstack_size++;
+}
- /* See how many incoming arguments we have in registers. */
- for (i = R_AR (0); i < R_AR (16); i++)
- if (! fixed_regs[i])
- arg_count++;
+/* Sets register names for incoming arguments and frame pointer.
+ This can't be computed until after register allocation. */
- /* The argument count includes the caller's lr0 and lr1. */
- arg_count += 2;
+void
+a29k_compute_reg_names ()
+{
+ int i;
+
+ compute_regstack_size ();
/* Set the names and numbers of the frame pointer and incoming argument
registers. */
@@ -1263,6 +1265,27 @@ output_prolog (file, size)
a29k_debug_reg_map[i] = a29k_debug_reg_map[R_KR (i)];
a29k_debug_reg_map[R_KR (i)] = tem;
}
+}
+
+/* Output function prolog code to file FILE. Memory stack size is SIZE. */
+
+void
+output_prolog (file, size)
+ FILE *file;
+ int size;
+{
+ int i;
+ int arg_count = 0;
+ rtx insn;
+ unsigned int tag_word;
+
+ /* See how many incoming arguments we have in registers. */
+ for (i = R_AR (0); i < R_AR (16); i++)
+ if (! fixed_regs[i])
+ arg_count++;
+
+ /* The argument count includes the caller's lr0 and lr1. */
+ arg_count += 2;
/* Compute memory stack size. Add in number of bytes that the we should
push and pretend the caller did and the size of outgoing arguments.
@@ -1326,7 +1349,7 @@ output_prolog (file, size)
slot (this condition is equivalent to seeing if we have an insn that
needs delay slots before an insn that has a filled delay slot). */
a29k_last_prologue_insn = 0;
- if (makes_calls)
+ if (a29k_makes_calls)
{
i = (a29k_regstack_size + arg_count) * 4;
if (i >= 256)
diff --git a/gnu/usr.bin/gcc/config/a29k/a29k.h b/gnu/usr.bin/gcc/config/a29k/a29k.h
index 8a9cfd7c3d4..db6e378d252 100644
--- a/gnu/usr.bin/gcc/config/a29k/a29k.h
+++ b/gnu/usr.bin/gcc/config/a29k/a29k.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU.
- Copyright (C) 1988, 90-94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 90-96, 1997 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@nyu.edu)
This file is part of GNU CC.
@@ -780,7 +780,7 @@ extern struct rtx_def *a29k_get_reloaded_address ();
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
/* Same, but called for incoming args.
@@ -928,12 +928,15 @@ extern int a29k_compare_fp_p;
For the 29k, we need the prolog to contain one or two words prior to
the declaration of the function name. So just store away the name and
- write it as part of the prolog. */
+ write it as part of the prolog. This also computes the register names,
+ which can't be done until after register allocation, but must be done
+ before final_start_function is called. */
extern char *a29k_function_name;
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
- a29k_function_name = NAME;
+ a29k_function_name = NAME; \
+ a29k_compute_reg_names ();
/* This macro generates the assembly code for function entry.
FILE is a stdio stream to output the code to.
@@ -984,13 +987,18 @@ extern char *a29k_function_name;
On the 29k, we must be able to place it in a delay slot, it must
not use sp if the frame pointer cannot be eliminated, and it cannot
- use local regs if we need to push the register stack. */
+ use local regs if we need to push the register stack.
+ If this is a SET with a memory as source, it might load from
+ a stack slot, unless the address is constant. */
#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN,N) \
(get_attr_in_delay_slot (INSN) == IN_DELAY_SLOT_YES \
&& ! (frame_pointer_needed \
&& reg_mentioned_p (stack_pointer_rtx, PATTERN (INSN))) \
- && ! (needs_regstack_p () && uses_local_reg_p (PATTERN (INSN))))
+ && ! (needs_regstack_p () && uses_local_reg_p (PATTERN (INSN))) \
+ && (GET_CODE (PATTERN (INSN)) != SET \
+ || GET_CODE (SET_SRC (PATTERN (INSN))) != MEM \
+ || ! rtx_varies_p (XEXP (SET_SRC (PATTERN (INSN)), 0))))
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.
@@ -1272,9 +1280,10 @@ extern char *a29k_function_name;
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 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. */
+ and some other value for true. This is the value stored for true, which
+ is just the sign bit. */
-#define STORE_FLAG_VALUE 0x80000000
+#define STORE_FLAG_VALUE (-2147483647 - 1)
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
@@ -1446,7 +1455,7 @@ extern int a29k_debug_reg_map[];
/* This how to write an assembler directive to FILE to switch to
section NAME for DECL. */
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
fprintf (FILE, "\t.sect %s, bss\n\t.use %s\n", NAME, NAME)
/* This is how to output the definition of a user-level label named NAME,
@@ -1461,11 +1470,10 @@ extern int a29k_debug_reg_map[];
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs ("\t.global ", 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)
+#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. */
@@ -1544,10 +1552,9 @@ extern int a29k_debug_reg_map[];
fprintf (FILE, "\t.word L%d\n", VALUE)
/* This is how to output an element of a case-vector that is relative.
- (29k does not use such vectors,
- but we must define this macro anyway.) */
+ Don't define this if it is not supported. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort ()
+/* #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) */
/* This is how to output an assembler line
that says to advance the location counter
diff --git a/gnu/usr.bin/gcc/config/a29k/t-vx29k b/gnu/usr.bin/gcc/config/a29k/t-vx29k
index 6cf4d9f7b2a..293674efd4b 100644
--- a/gnu/usr.bin/gcc/config/a29k/t-vx29k
+++ b/gnu/usr.bin/gcc/config/a29k/t-vx29k
@@ -6,7 +6,7 @@ LIBGCC1_TEST =
# We don't want to put exit in libgcc.a for VxWorks, because VxWorks
# does not have _exit.
-LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) -g1 -Dexit=unused_exit
+TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit
LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
diff --git a/gnu/usr.bin/gcc/config/a29k/unix.h b/gnu/usr.bin/gcc/config/a29k/unix.h
index f299d10398f..f05f258e94e 100644
--- a/gnu/usr.bin/gcc/config/a29k/unix.h
+++ b/gnu/usr.bin/gcc/config/a29k/unix.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for AMD Am29000 CPU, Unix.
- Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -20,10 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This is mostly the same as a29k.h, except that we define unix instead of
- EPI and define unix-style machine names. */
-
-#include "a29k/a29k.h"
+/* We define unix instead of EPI and define unix-style machine names. */
/* Set our default target to be the 29050; that is the more interesting chip
for Unix systems. */
diff --git a/gnu/usr.bin/gcc/config/a29k/vx29k.h b/gnu/usr.bin/gcc/config/a29k/vx29k.h
index 914b10878e6..8739b1ba7e2 100644
--- a/gnu/usr.bin/gcc/config/a29k/vx29k.h
+++ b/gnu/usr.bin/gcc/config/a29k/vx29k.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Vxworks 29k version.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,13 +20,18 @@ Boston, MA 02111-1307, USA. */
/* This file just exists to give specs for the 29k running on VxWorks. */
-#include "a29k/a29k-udi.h"
-
/* Names to predefine in the preprocessor for this target machine. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-D_AM29K -D_AM29000 -Acpu(a29k) -Amachine(a29k) -D__vxworks -D__vxworks_5"
+/* Vxworks header files require that the macro CPU be set.
+ We could define it in CPP_PREDEFINES, but the value is (or will be)
+ dependent upon GCC options. */
+
+#undef CPP_SPEC
+#define CPP_SPEC "-DCPU=AM29200"
+
/* VxWorks does all the library stuff itself. */
#undef LIB_SPEC
diff --git a/gnu/usr.bin/gcc/config/alpha/config-nt.sed b/gnu/usr.bin/gcc/config/alpha/config-nt.sed
index a5027bc1882..62a85fbc286 100644
--- a/gnu/usr.bin/gcc/config/alpha/config-nt.sed
+++ b/gnu/usr.bin/gcc/config/alpha/config-nt.sed
@@ -18,11 +18,11 @@ out_object_file=alpha.obj
/^md_file/ c\
md_file=config/alpha/alpha.md
/^tm_file/ c\
-tm_file=config/alpha/winnt.h
+tm_file=config/alpha/alpha.h config/alpha/winnt.h
/^build_xm_file/ c\
-build_xm_file=config/alpha/xm-winnt.h
+build_xm_file=config/alpha/xm-alpha.h config/winnt/xm-winnt.h config/alpha/xm-winnt.h
/^host_xm_file/ c\
-host_xm_file=config/alpha/xm-winnt.h
+host_xm_file=config/alpha/xm-alpha.h config/winnt/xm-winnt.h config/alpha/xm-winnt.h
/^####target/ i\
CC = cl \
CLIB = libc.lib kernel32.lib \
diff --git a/gnu/usr.bin/gcc/config/alpha/osf12.h b/gnu/usr.bin/gcc/config/alpha/osf12.h
index fe9112c007a..87e21111f4d 100644
--- a/gnu/usr.bin/gcc/config/alpha/osf12.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/alpha/win-nt.h b/gnu/usr.bin/gcc/config/alpha/win-nt.h
index cb3d9eb2bd9..c831da482a4 100644
--- a/gnu/usr.bin/gcc/config/alpha/win-nt.h
+++ b/gnu/usr.bin/gcc/config/alpha/win-nt.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for DEC Alpha
running Windows/NT.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -20,11 +20,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. */
-/* Say this is Windows/NT for the other config files. */
-#define WINDOWS_NT 1
-
-#include "alpha/alpha.h"
-
/* Names to predefine in the preprocessor for this target machine. */
#undef CPP_PREDEFINES
@@ -46,6 +41,11 @@ Boston, MA 02111-1307, USA. */
#undef LONG_TYPE_SIZE
#define LONG_TYPE_SIZE 32
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
/* We can't do any debugging. */
#undef SDB_DEBUGGING_INFO
#undef DBX_DEBUGGING_INFO
diff --git a/gnu/usr.bin/gcc/config/alpha/xm-winnt.h b/gnu/usr.bin/gcc/config/alpha/xm-winnt.h
index 202aec3457d..2f2a5a8ea1c 100644
--- a/gnu/usr.bin/gcc/config/alpha/xm-winnt.h
+++ b/gnu/usr.bin/gcc/config/alpha/xm-winnt.h
@@ -1,5 +1,5 @@
/* Configuration for GNU compiler for an Alpha running Windows NT 3.x.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Douglas B. Rupp (drupp@cs.washington.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/xm-alpha.h"
-#include "winnt/xm-winnt.h"
-
#undef HOST_BITS_PER_LONG
#define HOST_BITS_PER_LONG 32
diff --git a/gnu/usr.bin/gcc/config/arm/arm.c b/gnu/usr.bin/gcc/config/arm/arm.c
index 4c392753805..5e12e8d30f6 100644
--- a/gnu/usr.bin/gcc/config/arm/arm.c
+++ b/gnu/usr.bin/gcc/config/arm/arm.c
@@ -1,7 +1,7 @@
/* Output routines for GCC for ARM/RISCiX.
- Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
- and Martin Simmons (@harleqn.co.uk).
+ and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk)
This file is part of GNU CC.
@@ -21,10 +21,9 @@ 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 <stdio.h>
#include <string.h>
-#include "assert.h"
-#include "config.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -45,11 +44,29 @@ Boston, MA 02111-1307, USA. */
/* Some function declarations. */
extern FILE *asm_out_file;
-extern char *output_multi_immediate ();
-extern void arm_increase_location ();
-HOST_WIDE_INT int_log2 PROTO ((HOST_WIDE_INT));
-static int get_prologue_size PROTO ((void));
+static HOST_WIDE_INT int_log2 PROTO ((HOST_WIDE_INT));
+static char *output_multi_immediate PROTO ((rtx *, char *, char *, int,
+ HOST_WIDE_INT));
+static int arm_gen_constant PROTO ((enum rtx_code, enum machine_mode,
+ HOST_WIDE_INT, rtx, rtx, int, int));
+static int arm_naked_function_p PROTO ((tree));
+static void init_fpa_table PROTO ((void));
+static enum machine_mode select_dominance_cc_mode PROTO ((enum rtx_code, rtx,
+ rtx, HOST_WIDE_INT));
+static HOST_WIDE_INT add_constant PROTO ((rtx, enum machine_mode));
+static void dump_table PROTO ((rtx));
+static int fixit PROTO ((rtx, enum machine_mode, int));
+static rtx find_barrier PROTO ((rtx, int));
+static int broken_move PROTO ((rtx));
+static char *fp_const_from_val PROTO ((REAL_VALUE_TYPE *));
+static int eliminate_lr2ip PROTO ((rtx *));
+static char *shift_op PROTO ((rtx, HOST_WIDE_INT *));
+static int pattern_really_clobbers_lr PROTO ((rtx));
+static int function_really_clobbers_lr PROTO ((rtx));
+static void emit_multi_reg_push PROTO ((int));
+static void emit_sfm PROTO ((int, int));
+static enum arm_cond_code get_arm_condition_code PROTO ((rtx));
/* Define the information needed to generate branch insns. This is
stored from the compare operation. */
@@ -60,9 +77,27 @@ int arm_compare_fp;
/* What type of cpu are we compiling for? */
enum processor_type arm_cpu;
-/* What type of floating point are we compiling for? */
+/* What type of floating point are we tuning for? */
enum floating_point_type arm_fpu;
+/* What type of floating point instructions are available? */
+enum floating_point_type arm_fpu_arch;
+
+/* What program mode is the cpu running in? 26-bit mode or 32-bit mode */
+enum prog_mode_type arm_prgmode;
+
+/* Set by the -mfp=... option */
+char *target_fp_name = NULL;
+
+/* Nonzero if this is an "M" variant of the processor. */
+int arm_fast_multiply = 0;
+
+/* Nonzero if this chip supports the ARM Architecture 4 extensions */
+int arm_arch4 = 0;
+
+/* Set to the features we should tune the code for (multiply speed etc). */
+int tune_flags = 0;
+
/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
must report the mode of the memory reference from PRINT_OPERAND to
PRINT_OPERAND_ADDRESS. */
@@ -71,6 +106,9 @@ enum machine_mode output_memory_reference_mode;
/* Nonzero if the prologue must setup `fp'. */
int current_function_anonymous_args;
+/* The register number to be used for the PIC offset register. */
+int arm_pic_register = 9;
+
/* Location counter of .text segment. */
int arm_text_location = 0;
@@ -78,27 +116,16 @@ int arm_text_location = 0;
but all of these can be `put after' return insns */
int lr_save_eliminated;
-/* A hash table is used to store text segment labels and their associated
- offset from the start of the text segment. */
-struct label_offset
-{
- char *name;
- int offset;
- struct label_offset *cdr;
-};
-
-#define LABEL_HASH_SIZE 257
-
-static struct label_offset *offset_table[LABEL_HASH_SIZE];
-
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
static int return_used_this_function;
+static int arm_constant_limit = 3;
+
/* For an explanation of these variables, see final_prescan_insn below. */
int arm_ccfsm_state;
-int arm_current_cc;
+enum arm_cond_code arm_current_cc;
rtx arm_target_insn;
int arm_target_label;
@@ -109,8 +136,236 @@ char *arm_condition_codes[] =
"hi", "ls", "ge", "lt", "gt", "le", "al", "nv"
};
-#define ARM_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
+static enum arm_cond_code get_arm_condition_code ();
+
+/* Initialization code */
+
+struct arm_cpu_select arm_select[4] =
+{
+ /* switch name, tune arch */
+ { (char *)0, "--with-cpu=", 1, 1 },
+ { (char *)0, "-mcpu=", 1, 1 },
+ { (char *)0, "-march=", 0, 1 },
+ { (char *)0, "-mtune=", 1, 0 },
+};
+
+#define FL_CO_PROC 0x01 /* Has external co-processor bus */
+#define FL_FAST_MULT 0x02 /* Fast multiply */
+#define FL_MODE26 0x04 /* 26-bit mode support */
+#define FL_MODE32 0x08 /* 32-bit mode support */
+#define FL_ARCH4 0x10 /* Architecture rel 4 */
+#define FL_THUMB 0x20 /* Thumb aware */
+
+struct processors
+{
+ char *name;
+ enum processor_type type;
+ unsigned int flags;
+};
+
+/* Not all of these give usefully different compilation alternatives,
+ but there is no simple way of generalizing them. */
+static struct processors all_procs[] =
+{
+ {"arm2", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26},
+ {"arm250", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26},
+ {"arm3", PROCESSOR_ARM2, FL_CO_PROC | FL_MODE26},
+ {"arm6", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26},
+ {"arm600", PROCESSOR_ARM6, FL_CO_PROC | FL_MODE32 | FL_MODE26},
+ {"arm610", PROCESSOR_ARM6, FL_MODE32 | FL_MODE26},
+ {"arm7", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
+ /* arm7m doesn't exist on its own, only in conjunction with D, (and I), but
+ those don't alter the code, so it is sometimes known as the arm7m */
+ {"arm7m", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
+ | FL_MODE26)},
+ {"arm7dm", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
+ | FL_MODE26)},
+ {"arm7dmi", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
+ | FL_MODE26)},
+ {"arm700", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
+ {"arm710", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26},
+ {"arm7100", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26},
+ {"arm7500", PROCESSOR_ARM7, FL_MODE32 | FL_MODE26},
+ /* Doesn't really have an external co-proc, but does have embedded fpu */
+ {"arm7500fe", PROCESSOR_ARM7, FL_CO_PROC | FL_MODE32 | FL_MODE26},
+ {"arm7tdmi", PROCESSOR_ARM7, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
+ | FL_ARCH4 | FL_THUMB)},
+ {"arm8", PROCESSOR_ARM8, (FL_FAST_MULT | FL_MODE32 | FL_MODE26
+ | FL_ARCH4)},
+ {"arm810", PROCESSOR_ARM8, (FL_FAST_MULT | FL_MODE32 | FL_MODE26
+ | FL_ARCH4)},
+ {"strongarm", PROCESSOR_STARM, (FL_FAST_MULT | FL_MODE32 | FL_MODE26
+ | FL_ARCH4)},
+ {"strongarm110", PROCESSOR_STARM, (FL_FAST_MULT | FL_MODE32 | FL_MODE26
+ | FL_ARCH4)},
+ {"armv2", PROCESSOR_NONE, FL_CO_PROC | FL_MODE26},
+ {"armv2a", PROCESSOR_NONE, FL_CO_PROC | FL_MODE26},
+ {"armv3", PROCESSOR_NONE, FL_CO_PROC | FL_MODE32 | FL_MODE26},
+ {"armv3m", PROCESSOR_NONE, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
+ | FL_MODE26)},
+ {"armv4", PROCESSOR_NONE, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
+ | FL_MODE26 | FL_ARCH4)},
+ /* Strictly, FL_MODE26 is a permitted option for v4t, but there are no
+ implementations that support it, so we will leave it out for now. */
+ {"armv4t", PROCESSOR_NONE, (FL_CO_PROC | FL_FAST_MULT | FL_MODE32
+ | FL_ARCH4)},
+ {NULL, 0, 0}
+};
+
+/* Fix up any incompatible options that the user has specified.
+ This has now turned into a maze. */
+void
+arm_override_options ()
+{
+ int arm_thumb_aware = 0;
+ int flags = 0;
+ int i;
+ struct arm_cpu_select *ptr;
+ static struct cpu_default {
+ int cpu;
+ char *name;
+ } cpu_defaults[] = {
+ { TARGET_CPU_arm2, "arm2" },
+ { TARGET_CPU_arm6, "arm6" },
+ { TARGET_CPU_arm610, "arm610" },
+ { TARGET_CPU_arm7dm, "arm7dm" },
+ { TARGET_CPU_arm7500fe, "arm7500fe" },
+ { TARGET_CPU_arm7tdmi, "arm7tdmi" },
+ { TARGET_CPU_arm8, "arm8" },
+ { TARGET_CPU_arm810, "arm810" },
+ { TARGET_CPU_strongarm, "strongarm" },
+ { 0, 0 }
+ };
+ struct cpu_default *def;
+
+ /* Set the default. */
+ for (def = &cpu_defaults[0]; def->name; ++def)
+ if (def->cpu == TARGET_CPU_DEFAULT)
+ break;
+ if (! def->name)
+ abort ();
+
+ arm_select[0].string = def->name;
+
+ for (i = 0; i < sizeof (arm_select) / sizeof (arm_select[0]); i++)
+ {
+ ptr = &arm_select[i];
+ if (ptr->string != (char *)0 && ptr->string[0] != '\0')
+ {
+ struct processors *sel;
+
+ for (sel = all_procs; sel->name != NULL; sel++)
+ if (! strcmp (ptr->string, sel->name))
+ {
+ /* -march= is the only flag that can take an architecture
+ type, so if we match when the tune bit is set, the
+ option was invalid. */
+ if (ptr->set_tune_p)
+ {
+ if (sel->type == PROCESSOR_NONE)
+ continue; /* Its an architecture, not a cpu */
+
+ arm_cpu = sel->type;
+ tune_flags = sel->flags;
+ }
+
+ if (ptr->set_arch_p)
+ flags = sel->flags;
+
+ break;
+ }
+
+ if (sel->name == NULL)
+ error ("bad value (%s) for %s switch", ptr->string, ptr->name);
+ }
+ }
+
+ if (write_symbols != NO_DEBUG && flag_omit_frame_pointer)
+ warning ("-g with -fomit-frame-pointer may not give sensible debugging");
+
+ if (TARGET_POKE_FUNCTION_NAME)
+ target_flags |= ARM_FLAG_APCS_FRAME;
+
+ if (TARGET_6)
+ warning ("Option '-m6' deprecated. Use: '-mapcs-32' or -mcpu=<proc>");
+
+ if (TARGET_3)
+ warning ("Option '-m3' deprecated. Use: '-mapcs-26' or -mcpu=<proc>");
+
+ if (TARGET_APCS_REENT && flag_pic)
+ fatal ("-fpic and -mapcs-reent are incompatible");
+
+ if (TARGET_APCS_REENT)
+ warning ("APCS reentrant code not supported.");
+
+ /* If stack checking is disabled, we can use r10 as the PIC register,
+ which keeps r9 available. */
+ if (flag_pic && ! TARGET_APCS_STACK)
+ arm_pic_register = 10;
+
+ /* Well, I'm about to have a go, but pic is NOT going to be compatible
+ with APCS reentrancy, since that requires too much support in the
+ assembler and linker, and the ARMASM assembler seems to lack some
+ required directives. */
+ if (flag_pic)
+ warning ("Position independent code not supported. Ignored");
+
+ if (TARGET_APCS_FLOAT)
+ warning ("Passing floating point arguments in fp regs not yet supported");
+
+ if (TARGET_APCS_STACK && ! TARGET_APCS)
+ {
+ warning ("-mapcs-stack-check incompatible with -mno-apcs-frame");
+ target_flags |= ARM_FLAG_APCS_FRAME;
+ }
+
+ /* Default is to tune for an FPA */
+ arm_fpu = FP_HARD;
+
+ /* Default value for floating point code... if no co-processor
+ bus, then schedule for emulated floating point. Otherwise,
+ assume the user has an FPA.
+ Note: this does not prevent use of floating point instructions,
+ -msoft-float does that. */
+ if (tune_flags & FL_CO_PROC == 0)
+ arm_fpu = FP_SOFT3;
+
+ arm_fast_multiply = (flags & FL_FAST_MULT) != 0;
+ arm_arch4 = (flags & FL_ARCH4) != 0;
+ arm_thumb_aware = (flags & FL_THUMB) != 0;
+
+ if (target_fp_name)
+ {
+ if (strcmp (target_fp_name, "2") == 0)
+ arm_fpu_arch = FP_SOFT2;
+ else if (strcmp (target_fp_name, "3") == 0)
+ arm_fpu_arch = FP_HARD;
+ else
+ fatal ("Invalid floating point emulation option: -mfpe=%s",
+ target_fp_name);
+ }
+ else
+ arm_fpu_arch = FP_DEFAULT;
+
+ if (TARGET_THUMB_INTERWORK && ! arm_thumb_aware)
+ {
+ warning ("This processor variant does not support Thumb interworking");
+ target_flags &= ~ARM_FLAG_THUMB;
+ }
+
+ if (TARGET_FPE && arm_fpu != FP_HARD)
+ arm_fpu = FP_SOFT2;
+
+ /* For arm2/3 there is no need to do any scheduling if there is only
+ a floating point emulator, or we are doing software floating-point. */
+ if ((TARGET_SOFT_FLOAT || arm_fpu != FP_HARD) && arm_cpu == PROCESSOR_ARM2)
+ flag_schedule_insns = flag_schedule_insns_after_reload = 0;
+
+ arm_prog_mode = TARGET_APCS_32 ? PROG_MODE_PROG32 : PROG_MODE_PROG26;
+}
+
+
/* Return 1 if it is possible to return using a single instruction */
int
@@ -120,15 +375,27 @@ use_return_insn ()
if (!reload_completed ||current_function_pretend_args_size
|| current_function_anonymous_args
- || (get_frame_size () && !(TARGET_APCS || frame_pointer_needed)))
+ || ((get_frame_size () + current_function_outgoing_args_size != 0)
+ && !(TARGET_APCS || frame_pointer_needed)))
return 0;
+ /* Can't be done if interworking with Thumb, and any registers have been
+ stacked */
+ if (TARGET_THUMB_INTERWORK)
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ return 0;
+
/* Can't be done if any of the FPU regs are pushed, since this also
requires an insn */
- for (regno = 20; regno < 24; regno++)
- if (regs_ever_live[regno])
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
return 0;
+ /* If a function is naked, don't use the "return" insn. */
+ if (arm_naked_function_p (current_function_decl))
+ return 0;
+
return 1;
}
@@ -140,6 +407,13 @@ const_ok_for_arm (i)
{
unsigned HOST_WIDE_INT mask = ~0xFF;
+ /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must
+ be all zero, or all one. */
+ if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0
+ && ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff)
+ != (((HOST_WIDE_INT) -1) & ~(unsigned HOST_WIDE_INT) 0xffffffff)))
+ return FALSE;
+
/* Fast return for 0 and powers of 2 */
if ((i & (i - 1)) == 0)
return TRUE;
@@ -191,7 +465,8 @@ const_ok_for_op (i, code, mode)
VAL is the integer to operate on;
SOURCE is the other operand (a register, or a null-pointer for SET);
SUBTARGETS means it is safe to create scratch registers if that will
- either produce a simpler sequence, or we will want to cse the values. */
+ either produce a simpler sequence, or we will want to cse the values.
+ Return value is the number of insns emitted. */
int
arm_split_constant (code, mode, val, target, source, subtargets)
@@ -202,6 +477,55 @@ arm_split_constant (code, mode, val, target, source, subtargets)
rtx source;
int subtargets;
{
+ if (subtargets || code == SET
+ || (GET_CODE (target) == REG && GET_CODE (source) == REG
+ && REGNO (target) != REGNO (source)))
+ {
+ rtx temp;
+
+ if (arm_gen_constant (code, mode, val, target, source, 1, 0)
+ > arm_constant_limit + (code != SET))
+ {
+ if (code == SET)
+ {
+ /* Currently SET is the only monadic value for CODE, all
+ the rest are diadic. */
+ emit_insn (gen_rtx (SET, VOIDmode, target, GEN_INT (val)));
+ return 1;
+ }
+ else
+ {
+ rtx temp = subtargets ? gen_reg_rtx (mode) : target;
+
+ emit_insn (gen_rtx (SET, VOIDmode, temp, GEN_INT (val)));
+ /* For MINUS, the value is subtracted from, since we never
+ have subtraction of a constant. */
+ if (code == MINUS)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (code, mode, temp, source)));
+ else
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (code, mode, source, temp)));
+ return 2;
+ }
+ }
+ }
+
+ return arm_gen_constant (code, mode, val, target, source, subtargets, 1);
+}
+
+/* As above, but extra parameter GENERATE which, if clear, suppresses
+ RTL generation. */
+int
+arm_gen_constant (code, mode, val, target, source, subtargets, generate)
+ enum rtx_code code;
+ enum machine_mode mode;
+ HOST_WIDE_INT val;
+ rtx target;
+ rtx source;
+ int subtargets;
+ int generate;
+{
int can_add = 0;
int can_invert = 0;
int can_negate = 0;
@@ -237,15 +561,17 @@ arm_split_constant (code, mode, val, target, source, subtargets)
case IOR:
if (remainder == 0xffffffff)
{
- emit_insn (gen_rtx (SET, VOIDmode, target,
- GEN_INT (ARM_SIGN_EXTEND (val))));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ GEN_INT (ARM_SIGN_EXTEND (val))));
return 1;
}
if (remainder == 0)
{
if (reload_completed && rtx_equal_p (target, source))
return 0;
- emit_insn (gen_rtx (SET, VOIDmode, target, source));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target, source));
return 1;
}
break;
@@ -253,14 +579,16 @@ arm_split_constant (code, mode, val, target, source, subtargets)
case AND:
if (remainder == 0)
{
- emit_insn (gen_rtx (SET, VOIDmode, target, const0_rtx));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target, const0_rtx));
return 1;
}
if (remainder == 0xffffffff)
{
if (reload_completed && rtx_equal_p (target, source))
return 0;
- emit_insn (gen_rtx (SET, VOIDmode, target, source));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target, source));
return 1;
}
can_invert = 1;
@@ -271,13 +599,15 @@ arm_split_constant (code, mode, val, target, source, subtargets)
{
if (reload_completed && rtx_equal_p (target, source))
return 0;
- emit_insn (gen_rtx (SET, VOIDmode, target, source));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target, source));
return 1;
}
if (remainder == 0xffffffff)
{
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (NOT, mode, source)));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (NOT, mode, source)));
return 1;
}
@@ -289,14 +619,16 @@ arm_split_constant (code, mode, val, target, source, subtargets)
passed as (source + (-val)). */
if (remainder == 0)
{
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (NEG, mode, source)));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (NEG, mode, source)));
return 1;
}
if (const_ok_for_arm (val))
{
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (MINUS, mode, GEN_INT (val), source)));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (MINUS, mode, GEN_INT (val), source)));
return 1;
}
can_negate = 1;
@@ -312,9 +644,11 @@ arm_split_constant (code, mode, val, target, source, subtargets)
|| (can_negate_initial && const_ok_for_arm (-val))
|| (can_invert && const_ok_for_arm (~val)))
{
- emit_insn (gen_rtx (SET, VOIDmode, target,
- (source ? gen_rtx (code, mode, source,
- GEN_INT (val)) : GEN_INT (val))));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ (source ? gen_rtx (code, mode, source,
+ GEN_INT (val))
+ : GEN_INT (val))));
return 1;
}
@@ -366,10 +700,14 @@ arm_split_constant (code, mode, val, target, source, subtargets)
(temp1 = ARM_SIGN_EXTEND (remainder
<< (set_sign_bit_copies - 1))))
{
- new_src = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx (SET, VOIDmode, new_src, GEN_INT (temp1)));
- emit_insn (gen_ashrsi3 (target, new_src,
- GEN_INT (set_sign_bit_copies - 1)));
+ if (generate)
+ {
+ new_src = subtargets ? gen_reg_rtx (mode) : target;
+ emit_insn (gen_rtx (SET, VOIDmode, new_src,
+ GEN_INT (temp1)));
+ emit_insn (gen_ashrsi3 (target, new_src,
+ GEN_INT (set_sign_bit_copies - 1)));
+ }
return 2;
}
/* For an inverted constant, we will need to set the low bits,
@@ -377,10 +715,14 @@ arm_split_constant (code, mode, val, target, source, subtargets)
temp1 |= (1 << (set_sign_bit_copies - 1)) - 1;
if (const_ok_for_arm (~temp1))
{
- new_src = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx (SET, VOIDmode, new_src, GEN_INT (temp1)));
- emit_insn (gen_ashrsi3 (target, new_src,
- GEN_INT (set_sign_bit_copies - 1)));
+ if (generate)
+ {
+ new_src = subtargets ? gen_reg_rtx (mode) : target;
+ emit_insn (gen_rtx (SET, VOIDmode, new_src,
+ GEN_INT (temp1)));
+ emit_insn (gen_ashrsi3 (target, new_src,
+ GEN_INT (set_sign_bit_copies - 1)));
+ }
return 2;
}
}
@@ -401,18 +743,18 @@ arm_split_constant (code, mode, val, target, source, subtargets)
if ((((temp2 | (temp2 << i)) & 0xffffffff) == remainder)
&& ! const_ok_for_arm (temp2))
{
- insns
- = arm_split_constant (code, mode, temp2,
- (new_src
- = subtargets ? gen_reg_rtx (mode)
- : target),
- source, subtargets);
+ insns = arm_gen_constant (code, mode, temp2,
+ new_src = (subtargets
+ ? gen_reg_rtx (mode)
+ : target),
+ source, subtargets, generate);
source = new_src;
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (IOR, mode,
- gen_rtx (ASHIFT, mode, source,
- GEN_INT (i)),
- source)));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (IOR, mode,
+ gen_rtx (ASHIFT, mode, source,
+ GEN_INT (i)),
+ source)));
return insns + 1;
}
}
@@ -423,18 +765,18 @@ arm_split_constant (code, mode, val, target, source, subtargets)
if (((temp1 | (temp1 >> i)) == remainder)
&& ! const_ok_for_arm (temp1))
{
- insns
- = arm_split_constant (code, mode, temp1,
- (new_src
- = subtargets ? gen_reg_rtx (mode)
- : target),
- source, subtargets);
+ insns = arm_gen_constant (code, mode, temp1,
+ new_src = (subtargets
+ ? gen_reg_rtx (mode)
+ : target),
+ source, subtargets, generate);
source = new_src;
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (IOR, mode,
- gen_rtx (LSHIFTRT, mode, source,
- GEN_INT (i)),
- source)));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (IOR, mode,
+ gen_rtx (LSHIFTRT, mode,
+ source, GEN_INT (i)),
+ source)));
return insns + 1;
}
}
@@ -443,20 +785,22 @@ arm_split_constant (code, mode, val, target, source, subtargets)
case IOR:
case XOR:
- /* If we have IOR or XOR, and the inverse of the constant can be loaded
- in a single instruction, and we can find a temporary to put it in,
+ /* If we have IOR or XOR, and the constant can be loaded in a
+ single instruction, and we can find a temporary to put it in,
then this can be done in two instructions instead of 3-4. */
if (subtargets
|| (reload_completed && ! reg_mentioned_p (target, source)))
{
if (const_ok_for_arm (ARM_SIGN_EXTEND (~ val)))
{
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
+ if (generate)
+ {
+ rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx (SET, VOIDmode, sub,
- GEN_INT (ARM_SIGN_EXTEND (~ val))));
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (code, mode, source, sub)));
+ emit_insn (gen_rtx (SET, VOIDmode, sub, GEN_INT (val)));
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (code, mode, source, sub)));
+ }
return 2;
}
}
@@ -467,49 +811,59 @@ arm_split_constant (code, mode, val, target, source, subtargets)
if (set_sign_bit_copies > 8
&& (val & (-1 << (32 - set_sign_bit_copies))) == val)
{
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- rtx shift = GEN_INT (set_sign_bit_copies);
-
- emit_insn (gen_rtx (SET, VOIDmode, sub,
- gen_rtx (NOT, mode,
- gen_rtx (ASHIFT, mode, source,
- shift))));
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (NOT, mode,
- gen_rtx (LSHIFTRT, mode, sub,
- shift))));
+ if (generate)
+ {
+ rtx sub = subtargets ? gen_reg_rtx (mode) : target;
+ rtx shift = GEN_INT (set_sign_bit_copies);
+
+ emit_insn (gen_rtx (SET, VOIDmode, sub,
+ gen_rtx (NOT, mode,
+ gen_rtx (ASHIFT, mode, source,
+ shift))));
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (NOT, mode,
+ gen_rtx (LSHIFTRT, mode, sub,
+ shift))));
+ }
return 2;
}
if (set_zero_bit_copies > 8
&& (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder)
{
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- rtx shift = GEN_INT (set_zero_bit_copies);
-
- emit_insn (gen_rtx (SET, VOIDmode, sub,
- gen_rtx (NOT, mode,
- gen_rtx (LSHIFTRT, mode, source,
- shift))));
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (NOT, mode,
- gen_rtx (ASHIFT, mode, sub,
- shift))));
+ if (generate)
+ {
+ rtx sub = subtargets ? gen_reg_rtx (mode) : target;
+ rtx shift = GEN_INT (set_zero_bit_copies);
+
+ emit_insn (gen_rtx (SET, VOIDmode, sub,
+ gen_rtx (NOT, mode,
+ gen_rtx (LSHIFTRT, mode, source,
+ shift))));
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (NOT, mode,
+ gen_rtx (ASHIFT, mode, sub,
+ shift))));
+ }
return 2;
}
if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~ val)))
{
- rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx (SET, VOIDmode, sub,
- gen_rtx (NOT, mode, source)));
- source = sub;
- if (subtargets)
- sub = gen_reg_rtx (mode);
- emit_insn (gen_rtx (SET, VOIDmode, sub,
- gen_rtx (AND, mode, source, GEN_INT (temp1))));
- emit_insn (gen_rtx (SET, VOIDmode, target,
- gen_rtx (NOT, mode, sub)));
+ if (generate)
+ {
+ rtx sub = subtargets ? gen_reg_rtx (mode) : target;
+ emit_insn (gen_rtx (SET, VOIDmode, sub,
+ gen_rtx (NOT, mode, source)));
+ source = sub;
+ if (subtargets)
+ sub = gen_reg_rtx (mode);
+ emit_insn (gen_rtx (SET, VOIDmode, sub,
+ gen_rtx (AND, mode, source,
+ GEN_INT (temp1))));
+ emit_insn (gen_rtx (SET, VOIDmode, target,
+ gen_rtx (NOT, mode, sub)));
+ }
return 3;
}
break;
@@ -522,19 +876,30 @@ arm_split_constant (code, mode, val, target, source, subtargets)
<< (32 - clear_sign_bit_copies))
& 0xffffffff);
rtx new_source;
- rtx shift = GEN_INT (clear_sign_bit_copies);
+ rtx shift;
if ((remainder | shift_mask) != 0xffffffff)
{
+ if (generate)
+ {
+ new_source = subtargets ? gen_reg_rtx (mode) : target;
+ insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ new_source, source, subtargets, 1);
+ source = new_source;
+ }
+ else
+ insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ new_source, source, subtargets, 0);
+ }
+
+ if (generate)
+ {
+ shift = GEN_INT (clear_sign_bit_copies);
new_source = subtargets ? gen_reg_rtx (mode) : target;
- insns = arm_split_constant (AND, mode, remainder | shift_mask,
- new_source, source, subtargets);
- source = new_source;
+ emit_insn (gen_ashlsi3 (new_source, source, shift));
+ emit_insn (gen_lshrsi3 (target, new_source, shift));
}
- new_source = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_ashlsi3 (new_source, source, shift));
- emit_insn (gen_lshrsi3 (target, new_source, shift));
return insns + 2;
}
@@ -542,19 +907,30 @@ arm_split_constant (code, mode, val, target, source, subtargets)
{
HOST_WIDE_INT shift_mask = (1 << clear_zero_bit_copies) - 1;
rtx new_source;
- rtx shift = GEN_INT (clear_zero_bit_copies);
+ rtx shift;
if ((remainder | shift_mask) != 0xffffffff)
{
+ if (generate)
+ {
+ new_source = subtargets ? gen_reg_rtx (mode) : target;
+ insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ new_source, source, subtargets, 1);
+ source = new_source;
+ }
+ else
+ insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ new_source, source, subtargets, 0);
+ }
+
+ if (generate)
+ {
+ shift = GEN_INT (clear_zero_bit_copies);
new_source = subtargets ? gen_reg_rtx (mode) : target;
- insns = arm_split_constant (AND, mode, remainder | shift_mask,
- new_source, source, subtargets);
- source = new_source;
+ emit_insn (gen_lshrsi3 (new_source, source, shift));
+ emit_insn (gen_ashlsi3 (target, new_source, shift));
}
- new_source = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_lshrsi3 (new_source, source, shift));
- emit_insn (gen_ashlsi3 (target, new_source, shift));
return insns + 2;
}
@@ -629,32 +1005,40 @@ arm_split_constant (code, mode, val, target, source, subtargets)
if (code == SET)
{
- emit_insn (gen_rtx (SET, VOIDmode,
- new_src = (subtargets ? gen_reg_rtx (mode)
- : target),
- GEN_INT (can_invert ? ~temp1 : temp1)));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode,
+ new_src = (subtargets
+ ? gen_reg_rtx (mode)
+ : target),
+ GEN_INT (can_invert ? ~temp1 : temp1)));
can_invert = 0;
code = PLUS;
}
else if (code == MINUS)
{
- emit_insn (gen_rtx (SET, VOIDmode,
- new_src = (subtargets ? gen_reg_rtx (mode)
- : target),
- gen_rtx (code, mode, GEN_INT (temp1),
- source)));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode,
+ new_src = (subtargets
+ ? gen_reg_rtx (mode)
+ : target),
+ gen_rtx (code, mode, GEN_INT (temp1),
+ source)));
code = PLUS;
}
else
{
- emit_insn (gen_rtx (SET, VOIDmode,
- new_src = remainder ? (subtargets
- ? gen_reg_rtx (mode)
- : target) : target,
- gen_rtx (code, mode, source,
- GEN_INT (can_invert ? ~temp1
- : (can_negate
- ? -temp1 : temp1)))));
+ if (generate)
+ emit_insn (gen_rtx (SET, VOIDmode,
+ new_src = (remainder
+ ? (subtargets
+ ? gen_reg_rtx (mode)
+ : target)
+ : target),
+ gen_rtx (code, mode, source,
+ GEN_INT (can_invert ? ~temp1
+ : (can_negate
+ ? -temp1
+ : temp1)))));
}
insns++;
@@ -667,6 +1051,284 @@ arm_split_constant (code, mode, val, target, source, subtargets)
return insns;
}
+/* Canonicalize a comparison so that we are more likely to recognize it.
+ This can be done for a few constant compares, where we can make the
+ immediate value easier to load. */
+enum rtx_code
+arm_canonicalize_comparison (code, op1)
+ enum rtx_code code;
+ rtx *op1;
+{
+ HOST_WIDE_INT i = INTVAL (*op1);
+
+ switch (code)
+ {
+ case EQ:
+ case NE:
+ return code;
+
+ case GT:
+ case LE:
+ if (i != (1 << (HOST_BITS_PER_WIDE_INT - 1) - 1)
+ && (const_ok_for_arm (i+1) || const_ok_for_arm (- (i+1))))
+ {
+ *op1 = GEN_INT (i+1);
+ return code == GT ? GE : LT;
+ }
+ break;
+
+ case GE:
+ case LT:
+ if (i != (1 << (HOST_BITS_PER_WIDE_INT - 1))
+ && (const_ok_for_arm (i-1) || const_ok_for_arm (- (i-1))))
+ {
+ *op1 = GEN_INT (i-1);
+ return code == GE ? GT : LE;
+ }
+ break;
+
+ case GTU:
+ case LEU:
+ if (i != ~0
+ && (const_ok_for_arm (i+1) || const_ok_for_arm (- (i+1))))
+ {
+ *op1 = GEN_INT (i + 1);
+ return code == GTU ? GEU : LTU;
+ }
+ break;
+
+ case GEU:
+ case LTU:
+ if (i != 0
+ && (const_ok_for_arm (i - 1) || const_ok_for_arm (- (i - 1))))
+ {
+ *op1 = GEN_INT (i - 1);
+ return code == GEU ? GTU : LEU;
+ }
+ break;
+
+ default:
+ abort ();
+ }
+
+ return code;
+}
+
+
+/* Handle aggregates that are not laid out in a BLKmode element.
+ This is a sub-element of RETURN_IN_MEMORY. */
+int
+arm_return_in_memory (type)
+ tree type;
+{
+ if (TREE_CODE (type) == RECORD_TYPE)
+ {
+ tree field;
+
+ /* For a struct, we can return in a register if every element was a
+ bit-field. */
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) != FIELD_DECL
+ || ! DECL_BIT_FIELD_TYPE (field))
+ return 1;
+
+ return 0;
+ }
+ else if (TREE_CODE (type) == UNION_TYPE)
+ {
+ tree field;
+
+ /* Unions can be returned in registers if every element is
+ integral, or can be returned in an integer register. */
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL
+ || (AGGREGATE_TYPE_P (TREE_TYPE (field))
+ && RETURN_IN_MEMORY (TREE_TYPE (field)))
+ || FLOAT_TYPE_P (TREE_TYPE (field)))
+ return 1;
+ }
+ return 0;
+ }
+ /* XXX Not sure what should be done for other aggregates, so put them in
+ memory. */
+ return 1;
+}
+
+int
+legitimate_pic_operand_p (x)
+ rtx x;
+{
+ if (CONSTANT_P (x) && flag_pic
+ && (GET_CODE (x) == SYMBOL_REF
+ || (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)))
+ return 0;
+
+ return 1;
+}
+
+rtx
+legitimize_pic_address (orig, mode, reg)
+ rtx orig;
+ enum machine_mode mode;
+ rtx reg;
+{
+ if (GET_CODE (orig) == SYMBOL_REF)
+ {
+ rtx pic_ref, address;
+ rtx insn;
+ int subregs = 0;
+
+ if (reg == 0)
+ {
+ if (reload_in_progress || reload_completed)
+ abort ();
+ else
+ reg = gen_reg_rtx (Pmode);
+
+ subregs = 1;
+ }
+
+#ifdef AOF_ASSEMBLER
+ /* The AOF assembler can generate relocations for these directly, and
+ understands that the PIC register has to be added into the offset.
+ */
+ insn = emit_insn (gen_pic_load_addr_based (reg, orig));
+#else
+ if (subregs)
+ address = gen_reg_rtx (Pmode);
+ else
+ address = reg;
+
+ emit_insn (gen_pic_load_addr (address, orig));
+
+ pic_ref = gen_rtx (MEM, Pmode,
+ gen_rtx (PLUS, Pmode, pic_offset_table_rtx, address));
+ RTX_UNCHANGING_P (pic_ref) = 1;
+ insn = emit_move_insn (reg, pic_ref);
+#endif
+ current_function_uses_pic_offset_table = 1;
+ /* 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)
+ {
+ /* The base register doesn't really matter, we only want to
+ test the index for the appropriate mode. */
+ GO_IF_LEGITIMATE_INDEX (mode, 0, offset, win);
+
+ if (! reload_in_progress && ! reload_completed)
+ offset = force_reg (Pmode, offset);
+ else
+ abort ();
+
+ win:
+ if (GET_CODE (offset) == CONST_INT)
+ return plus_constant_for_output (base, INTVAL (offset));
+ }
+
+ if (GET_MODE_SIZE (mode) > 4
+ && (GET_MODE_CLASS (mode) == MODE_INT
+ || TARGET_SOFT_FLOAT))
+ {
+ emit_insn (gen_addsi3 (reg, base, offset));
+ return reg;
+ }
+
+ return gen_rtx (PLUS, Pmode, base, offset);
+ }
+ else if (GET_CODE (orig) == LABEL_REF)
+ current_function_uses_pic_offset_table = 1;
+
+ return orig;
+}
+
+static rtx pic_rtx;
+
+int
+is_pic(x)
+ rtx x;
+{
+ if (x == pic_rtx)
+ return 1;
+ return 0;
+}
+
+void
+arm_finalize_pic ()
+{
+#ifndef AOF_ASSEMBLER
+ rtx l1, pic_tmp, pic_tmp2, seq;
+ rtx global_offset_table;
+
+ if (current_function_uses_pic_offset_table == 0)
+ return;
+
+ if (! flag_pic)
+ abort ();
+
+ start_sequence ();
+ l1 = gen_label_rtx ();
+
+ global_offset_table = gen_rtx (SYMBOL_REF, Pmode, "_GLOBAL_OFFSET_TABLE_");
+ /* The PC contains 'dot'+8, but the label L1 is on the next
+ instruction, so the offset is only 'dot'+4. */
+ pic_tmp = gen_rtx (CONST, VOIDmode,
+ gen_rtx (PLUS, Pmode,
+ gen_rtx (LABEL_REF, VOIDmode, l1),
+ GEN_INT (4)));
+ pic_tmp2 = gen_rtx (CONST, VOIDmode,
+ gen_rtx (PLUS, Pmode,
+ global_offset_table,
+ pc_rtx));
+
+ pic_rtx = gen_rtx (CONST, Pmode,
+ gen_rtx (MINUS, Pmode, pic_tmp2, pic_tmp));
+
+ emit_insn (gen_pic_load_addr (pic_offset_table_rtx, pic_rtx));
+ emit_jump_insn (gen_pic_add_dot_plus_eight(l1, pic_offset_table_rtx));
+ emit_label (l1);
+
+ seq = gen_sequence ();
+ end_sequence ();
+ emit_insn_after (seq, get_insns ());
+
+ /* Need to emit this whether or not we obey regdecls,
+ since setjmp/longjmp can cause life info to screw up. */
+ emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
+#endif /* AOF_ASSEMBLER */
+}
+
#define REG_OR_SUBREG_REG(X) \
(GET_CODE (X) == REG \
|| (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))
@@ -814,29 +1476,51 @@ arm_rtx_costs (x, code, outer_code)
return 8;
case MULT:
+ /* There is no point basing this on the tuning, since it is always the
+ fast variant if it exists at all */
+ if (arm_fast_multiply && mode == DImode
+ && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
+ && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
+ return 8;
+
if (GET_MODE_CLASS (mode) == MODE_FLOAT
|| mode == DImode)
return 30;
if (GET_CODE (XEXP (x, 1)) == CONST_INT)
{
- HOST_WIDE_INT i = INTVAL (XEXP (x, 1)) & 0xffffffff;
+ unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
+ & (unsigned HOST_WIDE_INT) 0xffffffff);
int add_cost = const_ok_for_arm (i) ? 4 : 8;
int j;
-
- /* This will need adjusting for ARM's with fast multiplies */
- for (j = 0; i && j < 32; j += 2)
+ /* Tune as appropriate */
+ int booth_unit_size = ((tune_flags & FL_FAST_MULT) ? 8 : 2);
+
+ for (j = 0; i && j < 32; j += booth_unit_size)
{
- i &= ~(3 << j);
+ i >>= booth_unit_size;
add_cost += 2;
}
return add_cost;
}
- return (30 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
+ return (((tune_flags & FL_FAST_MULT) ? 8 : 30)
+ + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
+ (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));
+ case TRUNCATE:
+ if (arm_fast_multiply && mode == SImode
+ && GET_CODE (XEXP (x, 0)) == LSHIFTRT
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
+ == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+ && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
+ return 8;
+ return 99;
+
case NEG:
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
return 4 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 6);
@@ -883,21 +1567,53 @@ arm_rtx_costs (x, code, outer_code)
return 99;
}
}
-
+
+int
+arm_adjust_cost (insn, link, dep, cost)
+ rtx insn;
+ rtx link;
+ rtx dep;
+ int cost;
+{
+ rtx i_pat, d_pat;
+
+ if ((i_pat = single_set (insn)) != NULL
+ && GET_CODE (SET_SRC (i_pat)) == MEM
+ && (d_pat = single_set (dep)) != NULL
+ && GET_CODE (SET_DEST (d_pat)) == MEM)
+ {
+ /* This is a load after a store, there is no conflict if the load reads
+ from a cached area. Assume that loads from the stack, and from the
+ constant pool are cached, and that others will miss. This is a
+ hack. */
+
+/* debug_rtx (insn);
+ debug_rtx (dep);
+ debug_rtx (link);
+ fprintf (stderr, "costs %d\n", cost); */
+
+ if (CONSTANT_POOL_ADDRESS_P (XEXP (SET_SRC (i_pat), 0))
+ || reg_mentioned_p (stack_pointer_rtx, XEXP (SET_SRC (i_pat), 0))
+ || reg_mentioned_p (frame_pointer_rtx, XEXP (SET_SRC (i_pat), 0))
+ || reg_mentioned_p (hard_frame_pointer_rtx,
+ XEXP (SET_SRC (i_pat), 0)))
+ {
+/* fprintf (stderr, "***** Now 1\n"); */
+ return 1;
+ }
+ }
+
+ return cost;
+}
+
/* This code has been fixed for cross compilation. */
static int fpa_consts_inited = 0;
char *strings_fpa[8] = {
- "0.0",
- "1.0",
- "2.0",
- "3.0",
- "4.0",
- "5.0",
- "0.5",
- "10.0"
- };
+ "0", "1", "2", "3",
+ "4", "5", "0.5", "10"
+};
static REAL_VALUE_TYPE values_fpa[8];
@@ -966,7 +1682,12 @@ neg_const_double_rtx_ok_for_fpu (x)
/* Predicates for `match_operand' and `match_operator'. */
/* s_register_operand is the same as register_operand, but it doesn't accept
- (SUBREG (MEM)...). */
+ (SUBREG (MEM)...).
+
+ This function exists because at the time it was put in it led to better
+ code. SUBREG(MEM) always needs a reload in the places where
+ s_register_operand is used, and this seemed to lead to excessive
+ reloading. */
int
s_register_operand (op, mode)
@@ -1073,6 +1794,70 @@ arm_not_operand (op, mode)
|| const_ok_for_arm (~INTVAL (op)))));
}
+/* Return TRUE if the operand is a memory reference which contains an
+ offsettable address. */
+int
+offsettable_memory_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ return (mode == GET_MODE (op)
+ && GET_CODE (op) == MEM
+ && offsettable_address_p (reload_completed | reload_in_progress,
+ mode, XEXP (op, 0)));
+}
+
+/* Return TRUE if the operand is a memory reference which is, or can be
+ made word aligned by adjusting the offset. */
+int
+alignable_memory_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ rtx reg;
+
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+
+ if (mode != GET_MODE (op) || GET_CODE (op) != MEM)
+ return 0;
+
+ op = XEXP (op, 0);
+
+ return ((GET_CODE (reg = op) == REG
+ || (GET_CODE (op) == SUBREG
+ && GET_CODE (reg = SUBREG_REG (op)) == REG)
+ || (GET_CODE (op) == PLUS
+ && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && (GET_CODE (reg = XEXP (op, 0)) == REG
+ || (GET_CODE (XEXP (op, 0)) == SUBREG
+ && GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG))))
+ && REGNO_POINTER_ALIGN (REGNO (reg)) >= 4);
+}
+
+/* Similar to s_register_operand, but does not allow hard integer
+ registers. */
+int
+f_register_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ if (GET_MODE (op) != mode && mode != VOIDmode)
+ return 0;
+
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ /* We don't consider registers whose class is NO_REGS
+ to be a register operand. */
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) == FPU_REGS));
+}
+
/* Return TRUE for valid operands for the rhs of an FPU instruction. */
int
@@ -1282,30 +2067,92 @@ cc_register (x, mode)
}
/* Return TRUE if this is the condition code register, if we aren't given
- a mode, accept any mode in class CC_MODE that is reversible */
+ a mode, accept any class CCmode register which indicates a dominance
+ expression. */
int
-reversible_cc_register (x, mode)
+dominant_cc_register (x, mode)
rtx x;
enum machine_mode mode;
{
if (mode == VOIDmode)
{
mode = GET_MODE (x);
- if (GET_MODE_CLASS (mode) != MODE_CC
- && GET_CODE (x) == REG && REGNO (x) == 24)
- abort ();
- if (GET_MODE_CLASS (mode) != MODE_CC
- || (! flag_fast_math && ! REVERSIBLE_CC_MODE (mode)))
+ if (GET_MODE_CLASS (mode) != MODE_CC)
return FALSE;
}
+ if (mode != CC_DNEmode && mode != CC_DEQmode
+ && mode != CC_DLEmode && mode != CC_DLTmode
+ && mode != CC_DGEmode && mode != CC_DGTmode
+ && mode != CC_DLEUmode && mode != CC_DLTUmode
+ && mode != CC_DGEUmode && mode != CC_DGTUmode)
+ return FALSE;
+
if (mode == GET_MODE (x) && GET_CODE (x) == REG && REGNO (x) == 24)
return TRUE;
return FALSE;
}
+/* Return TRUE if X references a SYMBOL_REF. */
+int
+symbol_mentioned_p (x)
+ rtx x;
+{
+ register char *fmt;
+ register int i;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ return 1;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (symbol_mentioned_p (XVECEXP (x, i, j)))
+ return 1;
+ }
+ else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return TRUE if X references a LABEL_REF. */
+int
+label_mentioned_p (x)
+ rtx x;
+{
+ register char *fmt;
+ register int i;
+
+ if (GET_CODE (x) == LABEL_REF)
+ return 1;
+
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (label_mentioned_p (XVECEXP (x, i, j)))
+ return 1;
+ }
+ else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
+ return 1;
+ }
+
+ return 0;
+}
+
enum rtx_code
minmax_code (x)
rtx x;
@@ -1498,6 +2345,392 @@ store_multiple_operation (op, mode)
}
int
+load_multiple_sequence (operands, nops, regs, base, load_offset)
+ rtx *operands;
+ int nops;
+ int *regs;
+ int *base;
+ HOST_WIDE_INT *load_offset;
+{
+ int unsorted_regs[4];
+ HOST_WIDE_INT unsorted_offsets[4];
+ int order[4];
+ int base_reg;
+ int i;
+
+ /* Can only handle 2, 3, or 4 insns at present, though could be easily
+ extended if required. */
+ if (nops < 2 || nops > 4)
+ abort ();
+
+ /* Loop over the operands and check that the memory references are
+ suitable (ie immediate offsets from the same base register). At
+ the same time, extract the target register, and the memory
+ offsets. */
+ for (i = 0; i < nops; i++)
+ {
+ rtx reg;
+ rtx offset;
+
+ /* Convert a subreg of a mem into the mem itself. */
+ if (GET_CODE (operands[nops + i]) == SUBREG)
+ operands[nops + i] = alter_subreg(operands[nops + i]);
+
+ if (GET_CODE (operands[nops + i]) != MEM)
+ abort ();
+
+ /* Don't reorder volatile memory references; it doesn't seem worth
+ looking for the case where the order is ok anyway. */
+ if (MEM_VOLATILE_P (operands[nops + i]))
+ return 0;
+
+ offset = const0_rtx;
+
+ if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
+ || (GET_CODE (reg) == SUBREG
+ && GET_CODE (reg = SUBREG_REG (reg)) == REG))
+ || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
+ && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
+ == REG)
+ || (GET_CODE (reg) == SUBREG
+ && GET_CODE (reg = SUBREG_REG (reg)) == REG))
+ && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
+ == CONST_INT)))
+ {
+ if (i == 0)
+ {
+ base_reg = REGNO(reg);
+ unsorted_regs[0] = (GET_CODE (operands[i]) == REG
+ ? REGNO (operands[i])
+ : REGNO (SUBREG_REG (operands[i])));
+ order[0] = 0;
+ }
+ else
+ {
+ if (base_reg != REGNO (reg))
+ /* Not addressed from the same base register. */
+ return 0;
+
+ unsorted_regs[i] = (GET_CODE (operands[i]) == REG
+ ? REGNO (operands[i])
+ : REGNO (SUBREG_REG (operands[i])));
+ if (unsorted_regs[i] < unsorted_regs[order[0]])
+ order[0] = i;
+ }
+
+ /* If it isn't an integer register, or if it overwrites the
+ base register but isn't the last insn in the list, then
+ we can't do this. */
+ if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14
+ || (i != nops - 1 && unsorted_regs[i] == base_reg))
+ return 0;
+
+ unsorted_offsets[i] = INTVAL (offset);
+ }
+ else
+ /* Not a suitable memory address. */
+ return 0;
+ }
+
+ /* All the useful information has now been extracted from the
+ operands into unsorted_regs and unsorted_offsets; additionally,
+ order[0] has been set to the lowest numbered register in the
+ list. Sort the registers into order, and check that the memory
+ offsets are ascending and adjacent. */
+
+ for (i = 1; i < nops; i++)
+ {
+ int j;
+
+ order[i] = order[i - 1];
+ for (j = 0; j < nops; j++)
+ if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
+ && (order[i] == order[i - 1]
+ || unsorted_regs[j] < unsorted_regs[order[i]]))
+ order[i] = j;
+
+ /* Have we found a suitable register? if not, one must be used more
+ than once. */
+ if (order[i] == order[i - 1])
+ return 0;
+
+ /* Is the memory address adjacent and ascending? */
+ if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
+ return 0;
+ }
+
+ if (base)
+ {
+ *base = base_reg;
+
+ for (i = 0; i < nops; i++)
+ regs[i] = unsorted_regs[order[i]];
+
+ *load_offset = unsorted_offsets[order[0]];
+ }
+
+ if (unsorted_offsets[order[0]] == 0)
+ return 1; /* ldmia */
+
+ if (unsorted_offsets[order[0]] == 4)
+ return 2; /* ldmib */
+
+ if (unsorted_offsets[order[nops - 1]] == 0)
+ return 3; /* ldmda */
+
+ if (unsorted_offsets[order[nops - 1]] == -4)
+ return 4; /* ldmdb */
+
+ /* Can't do it without setting up the offset, only do this if it takes
+ no more than one insn. */
+ return (const_ok_for_arm (unsorted_offsets[order[0]])
+ || const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
+}
+
+char *
+emit_ldm_seq (operands, nops)
+ rtx *operands;
+ int nops;
+{
+ int regs[4];
+ int base_reg;
+ HOST_WIDE_INT offset;
+ char buf[100];
+ int i;
+
+ switch (load_multiple_sequence (operands, nops, regs, &base_reg, &offset))
+ {
+ case 1:
+ strcpy (buf, "ldm%?ia\t");
+ break;
+
+ case 2:
+ strcpy (buf, "ldm%?ib\t");
+ break;
+
+ case 3:
+ strcpy (buf, "ldm%?da\t");
+ break;
+
+ case 4:
+ strcpy (buf, "ldm%?db\t");
+ break;
+
+ case 5:
+ if (offset >= 0)
+ sprintf (buf, "add%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
+ reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
+ (long) offset);
+ else
+ sprintf (buf, "sub%%?\t%s%s, %s%s, #%ld", REGISTER_PREFIX,
+ reg_names[regs[0]], REGISTER_PREFIX, reg_names[base_reg],
+ (long) -offset);
+ output_asm_insn (buf, operands);
+ base_reg = regs[0];
+ strcpy (buf, "ldm%?ia\t");
+ break;
+
+ default:
+ abort ();
+ }
+
+ sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
+ reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
+
+ for (i = 1; i < nops; i++)
+ sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
+ reg_names[regs[i]]);
+
+ strcat (buf, "}\t%@ phole ldm");
+
+ output_asm_insn (buf, operands);
+ return "";
+}
+
+int
+store_multiple_sequence (operands, nops, regs, base, load_offset)
+ rtx *operands;
+ int nops;
+ int *regs;
+ int *base;
+ HOST_WIDE_INT *load_offset;
+{
+ int unsorted_regs[4];
+ HOST_WIDE_INT unsorted_offsets[4];
+ int order[4];
+ int base_reg;
+ int i;
+
+ /* Can only handle 2, 3, or 4 insns at present, though could be easily
+ extended if required. */
+ if (nops < 2 || nops > 4)
+ abort ();
+
+ /* Loop over the operands and check that the memory references are
+ suitable (ie immediate offsets from the same base register). At
+ the same time, extract the target register, and the memory
+ offsets. */
+ for (i = 0; i < nops; i++)
+ {
+ rtx reg;
+ rtx offset;
+
+ /* Convert a subreg of a mem into the mem itself. */
+ if (GET_CODE (operands[nops + i]) == SUBREG)
+ operands[nops + i] = alter_subreg(operands[nops + i]);
+
+ if (GET_CODE (operands[nops + i]) != MEM)
+ abort ();
+
+ /* Don't reorder volatile memory references; it doesn't seem worth
+ looking for the case where the order is ok anyway. */
+ if (MEM_VOLATILE_P (operands[nops + i]))
+ return 0;
+
+ offset = const0_rtx;
+
+ if ((GET_CODE (reg = XEXP (operands[nops + i], 0)) == REG
+ || (GET_CODE (reg) == SUBREG
+ && GET_CODE (reg = SUBREG_REG (reg)) == REG))
+ || (GET_CODE (XEXP (operands[nops + i], 0)) == PLUS
+ && ((GET_CODE (reg = XEXP (XEXP (operands[nops + i], 0), 0))
+ == REG)
+ || (GET_CODE (reg) == SUBREG
+ && GET_CODE (reg = SUBREG_REG (reg)) == REG))
+ && (GET_CODE (offset = XEXP (XEXP (operands[nops + i], 0), 1))
+ == CONST_INT)))
+ {
+ if (i == 0)
+ {
+ base_reg = REGNO(reg);
+ unsorted_regs[0] = (GET_CODE (operands[i]) == REG
+ ? REGNO (operands[i])
+ : REGNO (SUBREG_REG (operands[i])));
+ order[0] = 0;
+ }
+ else
+ {
+ if (base_reg != REGNO (reg))
+ /* Not addressed from the same base register. */
+ return 0;
+
+ unsorted_regs[i] = (GET_CODE (operands[i]) == REG
+ ? REGNO (operands[i])
+ : REGNO (SUBREG_REG (operands[i])));
+ if (unsorted_regs[i] < unsorted_regs[order[0]])
+ order[0] = i;
+ }
+
+ /* If it isn't an integer register, then we can't do this. */
+ if (unsorted_regs[i] < 0 || unsorted_regs[i] > 14)
+ return 0;
+
+ unsorted_offsets[i] = INTVAL (offset);
+ }
+ else
+ /* Not a suitable memory address. */
+ return 0;
+ }
+
+ /* All the useful information has now been extracted from the
+ operands into unsorted_regs and unsorted_offsets; additionally,
+ order[0] has been set to the lowest numbered register in the
+ list. Sort the registers into order, and check that the memory
+ offsets are ascending and adjacent. */
+
+ for (i = 1; i < nops; i++)
+ {
+ int j;
+
+ order[i] = order[i - 1];
+ for (j = 0; j < nops; j++)
+ if (unsorted_regs[j] > unsorted_regs[order[i - 1]]
+ && (order[i] == order[i - 1]
+ || unsorted_regs[j] < unsorted_regs[order[i]]))
+ order[i] = j;
+
+ /* Have we found a suitable register? if not, one must be used more
+ than once. */
+ if (order[i] == order[i - 1])
+ return 0;
+
+ /* Is the memory address adjacent and ascending? */
+ if (unsorted_offsets[order[i]] != unsorted_offsets[order[i - 1]] + 4)
+ return 0;
+ }
+
+ if (base)
+ {
+ *base = base_reg;
+
+ for (i = 0; i < nops; i++)
+ regs[i] = unsorted_regs[order[i]];
+
+ *load_offset = unsorted_offsets[order[0]];
+ }
+
+ if (unsorted_offsets[order[0]] == 0)
+ return 1; /* stmia */
+
+ if (unsorted_offsets[order[0]] == 4)
+ return 2; /* stmib */
+
+ if (unsorted_offsets[order[nops - 1]] == 0)
+ return 3; /* stmda */
+
+ if (unsorted_offsets[order[nops - 1]] == -4)
+ return 4; /* stmdb */
+
+ return 0;
+}
+
+char *
+emit_stm_seq (operands, nops)
+ rtx *operands;
+ int nops;
+{
+ int regs[4];
+ int base_reg;
+ HOST_WIDE_INT offset;
+ char buf[100];
+ int i;
+
+ switch (store_multiple_sequence (operands, nops, regs, &base_reg, &offset))
+ {
+ case 1:
+ strcpy (buf, "stm%?ia\t");
+ break;
+
+ case 2:
+ strcpy (buf, "stm%?ib\t");
+ break;
+
+ case 3:
+ strcpy (buf, "stm%?da\t");
+ break;
+
+ case 4:
+ strcpy (buf, "stm%?db\t");
+ break;
+
+ default:
+ abort ();
+ }
+
+ sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
+ reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
+
+ for (i = 1; i < nops; i++)
+ sprintf (buf + strlen (buf), ", %s%s", REGISTER_PREFIX,
+ reg_names[regs[i]]);
+
+ strcat (buf, "}\t%@ phole stm");
+
+ output_asm_insn (buf, operands);
+ return "";
+}
+
+int
multi_register_push (op, mode)
rtx op;
enum machine_mode mode;
@@ -1514,26 +2747,62 @@ multi_register_push (op, mode)
/* Routines for use with attributes */
+/* Return nonzero if ATTR is a valid attribute for DECL.
+ ATTRIBUTES are any existing attributes and ARGS are the arguments
+ supplied with ATTR.
+
+ Supported attributes:
+
+ naked: don't output any prologue or epilogue code, the user is assumed
+ to do the right thing. */
+
int
-const_pool_offset (symbol)
- rtx symbol;
+arm_valid_machine_decl_attribute (decl, attributes, attr, args)
+ tree decl;
+ tree attributes;
+ tree attr;
+ tree args;
{
- return get_pool_offset (symbol) - get_pool_size () - get_prologue_size ();
+ if (args != NULL_TREE)
+ return 0;
+
+ if (is_attribute_p ("naked", attr))
+ return TREE_CODE (decl) == FUNCTION_DECL;
+ return 0;
+}
+
+/* Return non-zero if FUNC is a naked function. */
+
+static int
+arm_naked_function_p (func)
+ tree func;
+{
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ abort ();
+
+ a = lookup_attribute ("naked", DECL_MACHINE_ATTRIBUTES (func));
+ return a != NULL_TREE;
}
/* Routines for use in generating RTL */
rtx
-arm_gen_load_multiple (base_regno, count, from, up, write_back)
+arm_gen_load_multiple (base_regno, count, from, up, write_back, unchanging_p,
+ in_struct_p)
int base_regno;
int count;
rtx from;
int up;
int write_back;
+ int unchanging_p;
+ int in_struct_p;
{
int i = 0, j;
rtx result;
int sign = up ? 1 : -1;
+ rtx mem;
result = gen_rtx (PARALLEL, VOIDmode,
rtvec_alloc (count + (write_back ? 2 : 0)));
@@ -1548,10 +2817,13 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back)
for (j = 0; i < count; i++, j++)
{
- XVECEXP (result, 0, i)
- = gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, base_regno + j),
- gen_rtx (MEM, SImode,
- plus_constant (from, j * 4 * sign)));
+ mem = gen_rtx (MEM, SImode, plus_constant (from, j * 4 * sign));
+ RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_IN_STRUCT_P (mem) = in_struct_p;
+
+ XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode,
+ gen_rtx (REG, SImode, base_regno + j),
+ mem);
}
if (write_back)
@@ -1561,16 +2833,20 @@ arm_gen_load_multiple (base_regno, count, from, up, write_back)
}
rtx
-arm_gen_store_multiple (base_regno, count, to, up, write_back)
+arm_gen_store_multiple (base_regno, count, to, up, write_back, unchanging_p,
+ in_struct_p)
int base_regno;
int count;
rtx to;
int up;
int write_back;
+ int unchanging_p;
+ int in_struct_p;
{
int i = 0, j;
rtx result;
int sign = up ? 1 : -1;
+ rtx mem;
result = gen_rtx (PARALLEL, VOIDmode,
rtvec_alloc (count + (write_back ? 2 : 0)));
@@ -1585,10 +2861,12 @@ arm_gen_store_multiple (base_regno, count, to, up, write_back)
for (j = 0; i < count; i++, j++)
{
- XVECEXP (result, 0, i)
- = gen_rtx (SET, VOIDmode,
- gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign)),
- gen_rtx (REG, SImode, base_regno + j));
+ mem = gen_rtx (MEM, SImode, plus_constant (to, j * 4 * sign));
+ RTX_UNCHANGING_P (mem) = unchanging_p;
+ MEM_IN_STRUCT_P (mem) = in_struct_p;
+
+ XVECEXP (result, 0, i) = gen_rtx (SET, VOIDmode, mem,
+ gen_rtx (REG, SImode, base_regno + j));
}
if (write_back)
@@ -1606,6 +2884,8 @@ arm_gen_movstrqi (operands)
rtx src, dst;
rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;
rtx part_bytes_reg = NULL;
+ rtx mem;
+ int dst_unchanging_p, dst_in_struct_p, src_unchanging_p, src_in_struct_p;
extern int optimize;
if (GET_CODE (operands[2]) != CONST_INT
@@ -1616,6 +2896,12 @@ arm_gen_movstrqi (operands)
st_dst = XEXP (operands[0], 0);
st_src = XEXP (operands[1], 0);
+
+ dst_unchanging_p = RTX_UNCHANGING_P (operands[0]);
+ dst_in_struct_p = MEM_IN_STRUCT_P (operands[0]);
+ src_unchanging_p = RTX_UNCHANGING_P (operands[1]);
+ src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
+
fin_dst = dst = copy_to_mode_reg (SImode, st_dst);
fin_src = src = copy_to_mode_reg (SImode, st_src);
@@ -1628,20 +2914,35 @@ arm_gen_movstrqi (operands)
for (i = 0; in_words_to_go >= 2; i+=4)
{
- emit_insn (arm_gen_load_multiple (0, (in_words_to_go > 4
- ? 4 : in_words_to_go),
- src, TRUE, TRUE));
+ if (in_words_to_go > 4)
+ emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
+ src_unchanging_p, src_in_struct_p));
+ else
+ emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
+ FALSE, src_unchanging_p,
+ src_in_struct_p));
+
if (out_words_to_go)
{
- if (out_words_to_go != 1)
- emit_insn (arm_gen_store_multiple (0, (out_words_to_go > 4
- ? 4 : out_words_to_go),
- dst, TRUE, TRUE));
+ if (out_words_to_go > 4)
+ emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
+ dst_unchanging_p,
+ dst_in_struct_p));
+ else if (out_words_to_go != 1)
+ emit_insn (arm_gen_store_multiple (0, out_words_to_go,
+ dst, TRUE,
+ (last_bytes == 0
+ ? FALSE : TRUE),
+ dst_unchanging_p,
+ dst_in_struct_p));
else
{
- emit_move_insn (gen_rtx (MEM, SImode, dst),
- gen_rtx (REG, SImode, 0));
- emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
+ mem = gen_rtx (MEM, SImode, dst);
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, gen_rtx (REG, SImode, 0));
+ if (last_bytes != 0)
+ emit_insn (gen_addsi3 (dst, dst, GEN_INT (4)));
}
}
@@ -1654,9 +2955,16 @@ arm_gen_movstrqi (operands)
{
rtx sreg;
- emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));
+ mem = gen_rtx (MEM, SImode, src);
+ RTX_UNCHANGING_P (mem) = src_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+ emit_move_insn (sreg = gen_reg_rtx (SImode), mem);
emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
- emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);
+
+ mem = gen_rtx (MEM, SImode, dst);
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, sreg);
emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
in_words_to_go--;
@@ -1669,8 +2977,10 @@ arm_gen_movstrqi (operands)
if (in_words_to_go < 0)
abort ();
- part_bytes_reg = copy_to_mode_reg (SImode, gen_rtx (MEM, SImode, src));
- emit_insn (gen_addsi3 (src, src, GEN_INT (4)));
+ mem = gen_rtx (MEM, SImode, src);
+ RTX_UNCHANGING_P (mem) = src_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = src_in_struct_p;
+ part_bytes_reg = copy_to_mode_reg (SImode, mem);
}
if (BYTES_BIG_ENDIAN && last_bytes)
@@ -1687,9 +2997,10 @@ arm_gen_movstrqi (operands)
while (last_bytes)
{
- emit_move_insn (gen_rtx (MEM, QImode,
- plus_constant (dst, last_bytes - 1)),
- gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
+ mem = gen_rtx (MEM, QImode, plus_constant (dst, last_bytes - 1));
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
if (--last_bytes)
{
tmp = gen_reg_rtx (SImode);
@@ -1706,12 +3017,15 @@ arm_gen_movstrqi (operands)
if (part_bytes_reg == NULL)
abort ();
- emit_move_insn (gen_rtx (MEM, QImode, dst),
- gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
- emit_insn (gen_addsi3 (dst, dst, const1_rtx));
+ mem = gen_rtx (MEM, QImode, dst);
+ RTX_UNCHANGING_P (mem) = dst_unchanging_p;
+ MEM_IN_STRUCT_P (mem) = dst_in_struct_p;
+ emit_move_insn (mem, gen_rtx (SUBREG, QImode, part_bytes_reg, 0));
if (--last_bytes)
{
rtx tmp = gen_reg_rtx (SImode);
+
+ emit_insn (gen_addsi3 (dst, dst, const1_rtx));
emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (8)));
part_bytes_reg = tmp;
}
@@ -1721,6 +3035,217 @@ arm_gen_movstrqi (operands)
return 1;
}
+/* Generate a memory reference for a half word, such that it will be loaded
+ into the top 16 bits of the word. We can assume that the address is
+ known to be alignable and of the form reg, or plus (reg, const). */
+rtx
+gen_rotated_half_load (memref)
+ rtx memref;
+{
+ HOST_WIDE_INT offset = 0;
+ rtx base = XEXP (memref, 0);
+
+ if (GET_CODE (base) == PLUS)
+ {
+ offset = INTVAL (XEXP (base, 1));
+ base = XEXP (base, 0);
+ }
+
+ /* If we aren't allowed to generate unaligned addresses, then fail. */
+ if (TARGET_SHORT_BY_BYTES
+ && ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 0)))
+ return NULL;
+
+ base = gen_rtx (MEM, SImode, plus_constant (base, offset & ~2));
+
+ if ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 2))
+ return base;
+
+ return gen_rtx (ROTATE, SImode, base, GEN_INT (16));
+}
+
+static enum machine_mode
+select_dominance_cc_mode (op, x, y, cond_or)
+ enum rtx_code op;
+ rtx x;
+ rtx y;
+ HOST_WIDE_INT cond_or;
+{
+ enum rtx_code cond1, cond2;
+ int swapped = 0;
+
+ /* Currently we will probably get the wrong result if the individual
+ comparisons are not simple. This also ensures that it is safe to
+ reverse a comparison if necessary. */
+ if ((arm_select_cc_mode (cond1 = GET_CODE (x), XEXP (x, 0), XEXP (x, 1))
+ != CCmode)
+ || (arm_select_cc_mode (cond2 = GET_CODE (y), XEXP (y, 0), XEXP (y, 1))
+ != CCmode))
+ return CCmode;
+
+ if (cond_or)
+ cond1 = reverse_condition (cond1);
+
+ /* If the comparisons are not equal, and one doesn't dominate the other,
+ then we can't do this. */
+ if (cond1 != cond2
+ && ! comparison_dominates_p (cond1, cond2)
+ && (swapped = 1, ! comparison_dominates_p (cond2, cond1)))
+ return CCmode;
+
+ if (swapped)
+ {
+ enum rtx_code temp = cond1;
+ cond1 = cond2;
+ cond2 = temp;
+ }
+
+ switch (cond1)
+ {
+ case EQ:
+ if (cond2 == EQ || ! cond_or)
+ return CC_DEQmode;
+
+ switch (cond2)
+ {
+ case LE: return CC_DLEmode;
+ case LEU: return CC_DLEUmode;
+ case GE: return CC_DGEmode;
+ case GEU: return CC_DGEUmode;
+ }
+
+ break;
+
+ case LT:
+ if (cond2 == LT || ! cond_or)
+ return CC_DLTmode;
+ if (cond2 == LE)
+ return CC_DLEmode;
+ if (cond2 == NE)
+ return CC_DNEmode;
+ break;
+
+ case GT:
+ if (cond2 == GT || ! cond_or)
+ return CC_DGTmode;
+ if (cond2 == GE)
+ return CC_DGEmode;
+ if (cond2 == NE)
+ return CC_DNEmode;
+ break;
+
+ case LTU:
+ if (cond2 == LTU || ! cond_or)
+ return CC_DLTUmode;
+ if (cond2 == LEU)
+ return CC_DLEUmode;
+ if (cond2 == NE)
+ return CC_DNEmode;
+ break;
+
+ case GTU:
+ if (cond2 == GTU || ! cond_or)
+ return CC_DGTUmode;
+ if (cond2 == GEU)
+ return CC_DGEUmode;
+ if (cond2 == NE)
+ return CC_DNEmode;
+ break;
+
+ /* The remaining cases only occur when both comparisons are the
+ same. */
+ case NE:
+ return CC_DNEmode;
+
+ case LE:
+ return CC_DLEmode;
+
+ case GE:
+ return CC_DGEmode;
+
+ case LEU:
+ return CC_DLEUmode;
+
+ case GEU:
+ return CC_DGEUmode;
+ }
+
+ abort ();
+}
+
+enum machine_mode
+arm_select_cc_mode (op, x, y)
+ enum rtx_code op;
+ rtx x;
+ rtx y;
+{
+ /* All floating point compares return CCFP if it is an equality
+ comparison, and CCFPE otherwise. */
+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+ return (op == EQ || op == NE) ? CCFPmode : CCFPEmode;
+
+ /* A compare with a shifted operand. Because of canonicalization, the
+ comparison will have to be swapped when we emit the assembler. */
+ if (GET_MODE (y) == SImode && GET_CODE (y) == REG
+ && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
+ || GET_CODE (x) == LSHIFTRT || GET_CODE (x) == ROTATE
+ || GET_CODE (x) == ROTATERT))
+ return CC_SWPmode;
+
+ /* This is a special case that is used by combine to allow a
+ comparison of a shifted byte load to be split into a zero-extend
+ followed by a comparison of the shifted integer (only valid for
+ equalities and unsigned inequalities). */
+ if (GET_MODE (x) == SImode
+ && GET_CODE (x) == ASHIFT
+ && GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 24
+ && GET_CODE (XEXP (x, 0)) == SUBREG
+ && GET_CODE (SUBREG_REG (XEXP (x, 0))) == MEM
+ && GET_MODE (SUBREG_REG (XEXP (x, 0))) == QImode
+ && (op == EQ || op == NE
+ || op == GEU || op == GTU || op == LTU || op == LEU)
+ && GET_CODE (y) == CONST_INT)
+ return CC_Zmode;
+
+ /* An operation that sets the condition codes as a side-effect, the
+ V flag is not set correctly, so we can only use comparisons where
+ this doesn't matter. (For LT and GE we can use "mi" and "pl"
+ instead. */
+ if (GET_MODE (x) == SImode
+ && y == const0_rtx
+ && (op == EQ || op == NE || op == LT || op == GE)
+ && (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
+ || GET_CODE (x) == AND || GET_CODE (x) == IOR
+ || GET_CODE (x) == XOR || GET_CODE (x) == MULT
+ || GET_CODE (x) == NOT || GET_CODE (x) == NEG
+ || GET_CODE (x) == LSHIFTRT
+ || GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT
+ || GET_CODE (x) == ROTATERT || GET_CODE (x) == ZERO_EXTRACT))
+ return CC_NOOVmode;
+
+ /* A construct for a conditional compare, if the false arm contains
+ 0, then both conditions must be true, otherwise either condition
+ must be true. Not all conditions are possible, so CCmode is
+ returned if it can't be done. */
+ if (GET_CODE (x) == IF_THEN_ELSE
+ && (XEXP (x, 2) == const0_rtx
+ || XEXP (x, 2) == const1_rtx)
+ && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
+ && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
+ return select_dominance_cc_mode (op, XEXP (x, 0), XEXP (x, 1),
+ INTVAL (XEXP (x, 2)));
+
+ if (GET_MODE (x) == QImode && (op == EQ || op == NE))
+ return CC_Zmode;
+
+ if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
+ && GET_CODE (x) == PLUS
+ && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
+ return CC_Cmode;
+
+ return CCmode;
+}
+
/* X and Y are two things to compare using CODE. Emit the compare insn and
return the rtx for register 0 in the proper mode. FP means this is a
floating point compare: I don't think that it is needed on the arm. */
@@ -1796,34 +3321,395 @@ arm_reload_out_hi (operands)
}
}
-/* Check to see if a branch is forwards or backwards. Return TRUE if it
- is backwards. */
+/* Routines for manipulation of the constant pool. */
+/* This is unashamedly hacked from the version in sh.c, since the problem is
+ extremely similar. */
+
+/* Arm instructions cannot load a large constant into a register,
+ constants have to come from a pc relative load. The reference of a pc
+ relative load instruction must be less than 1k infront of the instruction.
+ This means that we often have to dump a constant inside a function, and
+ generate code to branch around it.
+
+ It is important to minimize this, since the branches will slow things
+ down and make things bigger.
+
+ Worst case code looks like:
+
+ ldr rn, L1
+ b L2
+ align
+ L1: .long value
+ L2:
+ ..
+
+ ldr rn, L3
+ b L4
+ align
+ L3: .long value
+ L4:
+ ..
+
+ We fix this by performing a scan before scheduling, which notices which
+ instructions need to have their operands fetched from the constant table
+ and builds the table.
+
+
+ The algorithm is:
+
+ scan, find an instruction which needs a pcrel move. Look forward, find th
+ last barrier which is within MAX_COUNT bytes of the requirement.
+ If there isn't one, make one. Process all the instructions between
+ the find and the barrier.
+
+ In the above example, we can tell that L3 is within 1k of L1, so
+ the first move can be shrunk from the 2 insn+constant sequence into
+ just 1 insn, and the constant moved to L3 to make:
+
+ ldr rn, L1
+ ..
+ ldr rn, L3
+ b L4
+ align
+ L1: .long value
+ L3: .long value
+ L4:
+
+ Then the second move becomes the target for the shortening process.
-int
-arm_backwards_branch (from, to)
- int from, to;
+ */
+
+typedef struct
+{
+ rtx value; /* Value in table */
+ HOST_WIDE_INT next_offset;
+ enum machine_mode mode; /* Mode of value */
+} pool_node;
+
+/* The maximum number of constants that can fit into one pool, since
+ the pc relative range is 0...1020 bytes and constants are at least 4
+ bytes long */
+
+#define MAX_POOL_SIZE (1020/4)
+static pool_node pool_vector[MAX_POOL_SIZE];
+static int pool_size;
+static rtx pool_vector_label;
+
+/* Add a constant to the pool and return its label. */
+static HOST_WIDE_INT
+add_constant (x, mode)
+ rtx x;
+ enum machine_mode mode;
+{
+ int i;
+ rtx lab;
+ HOST_WIDE_INT offset;
+
+ if (mode == SImode && GET_CODE (x) == MEM && CONSTANT_P (XEXP (x, 0))
+ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
+ x = get_pool_constant (XEXP (x, 0));
+#ifndef AOF_ASSEMBLER
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == 3)
+ x = XVECEXP (x, 0, 0);
+#endif
+
+#ifdef AOF_ASSEMBLER
+ /* PIC Symbol references need to be converted into offsets into the
+ based area. */
+ if (flag_pic && GET_CODE (x) == SYMBOL_REF)
+ x = aof_pic_entry (x);
+#endif /* AOF_ASSEMBLER */
+
+ /* First see if we've already got it */
+ for (i = 0; i < pool_size; i++)
+ {
+ if (GET_CODE (x) == pool_vector[i].value->code
+ && mode == pool_vector[i].mode)
+ {
+ if (GET_CODE (x) == CODE_LABEL)
+ {
+ if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
+ continue;
+ }
+ if (rtx_equal_p (x, pool_vector[i].value))
+ return pool_vector[i].next_offset - GET_MODE_SIZE (mode);
+ }
+ }
+
+ /* Need a new one */
+ pool_vector[pool_size].next_offset = GET_MODE_SIZE (mode);
+ offset = 0;
+ if (pool_size == 0)
+ pool_vector_label = gen_label_rtx ();
+ else
+ pool_vector[pool_size].next_offset
+ += (offset = pool_vector[pool_size - 1].next_offset);
+
+ pool_vector[pool_size].value = x;
+ pool_vector[pool_size].mode = mode;
+ pool_size++;
+ return offset;
+}
+
+/* Output the literal table */
+static void
+dump_table (scan)
+ rtx scan;
{
- return insn_addresses[to] <= insn_addresses[from];
+ int i;
+
+ scan = emit_label_after (gen_label_rtx (), scan);
+ scan = emit_insn_after (gen_align_4 (), scan);
+ scan = emit_label_after (pool_vector_label, scan);
+
+ for (i = 0; i < pool_size; i++)
+ {
+ pool_node *p = pool_vector + i;
+
+ switch (GET_MODE_SIZE (p->mode))
+ {
+ case 4:
+ scan = emit_insn_after (gen_consttable_4 (p->value), scan);
+ break;
+
+ case 8:
+ scan = emit_insn_after (gen_consttable_8 (p->value), scan);
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+ }
+
+ scan = emit_insn_after (gen_consttable_end (), scan);
+ scan = emit_barrier_after (scan);
+ pool_size = 0;
}
-/* Check to see if a branch is within the distance that can be done using
- an arithmetic expression. */
-int
-short_branch (from, to)
- int from, to;
+/* Non zero if the src operand needs to be fixed up */
+static int
+fixit (src, mode, destreg)
+ rtx src;
+ enum machine_mode mode;
+ int destreg;
+{
+ if (CONSTANT_P (src))
+ {
+ if (GET_CODE (src) == CONST_INT)
+ return (! const_ok_for_arm (INTVAL (src))
+ && ! const_ok_for_arm (~INTVAL (src)));
+ if (GET_CODE (src) == CONST_DOUBLE)
+ return (GET_MODE (src) == VOIDmode
+ || destreg < 16
+ || (! const_double_rtx_ok_for_fpu (src)
+ && ! neg_const_double_rtx_ok_for_fpu (src)));
+ return symbol_mentioned_p (src);
+ }
+#ifndef AOF_ASSEMBLER
+ else if (GET_CODE (src) == UNSPEC && XINT (src, 1) == 3)
+ return 1;
+#endif
+ else
+ return (mode == SImode && GET_CODE (src) == MEM
+ && GET_CODE (XEXP (src, 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (src, 0)));
+}
+
+/* Find the last barrier less than MAX_COUNT bytes from FROM, or create one. */
+static rtx
+find_barrier (from, max_count)
+ rtx from;
+ int max_count;
{
- int delta = insn_addresses[from] + 8 - insn_addresses[to];
+ int count = 0;
+ rtx found_barrier = 0;
+
+ while (from && count < max_count)
+ {
+ if (GET_CODE (from) == BARRIER)
+ found_barrier = from;
+
+ /* Count the length of this insn */
+ if (GET_CODE (from) == INSN
+ && GET_CODE (PATTERN (from)) == SET
+ && CONSTANT_P (SET_SRC (PATTERN (from)))
+ && CONSTANT_POOL_ADDRESS_P (SET_SRC (PATTERN (from))))
+ {
+ rtx src = SET_SRC (PATTERN (from));
+ count += 2;
+ }
+ else
+ count += get_attr_length (from);
- return abs (delta) < 980; /* A small margin for safety */
+ from = NEXT_INSN (from);
+ }
+
+ if (!found_barrier)
+ {
+ /* We didn't find a barrier in time to
+ dump our stuff, so we'll make one */
+ rtx label = gen_label_rtx ();
+
+ if (from)
+ from = PREV_INSN (from);
+ else
+ from = get_last_insn ();
+
+ /* Walk back to be just before any jump */
+ while (GET_CODE (from) == JUMP_INSN
+ || GET_CODE (from) == NOTE
+ || GET_CODE (from) == CODE_LABEL)
+ from = PREV_INSN (from);
+
+ from = emit_jump_insn_after (gen_jump (label), from);
+ JUMP_LABEL (from) = label;
+ found_barrier = emit_barrier_after (from);
+ emit_label_after (label, found_barrier);
+ return found_barrier;
+ }
+
+ return found_barrier;
}
-/* Check to see that the insn isn't the target of the conditionalizing
- code */
-int
-arm_insn_not_targeted (insn)
+/* Non zero if the insn is a move instruction which needs to be fixed. */
+static int
+broken_move (insn)
rtx insn;
{
- return insn != arm_target_insn;
+ if (!INSN_DELETED_P (insn)
+ && GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET)
+ {
+ rtx pat = PATTERN (insn);
+ rtx src = SET_SRC (pat);
+ rtx dst = SET_DEST (pat);
+ int destreg;
+ enum machine_mode mode = GET_MODE (dst);
+ if (dst == pc_rtx)
+ return 0;
+
+ if (GET_CODE (dst) == REG)
+ destreg = REGNO (dst);
+ else if (GET_CODE (dst) == SUBREG && GET_CODE (SUBREG_REG (dst)) == REG)
+ destreg = REGNO (SUBREG_REG (dst));
+
+ return fixit (src, mode, destreg);
+ }
+ return 0;
+}
+
+void
+arm_reorg (first)
+ rtx first;
+{
+ rtx insn;
+ int count_size;
+ int regno;
+
+#if 0
+ /* The ldr instruction can work with up to a 4k offset, and most constants
+ will be loaded with one of these instructions; however, the adr
+ instruction and the ldf instructions only work with a 1k offset. This
+ code needs to be rewritten to use the 4k offset when possible, and to
+ adjust when a 1k offset is needed. For now we just use a 1k offset
+ from the start. */
+ count_size = 4000;
+
+ /* Floating point operands can't work further than 1024 bytes from the
+ PC, so to make things simple we restrict all loads for such functions.
+ */
+ if (TARGET_HARD_FLOAT)
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno])
+ {
+ count_size = 1000;
+ break;
+ }
+#else
+ count_size = 1000;
+#endif /* 0 */
+
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ if (broken_move (insn))
+ {
+ /* This is a broken move instruction, scan ahead looking for
+ a barrier to stick the constant table behind */
+ rtx scan;
+ rtx barrier = find_barrier (insn, count_size);
+
+ /* Now find all the moves between the points and modify them */
+ for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
+ {
+ if (broken_move (scan))
+ {
+ /* This is a broken move instruction, add it to the pool */
+ rtx pat = PATTERN (scan);
+ rtx src = SET_SRC (pat);
+ rtx dst = SET_DEST (pat);
+ enum machine_mode mode = GET_MODE (dst);
+ HOST_WIDE_INT offset;
+ rtx newinsn = scan;
+ rtx newsrc;
+ rtx addr;
+ int scratch;
+
+ /* If this is an HImode constant load, convert it into
+ an SImode constant load. Since the register is always
+ 32 bits this is safe. We have to do this, since the
+ load pc-relative instruction only does a 32-bit load. */
+ if (mode == HImode)
+ {
+ mode = SImode;
+ if (GET_CODE (dst) != REG)
+ abort ();
+ PUT_MODE (dst, SImode);
+ }
+
+ offset = add_constant (src, mode);
+ addr = plus_constant (gen_rtx (LABEL_REF, VOIDmode,
+ pool_vector_label),
+ offset);
+
+ /* For wide moves to integer regs we need to split the
+ address calculation off into a separate insn, so that
+ the load can then be done with a load-multiple. This is
+ safe, since we have already noted the length of such
+ insns to be 8, and we are immediately over-writing the
+ scratch we have grabbed with the final result. */
+ if (GET_MODE_SIZE (mode) > 4
+ && (scratch = REGNO (dst)) < 16)
+ {
+ rtx reg = gen_rtx (REG, SImode, scratch);
+ newinsn = emit_insn_after (gen_movaddr (reg, addr),
+ newinsn);
+ addr = reg;
+ }
+
+ newsrc = gen_rtx (MEM, mode, addr);
+
+ /* Build a jump insn wrapper around the move instead
+ of an ordinary insn, because we want to have room for
+ the target label rtx in fld[7], which an ordinary
+ insn doesn't have. */
+ newinsn = emit_jump_insn_after (gen_rtx (SET, VOIDmode,
+ dst, newsrc),
+ newinsn);
+ JUMP_LABEL (newinsn) = pool_vector_label;
+
+ /* But it's still an ordinary insn */
+ PUT_CODE (newinsn, INSN);
+
+ /* Kill old insn */
+ delete_insn (scan);
+ scan = newinsn;
+ }
+ }
+ dump_table (barrier);
+ insn = scan;
+ }
+ }
}
@@ -2097,7 +3983,7 @@ output_move_double (operands)
{
enum rtx_code code0 = GET_CODE (operands[0]);
enum rtx_code code1 = GET_CODE (operands[1]);
- rtx otherops[2];
+ rtx otherops[3];
if (code0 == REG)
{
@@ -2110,106 +3996,202 @@ output_move_double (operands)
if (reg1 == 12)
abort();
- otherops[1] = gen_rtx (REG, SImode, 1 + reg1);
-
/* Ensure the second source is not overwritten */
- if (reg0 == 1 + reg1)
+ if (reg1 == reg0 + (WORDS_BIG_ENDIAN ? -1 : 1))
+ output_asm_insn("mov%?\t%Q0, %Q1\n\tmov%?\t%R0, %R1", operands);
+ else
+ output_asm_insn("mov%?\t%R0, %R1\n\tmov%?\t%Q0, %Q1", operands);
+ }
+ else if (code1 == CONST_DOUBLE)
+ {
+ if (GET_MODE (operands[1]) == DFmode)
+ {
+ long l[2];
+ union real_extract u;
+
+ bcopy ((char *) &CONST_DOUBLE_LOW (operands[1]), (char *) &u,
+ sizeof (u));
+ REAL_VALUE_TO_TARGET_DOUBLE (u.d, l);
+ otherops[1] = GEN_INT(l[1]);
+ operands[1] = GEN_INT(l[0]);
+ }
+ else if (GET_MODE (operands[1]) != VOIDmode)
+ abort ();
+ else if (WORDS_BIG_ENDIAN)
{
- output_asm_insn("mov%?\t%0, %1", otherops);
- output_asm_insn("mov%?\t%0, %1", operands);
+
+ otherops[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+ operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
}
else
{
- output_asm_insn("mov%?\t%0, %1", operands);
- output_asm_insn("mov%?\t%0, %1", otherops);
+
+ otherops[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
+ operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
}
- }
- else if (code1 == CONST_DOUBLE)
- {
- otherops[1] = gen_rtx (CONST_INT, VOIDmode,
- CONST_DOUBLE_HIGH (operands[1]));
- operands[1] = gen_rtx (CONST_INT, VOIDmode,
- CONST_DOUBLE_LOW (operands[1]));
- output_mov_immediate (operands, FALSE, "");
- output_mov_immediate (otherops, FALSE, "");
+ output_mov_immediate (operands);
+ output_mov_immediate (otherops);
}
else if (code1 == CONST_INT)
{
- otherops[1] = const0_rtx;
- /* sign extend the intval into the high-order word */
- /* Note: output_mov_immediate may clobber operands[1], so we
- put this out first */
- if (INTVAL (operands[1]) < 0)
- output_asm_insn ("mvn%?\t%0, %1", otherops);
+#if HOST_BITS_PER_WIDE_INT > 32
+ /* If HOST_WIDE_INT is more than 32 bits, the intval tells us
+ what the upper word is. */
+ if (WORDS_BIG_ENDIAN)
+ {
+ otherops[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
+ operands[1] = GEN_INT (INTVAL (operands[1]) >> 32);
+ }
+ else
+ {
+ otherops[1] = GEN_INT (INTVAL (operands[1]) >> 32);
+ operands[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
+ }
+#else
+ /* Sign extend the intval into the high-order word */
+ if (WORDS_BIG_ENDIAN)
+ {
+ otherops[1] = operands[1];
+ operands[1] = (INTVAL (operands[1]) < 0
+ ? constm1_rtx : const0_rtx);
+ }
else
- output_asm_insn ("mov%?\t%0, %1", otherops);
- output_mov_immediate (operands, FALSE, "");
+ otherops[1] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
+#endif
+ output_mov_immediate (otherops);
+ output_mov_immediate (operands);
}
else if (code1 == MEM)
{
switch (GET_CODE (XEXP (operands[1], 0)))
{
case REG:
- /* Handle the simple case where address is [r, #0] more
- efficient. */
output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
break;
+
case PRE_INC:
- output_asm_insn ("add%?\t%m1, %m1, #8", operands);
- output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
+ abort (); /* Should never happen now */
break;
+
case PRE_DEC:
- output_asm_insn ("sub%?\t%m1, %m1, #8", operands);
- output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
+ output_asm_insn ("ldm%?db\t%m1!, %M0", operands);
break;
+
case POST_INC:
output_asm_insn ("ldm%?ia\t%m1!, %M0", operands);
break;
+
case POST_DEC:
- output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
- output_asm_insn ("sub%?\t%m1, %m1, #8", operands);
+ abort (); /* Should never happen now */
break;
+
+ case LABEL_REF:
+ case CONST:
+ output_asm_insn ("adr%?\t%0, %1", operands);
+ output_asm_insn ("ldm%?ia\t%0, %M0", operands);
+ break;
+
default:
- otherops[1] = adj_offsettable_operand (operands[1], 4);
- /* Take care of overlapping base/data reg. */
- if (reg_mentioned_p (operands[0], operands[1]))
+ if (arm_add_operand (XEXP (XEXP (operands[1], 0), 1)))
{
- output_asm_insn ("ldr%?\t%0, %1", otherops);
- output_asm_insn ("ldr%?\t%0, %1", operands);
- }
- else
- {
- output_asm_insn ("ldr%?\t%0, %1", operands);
- output_asm_insn ("ldr%?\t%0, %1", otherops);
+ otherops[0] = operands[0];
+ otherops[1] = XEXP (XEXP (operands[1], 0), 0);
+ otherops[2] = XEXP (XEXP (operands[1], 0), 1);
+ if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
+ {
+ if (GET_CODE (otherops[2]) == CONST_INT)
+ {
+ switch (INTVAL (otherops[2]))
+ {
+ case -8:
+ output_asm_insn ("ldm%?db\t%1, %M0", otherops);
+ return "";
+ case -4:
+ output_asm_insn ("ldm%?da\t%1, %M0", otherops);
+ return "";
+ case 4:
+ output_asm_insn ("ldm%?ib\t%1, %M0", otherops);
+ return "";
+ }
+ if (!(const_ok_for_arm (INTVAL (otherops[2]))))
+ output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
+ else
+ output_asm_insn ("add%?\t%0, %1, %2", otherops);
+ }
+ else
+ output_asm_insn ("add%?\t%0, %1, %2", otherops);
+ }
+ else
+ output_asm_insn ("sub%?\t%0, %1, %2", otherops);
+ return "ldm%?ia\t%0, %M0";
+ }
+ else
+ {
+ otherops[1] = adj_offsettable_operand (operands[1], 4);
+ /* Take care of overlapping base/data reg. */
+ if (reg_mentioned_p (operands[0], operands[1]))
+ {
+ output_asm_insn ("ldr%?\t%0, %1", otherops);
+ output_asm_insn ("ldr%?\t%0, %1", operands);
+ }
+ else
+ {
+ output_asm_insn ("ldr%?\t%0, %1", operands);
+ output_asm_insn ("ldr%?\t%0, %1", otherops);
+ }
}
}
}
- else abort(); /* Constraints should prevent this */
+ else
+ abort(); /* Constraints should prevent this */
}
else if (code0 == MEM && code1 == REG)
{
if (REGNO (operands[1]) == 12)
abort();
+
switch (GET_CODE (XEXP (operands[0], 0)))
{
case REG:
output_asm_insn ("stm%?ia\t%m0, %M1", operands);
break;
+
case PRE_INC:
- output_asm_insn ("add%?\t%m0, %m0, #8", operands);
- output_asm_insn ("stm%?ia\t%m0, %M1", operands);
+ abort (); /* Should never happen now */
break;
+
case PRE_DEC:
- output_asm_insn ("sub%?\t%m0, %m0, #8", operands);
- output_asm_insn ("stm%?ia\t%m0, %M1", operands);
+ output_asm_insn ("stm%?db\t%m0!, %M1", operands);
break;
+
case POST_INC:
output_asm_insn ("stm%?ia\t%m0!, %M1", operands);
break;
+
case POST_DEC:
- output_asm_insn ("stm%?ia\t%m0, %M1", operands);
- output_asm_insn ("sub%?\t%m0, %m0, #8", operands);
+ abort (); /* Should never happen now */
break;
+
+ case PLUS:
+ if (GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
+ {
+ switch (INTVAL (XEXP (XEXP (operands[0], 0), 1)))
+ {
+ case -8:
+ output_asm_insn ("stm%?db\t%m0, %M1", operands);
+ return "";
+
+ case -4:
+ output_asm_insn ("stm%?da\t%m0, %M1", operands);
+ return "";
+
+ case 4:
+ output_asm_insn ("stm%?ib\t%m0, %M1", operands);
+ return "";
+ }
+ }
+ /* Fall through */
+
default:
otherops[0] = adj_offsettable_operand (operands[0], 4);
otherops[1] = gen_rtx (REG, SImode, 1 + REGNO (operands[1]));
@@ -2217,7 +4199,8 @@ output_move_double (operands)
output_asm_insn ("str%?\t%1, %0", otherops);
}
}
- else abort(); /* Constraints should prevent this */
+ else
+ abort(); /* Constraints should prevent this */
return "";
}
@@ -2297,7 +4280,7 @@ output_add_immediate (operands)
IMMED_OP is the index of the constant slot in OPERANDS.
N is the constant value. */
-char *
+static char *
output_multi_immediate (operands, instr1, instr2, immed_op, n)
rtx *operands;
char *instr1, *instr2;
@@ -2448,13 +4431,13 @@ shift_op (op, amountp)
/* Obtain the shift from the POWER of two. */
-HOST_WIDE_INT
+static HOST_WIDE_INT
int_log2 (power)
HOST_WIDE_INT power;
{
HOST_WIDE_INT shift = 0;
- while (((1 << shift) & power) == 0)
+ while (((((HOST_WIDE_INT) 1) << shift) & power) == 0)
{
if (shift > 31)
abort ();
@@ -2487,7 +4470,6 @@ output_ascii_pseudo_op (stream, p, len)
fputs ("\"\n", stream);
fputs ("\t.ascii\t\"", stream);
len_so_far = 0;
- arm_increase_location (chars_so_far);
chars_so_far = 0;
}
@@ -2512,7 +4494,6 @@ output_ascii_pseudo_op (stream, p, len)
}
fputs ("\"\n", stream);
- arm_increase_location (chars_so_far);
}
@@ -2636,6 +4617,10 @@ function_really_clobbers_lr (first)
if ((next = next_nonnote_insn (insn)) == NULL)
return 1;
+ /* No need to worry about lr if the call never returns */
+ if (GET_CODE (next) == BARRIER)
+ break;
+
if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == USE
&& (GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
&& (REGNO (SET_DEST (XVECEXP (PATTERN (insn), 0, 0)))
@@ -2658,9 +4643,10 @@ function_really_clobbers_lr (first)
}
char *
-output_return_instruction (operand, really_return)
+output_return_instruction (operand, really_return, reverse)
rtx operand;
int really_return;
+ int reverse;
{
char instr[100];
int reg, live_regs = 0;
@@ -2680,7 +4666,8 @@ output_return_instruction (operand, really_return)
/* Otherwise, trap an attempted return by aborting. */
ops[0] = operand;
ops[1] = gen_rtx (SYMBOL_REF, Pmode, "abort");
- output_asm_insn ("bl%d0\t%a1", ops);
+ assemble_external_libcall (ops[1]);
+ output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
return "";
}
@@ -2703,9 +4690,11 @@ output_return_instruction (operand, really_return)
live_regs++;
if (frame_pointer_needed)
- strcpy (instr, "ldm%?%d0ea\t%|fp, {");
+ strcpy (instr,
+ reverse ? "ldm%?%D0ea\t%|fp, {" : "ldm%?%d0ea\t%|fp, {");
else
- strcpy (instr, "ldm%?%d0fd\t%|sp!, {");
+ strcpy (instr,
+ reverse ? "ldm%?%D0fd\t%|sp!, {" : "ldm%?%d0fd\t%|sp!, {");
for (reg = 0; reg <= 10; reg++)
if (regs_ever_live[reg] && ! call_used_regs[reg])
@@ -2732,13 +4721,16 @@ output_return_instruction (operand, really_return)
strcat (instr, "%|");
strcat (instr, really_return ? reg_names[15] : reg_names[14]);
}
- strcat (instr, (TARGET_6 || !really_return) ? "}" : "}^");
+ strcat (instr, (TARGET_APCS_32 || !really_return) ? "}" : "}^");
output_asm_insn (instr, &operand);
}
else if (really_return)
{
- strcpy (instr,
- TARGET_6 ? "mov%?%d0\t%|pc, lr" : "mov%?%d0s\t%|pc, %|lr");
+ if (TARGET_THUMB_INTERWORK)
+ sprintf (instr, "bx%%?%%%s\t%%|lr", reverse ? "D" : "d");
+ else
+ sprintf (instr, "mov%%?%%%s0%s\t%%|pc, %%|lr",
+ reverse ? "D" : "d", TARGET_APCS_32 ? "" : "s");
output_asm_insn (instr, &operand);
}
@@ -2757,15 +4749,6 @@ arm_volatile_func ()
return (optimize > 0 && TREE_THIS_VOLATILE (current_function_decl));
}
-/* Return the size of the prologue. It's not too bad if we slightly
- over-estimate. */
-
-static int
-get_prologue_size ()
-{
- return profile_flag ? 12 : 0;
-}
-
/* The amount of stack adjustment that happens here, in output_return and in
output_epilogue must be exactly the same as was calculated during reload,
or things will point to the wrong place. The only time we can safely
@@ -2791,7 +4774,10 @@ output_func_prologue (f, frame_size)
if (arm_ccfsm_state || arm_target_insn)
abort (); /* Sanity check */
-
+
+ if (arm_naked_function_p (current_function_decl))
+ return;
+
return_used_this_function = 0;
lr_save_eliminated = 0;
@@ -2838,6 +4824,12 @@ output_func_prologue (f, frame_size)
if (lr_save_eliminated)
fprintf (f,"\t%s I don't think this function clobbers lr\n",
ASM_COMMENT_START);
+
+#ifdef AOF_ASSEMBLER
+ if (flag_pic)
+ fprintf (f, "\tmov\t%sip, %s%s\n", REGISTER_PREFIX, REGISTER_PREFIX,
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+#endif
}
@@ -2846,28 +4838,31 @@ output_func_epilogue (f, frame_size)
FILE *f;
int frame_size;
{
- int reg, live_regs_mask = 0, code_size = 0;
- /* If we need this then it will always be at lesat this much */
- int floats_offset = 24;
+ int reg, live_regs_mask = 0;
+ /* If we need this then it will always be at least this much */
+ int floats_offset = 12;
rtx operands[3];
int volatile_func = (optimize > 0
&& TREE_THIS_VOLATILE (current_function_decl));
if (use_return_insn() && return_used_this_function)
{
- if (frame_size && !(frame_pointer_needed || TARGET_APCS))
- {
- abort ();
- }
+ if ((frame_size + current_function_outgoing_args_size) != 0
+ && !(frame_pointer_needed || TARGET_APCS))
+ abort ();
goto epilogue_done;
}
+ /* Naked functions don't have epilogues. */
+ if (arm_naked_function_p (current_function_decl))
+ goto epilogue_done;
+
/* A volatile function should never return. Call abort. */
if (volatile_func)
{
rtx op = gen_rtx (SYMBOL_REF, Pmode, "abort");
+ assemble_external_libcall (op);
output_asm_insn ("bl\t%a0", &op);
- code_size = 4;
goto epilogue_done;
}
@@ -2880,73 +4875,166 @@ output_func_epilogue (f, frame_size)
if (frame_pointer_needed)
{
- for (reg = 23; reg > 15; reg--)
- if (regs_ever_live[reg] && ! call_used_regs[reg])
- {
- fprintf (f, "\tldfe\t%s%s, [%sfp, #-%d]\n", REGISTER_PREFIX,
- reg_names[reg], REGISTER_PREFIX, floats_offset);
- floats_offset += 12;
- code_size += 4;
- }
+ if (arm_fpu_arch == FP_SOFT2)
+ {
+ for (reg = 23; reg > 15; reg--)
+ if (regs_ever_live[reg] && ! call_used_regs[reg])
+ {
+ floats_offset += 12;
+ fprintf (f, "\tldfe\t%s%s, [%sfp, #-%d]\n", REGISTER_PREFIX,
+ reg_names[reg], REGISTER_PREFIX, floats_offset);
+ }
+ }
+ else
+ {
+ int start_reg = 23;
+
+ for (reg = 23; reg > 15; reg--)
+ {
+ if (regs_ever_live[reg] && ! call_used_regs[reg])
+ {
+ floats_offset += 12;
+ /* We can't unstack more than four registers at once */
+ if (start_reg - reg == 3)
+ {
+ fprintf (f, "\tlfm\t%s%s, 4, [%sfp, #-%d]\n",
+ REGISTER_PREFIX, reg_names[reg],
+ REGISTER_PREFIX, floats_offset);
+ start_reg = reg - 1;
+ }
+ }
+ else
+ {
+ if (reg != start_reg)
+ fprintf (f, "\tlfm\t%s%s, %d, [%sfp, #-%d]\n",
+ REGISTER_PREFIX, reg_names[reg + 1],
+ start_reg - reg, REGISTER_PREFIX, floats_offset);
- live_regs_mask |= 0xA800;
- print_multi_reg (f, "ldmea\t%sfp", live_regs_mask,
- TARGET_6 ? FALSE : TRUE);
- code_size += 4;
+ start_reg = reg - 1;
+ }
+ }
+
+ /* Just in case the last register checked also needs unstacking. */
+ if (reg != start_reg)
+ fprintf (f, "\tlfm\t%s%s, %d, [%sfp, #-%d]\n",
+ REGISTER_PREFIX, reg_names[reg + 1],
+ start_reg - reg, REGISTER_PREFIX, floats_offset);
+ }
+
+ if (TARGET_THUMB_INTERWORK)
+ {
+ live_regs_mask |= 0x6800;
+ print_multi_reg (f, "ldmea\t%sfp", live_regs_mask, FALSE);
+ fprintf (f, "\tbx\t%slr\n", REGISTER_PREFIX);
+ }
+ else
+ {
+ live_regs_mask |= 0xA800;
+ print_multi_reg (f, "ldmea\t%sfp", live_regs_mask,
+ TARGET_APCS_32 ? FALSE : TRUE);
+ }
}
else
{
/* Restore stack pointer if necessary. */
- if (frame_size)
+ if (frame_size + current_function_outgoing_args_size != 0)
{
operands[0] = operands[1] = stack_pointer_rtx;
- operands[2] = gen_rtx (CONST_INT, VOIDmode, frame_size);
+ operands[2] = GEN_INT (frame_size
+ + current_function_outgoing_args_size);
output_add_immediate (operands);
}
- for (reg = 16; reg < 24; reg++)
- if (regs_ever_live[reg] && ! call_used_regs[reg])
- {
- fprintf (f, "\tldfe\t%s%s, [%ssp], #12\n", REGISTER_PREFIX,
- reg_names[reg], REGISTER_PREFIX);
- code_size += 4;
- }
+ if (arm_fpu_arch == FP_SOFT2)
+ {
+ for (reg = 16; reg < 24; reg++)
+ if (regs_ever_live[reg] && ! call_used_regs[reg])
+ fprintf (f, "\tldfe\t%s%s, [%ssp], #12\n", REGISTER_PREFIX,
+ reg_names[reg], REGISTER_PREFIX);
+ }
+ else
+ {
+ int start_reg = 16;
+
+ for (reg = 16; reg < 24; reg++)
+ {
+ if (regs_ever_live[reg] && ! call_used_regs[reg])
+ {
+ if (reg - start_reg == 3)
+ {
+ fprintf (f, "\tlfmfd\t%s%s, 4, [%ssp]!\n",
+ REGISTER_PREFIX, reg_names[start_reg],
+ REGISTER_PREFIX);
+ start_reg = reg + 1;
+ }
+ }
+ else
+ {
+ if (reg != start_reg)
+ fprintf (f, "\tlfmfd\t%s%s, %d, [%ssp]!\n",
+ REGISTER_PREFIX, reg_names[start_reg],
+ reg - start_reg, REGISTER_PREFIX);
+
+ start_reg = reg + 1;
+ }
+ }
+
+ /* Just in case the last register checked also needs unstacking. */
+ if (reg != start_reg)
+ fprintf (f, "\tlfmfd\t%s%s, %d, [%ssp]!\n",
+ REGISTER_PREFIX, reg_names[start_reg],
+ reg - start_reg, REGISTER_PREFIX);
+ }
+
if (current_function_pretend_args_size == 0 && regs_ever_live[14])
{
- print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask | 0x8000,
- TARGET_6 ? FALSE : TRUE);
- code_size += 4;
+ if (TARGET_THUMB_INTERWORK)
+ {
+ if (! lr_save_eliminated)
+ print_multi_reg(f, "ldmfd\t%ssp!", live_regs_mask | 0x4000,
+ FALSE);
+
+ fprintf (f, "\tbx\t%slr\n", REGISTER_PREFIX);
+ }
+ else if (lr_save_eliminated)
+ fprintf (f, (TARGET_APCS_32 ? "\tmov\t%spc, %slr\n"
+ : "\tmovs\t%spc, %slr\n"),
+ REGISTER_PREFIX, REGISTER_PREFIX, f);
+ else
+ print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask | 0x8000,
+ TARGET_APCS_32 ? FALSE : TRUE);
}
else
{
if (live_regs_mask || regs_ever_live[14])
{
- live_regs_mask |= 0x4000;
- print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE);
- code_size += 4;
+ /* Restore the integer regs, and the return address into lr */
+ if (! lr_save_eliminated)
+ live_regs_mask |= 0x4000;
+
+ if (live_regs_mask != 0)
+ print_multi_reg (f, "ldmfd\t%ssp!", live_regs_mask, FALSE);
}
+
if (current_function_pretend_args_size)
{
+ /* Unwind the pre-pushed regs */
operands[0] = operands[1] = stack_pointer_rtx;
operands[2] = gen_rtx (CONST_INT, VOIDmode,
current_function_pretend_args_size);
output_add_immediate (operands);
}
- fprintf (f,
- TARGET_6 ? "\tmov\t%spc, %slr\n" : "\tmovs\t%spc, %slr\n",
- REGISTER_PREFIX, REGISTER_PREFIX, f);
- code_size += 4;
+ /* And finally, go home */
+ if (TARGET_THUMB_INTERWORK)
+ fprintf (f, "\tbx\t%slr\n", REGISTER_PREFIX);
+ else
+ fprintf (f, (TARGET_APCS_32 ? "\tmov\t%spc, %slr\n"
+ : "\tmovs\t%spc, %slr\n"),
+ REGISTER_PREFIX, REGISTER_PREFIX, f);
}
}
- epilogue_done:
-
- /* insn_addresses isn't allocated when not optimizing */
-
- if (optimize > 0)
- arm_increase_location (code_size
- + insn_addresses[INSN_UID (get_last_insn ())]
- + get_prologue_size ());
+epilogue_done:
current_function_anonymous_args = 0;
}
@@ -2992,6 +5080,32 @@ emit_multi_reg_push (mask)
j++;
}
}
+
+ emit_insn (par);
+}
+
+static void
+emit_sfm (base_reg, count)
+ int base_reg;
+ int count;
+{
+ rtx par;
+ int i;
+
+ par = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count));
+
+ XVECEXP (par, 0, 0) = gen_rtx (SET, VOIDmode,
+ gen_rtx (MEM, BLKmode,
+ gen_rtx (PRE_DEC, BLKmode,
+ stack_pointer_rtx)),
+ gen_rtx (UNSPEC, BLKmode,
+ gen_rtvec (1, gen_rtx (REG, XFmode,
+ base_reg++)),
+ 2));
+ for (i = 1; i < count; i++)
+ XVECEXP (par, 0, i) = gen_rtx (USE, VOIDmode,
+ gen_rtx (REG, XFmode, base_reg++));
+
emit_insn (par);
}
@@ -2999,7 +5113,8 @@ void
arm_expand_prologue ()
{
int reg;
- rtx amount = GEN_INT (- get_frame_size ());
+ rtx amount = GEN_INT (-(get_frame_size ()
+ + current_function_outgoing_args_size));
rtx push_insn;
int num_regs;
int live_regs_mask = 0;
@@ -3007,6 +5122,10 @@ arm_expand_prologue ()
int volatile_func = (optimize > 0
&& TREE_THIS_VOLATILE (current_function_decl));
+ /* Naked functions don't have prologues. */
+ if (arm_naked_function_p (current_function_decl))
+ return;
+
if (current_function_anonymous_args && current_function_pretend_args_size)
store_arg_regs = 1;
@@ -3046,13 +5165,43 @@ arm_expand_prologue ()
/* For now the integer regs are still pushed in output_func_epilogue (). */
if (! volatile_func)
- for (reg = 23; reg > 15; reg--)
- if (regs_ever_live[reg] && ! call_used_regs[reg])
- emit_insn (gen_rtx (SET, VOIDmode,
- gen_rtx (MEM, XFmode,
- gen_rtx (PRE_DEC, XFmode,
- stack_pointer_rtx)),
- gen_rtx (REG, XFmode, reg)));
+ {
+ if (arm_fpu_arch == FP_SOFT2)
+ {
+ for (reg = 23; reg > 15; reg--)
+ if (regs_ever_live[reg] && ! call_used_regs[reg])
+ emit_insn (gen_rtx (SET, VOIDmode,
+ gen_rtx (MEM, XFmode,
+ gen_rtx (PRE_DEC, XFmode,
+ stack_pointer_rtx)),
+ gen_rtx (REG, XFmode, reg)));
+ }
+ else
+ {
+ int start_reg = 23;
+
+ for (reg = 23; reg > 15; reg--)
+ {
+ if (regs_ever_live[reg] && ! call_used_regs[reg])
+ {
+ if (start_reg - reg == 3)
+ {
+ emit_sfm (reg, 4);
+ start_reg = reg - 1;
+ }
+ }
+ else
+ {
+ if (start_reg != reg)
+ emit_sfm (reg + 1, start_reg - reg);
+ start_reg = reg - 1;
+ }
+ }
+
+ if (start_reg != reg)
+ emit_sfm (reg + 1, start_reg - reg);
+ }
+ }
if (frame_pointer_needed)
emit_insn (gen_addsi3 (hard_frame_pointer_rtx, gen_rtx (REG, SImode, 12),
@@ -3163,11 +5312,18 @@ arm_print_operand (stream, x, code)
}
return;
+ case 'Q':
+ if (REGNO (x) > 15)
+ abort ();
+ fputs (REGISTER_PREFIX, stream);
+ fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0)], stream);
+ return;
+
case 'R':
if (REGNO (x) > 15)
abort ();
fputs (REGISTER_PREFIX, stream);
- fputs (reg_names[REGNO (x) + 1], stream);
+ fputs (reg_names[REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1)], stream);
return;
case 'm':
@@ -3193,11 +5349,7 @@ arm_print_operand (stream, x, code)
return;
case 'D':
- if (x && (flag_fast_math
- || GET_CODE (x) == EQ || GET_CODE (x) == NE
- || (GET_MODE (XEXP (x, 0)) != CCFPEmode
- && (GET_MODE_CLASS (GET_MODE (XEXP (x, 0)))
- != MODE_FLOAT))))
+ if (x)
fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
(get_arm_condition_code (x))],
stream);
@@ -3229,157 +5381,6 @@ arm_print_operand (stream, x, code)
}
}
-/* Increase the `arm_text_location' by AMOUNT if we're in the text
- segment. */
-
-void
-arm_increase_location (amount)
- int amount;
-{
- if (in_text_section ())
- arm_text_location += amount;
-}
-
-
-/* Output a label definition. If this label is within the .text segment, it
- is stored in OFFSET_TABLE, to be used when building `llc' instructions.
- Maybe GCC remembers names not starting with a `*' for a long time, but this
- is a minority anyway, so we just make a copy. Do not store the leading `*'
- if the name starts with one. */
-
-void
-arm_asm_output_label (stream, name)
- FILE *stream;
- char *name;
-{
- char *real_name, *s;
- struct label_offset *cur;
- int hash = 0;
-
- assemble_name (stream, name);
- fputs (":\n", stream);
- if (! in_text_section ())
- return;
-
- if (name[0] == '*')
- {
- real_name = xmalloc (1 + strlen (&name[1]));
- strcpy (real_name, &name[1]);
- }
- else
- {
- real_name = xmalloc (2 + strlen (name));
- strcpy (real_name, USER_LABEL_PREFIX);
- strcat (real_name, name);
- }
- for (s = real_name; *s; s++)
- hash += *s;
-
- hash = hash % LABEL_HASH_SIZE;
- cur = (struct label_offset *) xmalloc (sizeof (struct label_offset));
- cur->name = real_name;
- cur->offset = arm_text_location;
- cur->cdr = offset_table[hash];
- offset_table[hash] = cur;
-}
-
-/* Load a symbol that is known to be in the text segment into a register.
- This should never be called when not optimizing. */
-
-char *
-output_load_symbol (insn, operands)
- rtx insn;
- rtx *operands;
-{
- char *s;
- char *name = XSTR (operands[1], 0);
- struct label_offset *he;
- int hash = 0;
- int offset;
- unsigned int mask, never_mask = 0xffffffff;
- int shift, inst;
- char buffer[100];
-
- if (optimize == 0 || *name != '*')
- abort ();
-
- for (s = &name[1]; *s; s++)
- hash += *s;
-
- hash = hash % LABEL_HASH_SIZE;
- he = offset_table[hash];
- while (he && strcmp (he->name, &name[1]))
- he = he->cdr;
-
- if (!he)
- abort ();
-
- offset = (arm_text_location + insn_addresses[INSN_UID (insn)]
- + get_prologue_size () + 8 - he->offset);
- if (offset < 0)
- abort ();
-
- /* When generating the instructions, we never mask out the bits that we
- think will be always zero, then if a mistake has occurred somewhere, the
- assembler will spot it and generate an error. */
-
- /* If the symbol is word aligned then we might be able to reduce the
- number of loads. */
- shift = ((offset & 3) == 0) ? 2 : 0;
-
- /* Clear the bits from NEVER_MASK that will be orred in with the individual
- instructions. */
- for (; shift < 32; shift += 8)
- {
- mask = 0xff << shift;
- if ((offset & mask) || ((unsigned) offset) > mask)
- never_mask &= ~mask;
- }
-
- inst = 8;
- mask = 0xff << (shift - 32);
-
- while (mask && (never_mask & mask) == 0)
- {
- if (inst == 8)
- {
- strcpy (buffer, "sub%?\t%0, %|pc, #(8 + . -%a1)");
- if ((never_mask | mask) != 0xffffffff)
- sprintf (buffer + strlen (buffer), " & 0x%x", mask | never_mask);
- }
- else
- sprintf (buffer, "sub%%?\t%%0, %%0, #(%d + . -%%a1) & 0x%x",
- inst, mask | never_mask);
-
- output_asm_insn (buffer, operands);
- mask <<= 8;
- inst -= 4;
- }
-
- return "";
-}
-
-/* Output code resembling an .lcomm directive. /bin/as doesn't have this
- directive hence this hack, which works by reserving some `.space' in the
- bss segment directly.
-
- XXX This is a severe hack, which is guaranteed NOT to work since it doesn't
- define STATIC COMMON space but merely STATIC BSS space. */
-
-void
-output_lcomm_directive (stream, name, size, rounded)
- FILE *stream;
- char *name;
- int size, rounded;
-{
- fprintf (stream, "\n\t.bss\t%s .lcomm\n", ASM_COMMENT_START);
- assemble_name (stream, name);
- fprintf (stream, ":\t.space\t%d\n", rounded);
- if (in_text_section ())
- fputs ("\n\t.text\n", stream);
- else
- fputs ("\n\t.data\n", stream);
-}
/* A finite state machine takes care of noticing whether or not instructions
can be conditionally executed, and thus decrease execution time and code
@@ -3416,26 +5417,112 @@ output_lcomm_directive (stream, name, size, rounded)
`arm_condition_codes'. COMPARISON should be an rtx like
`(eq (...) (...))'. */
-int
+static enum arm_cond_code
get_arm_condition_code (comparison)
rtx comparison;
{
- switch (GET_CODE (comparison))
- {
- case NE: return (1);
- case EQ: return (0);
- case GE: return (10);
- case GT: return (12);
- case LE: return (13);
- case LT: return (11);
- case GEU: return (2);
- case GTU: return (8);
- case LEU: return (9);
- case LTU: return (3);
+ enum machine_mode mode = GET_MODE (XEXP (comparison, 0));
+ register int code;
+ register enum rtx_code comp_code = GET_CODE (comparison);
+
+ if (GET_MODE_CLASS (mode) != MODE_CC)
+ mode = SELECT_CC_MODE (comp_code, XEXP (comparison, 0),
+ XEXP (comparison, 1));
+
+ switch (mode)
+ {
+ case CC_DNEmode: code = ARM_NE; goto dominance;
+ case CC_DEQmode: code = ARM_EQ; goto dominance;
+ case CC_DGEmode: code = ARM_GE; goto dominance;
+ case CC_DGTmode: code = ARM_GT; goto dominance;
+ case CC_DLEmode: code = ARM_LE; goto dominance;
+ case CC_DLTmode: code = ARM_LT; goto dominance;
+ case CC_DGEUmode: code = ARM_CS; goto dominance;
+ case CC_DGTUmode: code = ARM_HI; goto dominance;
+ case CC_DLEUmode: code = ARM_LS; goto dominance;
+ case CC_DLTUmode: code = ARM_CC;
+
+ dominance:
+ if (comp_code != EQ && comp_code != NE)
+ abort ();
+
+ if (comp_code == EQ)
+ return ARM_INVERSE_CONDITION_CODE (code);
+ return code;
+
+ case CC_NOOVmode:
+ switch (comp_code)
+ {
+ case NE: return ARM_NE;
+ case EQ: return ARM_EQ;
+ case GE: return ARM_PL;
+ case LT: return ARM_MI;
+ default: abort ();
+ }
+
+ case CC_Zmode:
+ case CCFPmode:
+ switch (comp_code)
+ {
+ case NE: return ARM_NE;
+ case EQ: return ARM_EQ;
+ default: abort ();
+ }
+
+ case CCFPEmode:
+ switch (comp_code)
+ {
+ case GE: return ARM_GE;
+ case GT: return ARM_GT;
+ case LE: return ARM_LS;
+ case LT: return ARM_MI;
+ default: abort ();
+ }
+
+ case CC_SWPmode:
+ switch (comp_code)
+ {
+ case NE: return ARM_NE;
+ case EQ: return ARM_EQ;
+ case GE: return ARM_LE;
+ case GT: return ARM_LT;
+ case LE: return ARM_GE;
+ case LT: return ARM_GT;
+ case GEU: return ARM_LS;
+ case GTU: return ARM_CC;
+ case LEU: return ARM_CS;
+ case LTU: return ARM_HI;
+ default: abort ();
+ }
+
+ case CC_Cmode:
+ switch (comp_code)
+ {
+ case LTU: return ARM_CS;
+ case GEU: return ARM_CC;
+ default: abort ();
+ }
+
+ case CCmode:
+ switch (comp_code)
+ {
+ case NE: return ARM_NE;
+ case EQ: return ARM_EQ;
+ case GE: return ARM_GE;
+ case GT: return ARM_GT;
+ case LE: return ARM_LE;
+ case LT: return ARM_LT;
+ case GEU: return ARM_CS;
+ case GTU: return ARM_HI;
+ case LEU: return ARM_LS;
+ case LTU: return ARM_CC;
+ default: abort ();
+ }
+
default: abort ();
}
- /*NOTREACHED*/
- return (42);
+
+ abort ();
}
@@ -3540,7 +5627,8 @@ final_prescan_insn (insn, opvec, noperands)
|| (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
&& GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
{
- int insns_skipped = 0, fail = FALSE, succeed = FALSE;
+ int insns_skipped;
+ int fail = FALSE, succeed = FALSE;
/* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
int then_not_else = TRUE;
rtx this_insn = start_insn, label = 0;
@@ -3581,8 +5669,7 @@ final_prescan_insn (insn, opvec, noperands)
insns are okay, and the label or unconditional branch to the same
label is not too far away, succeed. */
for (insns_skipped = 0;
- !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
- insns_skipped++)
+ !fail && !succeed && insns_skipped++ < MAX_INSNS_SKIPPED;)
{
rtx scanbody;
@@ -3634,11 +5721,34 @@ final_prescan_insn (insn, opvec, noperands)
break;
case CALL_INSN:
- /* The arm 6xx uses full 32 bit addresses so the cc is not
- preserved over calls */
- if (TARGET_6)
- fail = TRUE;
+ /* If using 32-bit addresses the cc is not preserved over
+ calls */
+ if (TARGET_APCS_32)
+ {
+ /* Succeed if the following insn is the target label,
+ or if the following two insns are a barrier and
+ the target label. */
+ this_insn = next_nonnote_insn (this_insn);
+ if (this_insn && GET_CODE (this_insn) == BARRIER)
+ this_insn = next_nonnote_insn (this_insn);
+
+ if (this_insn && this_insn == label
+ && insns_skipped < MAX_INSNS_SKIPPED)
+ {
+ if (jump_clobbers)
+ {
+ arm_ccfsm_state = 2;
+ this_insn = next_nonnote_insn (this_insn);
+ }
+ else
+ arm_ccfsm_state = 1;
+ succeed = TRUE;
+ }
+ else
+ fail = TRUE;
+ }
break;
+
case JUMP_INSN:
/* If this is an unconditional branch to the same label, succeed.
If it is to another label, do nothing. If it is conditional,
@@ -3746,4 +5856,162 @@ final_prescan_insn (insn, opvec, noperands)
}
}
-/* EOF */
+#ifdef AOF_ASSEMBLER
+/* Special functions only needed when producing AOF syntax assembler. */
+
+rtx aof_pic_label = NULL_RTX;
+struct pic_chain
+{
+ struct pic_chain *next;
+ char *symname;
+};
+
+static struct pic_chain *aof_pic_chain = NULL;
+
+rtx
+aof_pic_entry (x)
+ rtx x;
+{
+ struct pic_chain **chainp;
+ int offset;
+
+ if (aof_pic_label == NULL_RTX)
+ {
+ /* This needs to persist throughout the compilation. */
+ end_temporary_allocation ();
+ aof_pic_label = gen_rtx (SYMBOL_REF, Pmode, "x$adcons");
+ resume_temporary_allocation ();
+ }
+
+ for (offset = 0, chainp = &aof_pic_chain; *chainp;
+ offset += 4, chainp = &(*chainp)->next)
+ if ((*chainp)->symname == XSTR (x, 0))
+ return plus_constant (aof_pic_label, offset);
+
+ *chainp = (struct pic_chain *) xmalloc (sizeof (struct pic_chain));
+ (*chainp)->next = NULL;
+ (*chainp)->symname = XSTR (x, 0);
+ return plus_constant (aof_pic_label, offset);
+}
+
+void
+aof_dump_pic_table (f)
+ FILE *f;
+{
+ struct pic_chain *chain;
+
+ if (aof_pic_chain == NULL)
+ return;
+
+ fprintf (f, "\tAREA |%s$$adcons|, BASED %s%s\n",
+ reg_names[PIC_OFFSET_TABLE_REGNUM], REGISTER_PREFIX,
+ reg_names[PIC_OFFSET_TABLE_REGNUM]);
+ fputs ("|x$adcons|\n", f);
+
+ for (chain = aof_pic_chain; chain; chain = chain->next)
+ {
+ fputs ("\tDCD\t", f);
+ assemble_name (f, chain->symname);
+ fputs ("\n", f);
+ }
+}
+
+int arm_text_section_count = 1;
+
+char *
+aof_text_section ()
+{
+ static char buf[100];
+ sprintf (buf, "\tAREA |C$$code%d|, CODE, READONLY",
+ arm_text_section_count++);
+ if (flag_pic)
+ strcat (buf, ", PIC, REENTRANT");
+ return buf;
+}
+
+static int arm_data_section_count = 1;
+
+char *
+aof_data_section ()
+{
+ static char buf[100];
+ sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
+ return buf;
+}
+
+/* The AOF assembler is religiously strict about declarations of
+ imported and exported symbols, so that it is impossible to declare
+ a function as imported near the beginning of the file, and then to
+ export it later on. It is, however, possible to delay the decision
+ until all the functions in the file have been compiled. To get
+ around this, we maintain a list of the imports and exports, and
+ delete from it any that are subsequently defined. At the end of
+ compilation we spit the remainder of the list out before the END
+ directive. */
+
+struct import
+{
+ struct import *next;
+ char *name;
+};
+
+static struct import *imports_list = NULL;
+
+void
+aof_add_import (name)
+ char *name;
+{
+ struct import *new;
+
+ for (new = imports_list; new; new = new->next)
+ if (new->name == name)
+ return;
+
+ new = (struct import *) xmalloc (sizeof (struct import));
+ new->next = imports_list;
+ imports_list = new;
+ new->name = name;
+}
+
+void
+aof_delete_import (name)
+ char *name;
+{
+ struct import **old;
+
+ for (old = &imports_list; *old; old = & (*old)->next)
+ {
+ if ((*old)->name == name)
+ {
+ *old = (*old)->next;
+ return;
+ }
+ }
+}
+
+int arm_main_function = 0;
+
+void
+aof_dump_imports (f)
+ FILE *f;
+{
+ /* The AOF assembler needs this to cause the startup code to be extracted
+ from the library. Brining in __main causes the whole thing to work
+ automagically. */
+ if (arm_main_function)
+ {
+ text_section ();
+ fputs ("\tIMPORT __main\n", f);
+ fputs ("\tDCD __main\n", f);
+ }
+
+ /* Now dump the remaining imports. */
+ while (imports_list)
+ {
+ fprintf (f, "\tIMPORT\t");
+ assemble_name (f, imports_list->name);
+ fputc ('\n', f);
+ imports_list = imports_list->next;
+ }
+}
+#endif /* AOF_ASSEMBLER */
diff --git a/gnu/usr.bin/gcc/config/arm/arm.h b/gnu/usr.bin/gcc/config/arm/arm.h
index db5ffdead35..17c9f7edef5 100644
--- a/gnu/usr.bin/gcc/config/arm/arm.h
+++ b/gnu/usr.bin/gcc/config/arm/arm.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for Acorn RISC Machine.
- Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rwe11@cl.cam.ac.uk)
@@ -21,43 +21,221 @@ 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. */
-/* Sometimes the directive `riscos' is checked. This does not imply that this
- tm file can be used unchanged to build a GCC for RISC OS.
- (Since in fact, it can't.) */
-
-extern void output_func_prologue ();
-extern void output_func_epilogue ();
-extern char *output_add_immediate ();
-extern char *output_call ();
-extern char *output_call_mem ();
-extern char *output_move_double ();
-extern char *output_mov_double_fpu_from_arm ();
-extern char *output_mov_double_arm_from_fpu ();
-extern char *output_mov_long_double_fpu_from_arm ();
-extern char *output_mov_long_double_arm_from_fpu ();
-extern char *output_mov_long_double_arm_from_arm ();
-extern char *output_mov_immediate ();
-extern char *output_multi_immediate ();
-extern char *output_return_instruction ();
-extern char *output_load_symbol ();
-extern char *fp_immediate_constant ();
-extern struct rtx_def *gen_compare_reg ();
-extern struct rtx_def *arm_gen_store_multiple ();
-extern struct rtx_def *arm_gen_load_multiple ();
-
+/* Configuration triples for ARM ports work as follows:
+ (This is a bit of a mess and needs some thought)
+ arm-*-*: little endian
+ armel-*-*: little endian
+ armeb-*-*: big endian
+ If a non-embedded environment (ie: "real" OS) is specified, `arm'
+ should default to that used by the OS.
+*/
+
+#define TARGET_CPU_arm2 0x0000
+#define TARGET_CPU_arm250 0x0000
+#define TARGET_CPU_arm3 0x0000
+#define TARGET_CPU_arm6 0x0001
+#define TARGET_CPU_arm600 0x0001
+#define TARGET_CPU_arm610 0x0002
+#define TARGET_CPU_arm7 0x0001
+#define TARGET_CPU_arm7m 0x0004
+#define TARGET_CPU_arm7dm 0x0004
+#define TARGET_CPU_arm7dmi 0x0004
+#define TARGET_CPU_arm700 0x0001
+#define TARGET_CPU_arm710 0x0002
+#define TARGET_CPU_arm7100 0x0002
+#define TARGET_CPU_arm7500 0x0002
+#define TARGET_CPU_arm7500fe 0x1001
+#define TARGET_CPU_arm7tdmi 0x0008
+#define TARGET_CPU_arm8 0x0010
+#define TARGET_CPU_arm810 0x0020
+#define TARGET_CPU_strongarm 0x0040
+#define TARGET_CPU_strongarm110 0x0040
+/* Configure didn't specify */
+#define TARGET_CPU_generic 0x8000
+
+enum arm_cond_code
+{
+ ARM_EQ = 0, ARM_NE, ARM_CS, ARM_CC, ARM_MI, ARM_PL, ARM_VS, ARM_VC,
+ ARM_HI, ARM_LS, ARM_GE, ARM_LT, ARM_GT, ARM_LE, ARM_AL, ARM_NV
+};
+extern enum arm_cond_code arm_current_cc;
extern char *arm_condition_codes[];
+#define ARM_INVERSE_CONDITION_CODE(X) ((enum arm_cond_code) (((int)X) ^ 1))
+
/* This is needed by the tail-calling peepholes */
extern int frame_pointer_needed;
+/* Just in case configure has failed to define anything. */
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT TARGET_CPU_generic
+#endif
+
+/* If the configuration file doesn't specify the cpu, the subtarget may
+ override it. If it doesn't, then default to an ARM6. */
+#if TARGET_CPU_DEFAULT == TARGET_CPU_generic
+#undef TARGET_CPU_DEFAULT
+#ifdef SUBTARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT SUBTARGET_CPU_DEFAULT
+#else
+#define TARGET_CPU_DEFAULT TARGET_CPU_arm6
+#endif
+#endif
+
+#if TARGET_CPU_DEFAULT == TARGET_CPU_arm2
+#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_2__"
+#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_arm6 || TARGET_CPU_DEFAULT == TARGET_CPU_arm610 || TARGET_CPU_DEFAULT == TARGET_CPU_arm7500fe
+#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_3__"
+#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_arm7m
+#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_3M__"
+#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_arm7tdmi
+#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4T__"
+#else
+#if TARGET_CPU_DEFAULT == TARGET_CPU_arm8 || TARGET_CPU_DEFAULT == TARGET_CPU_arm810 || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm
+#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4__"
+#else
+Unrecognized value in TARGET_CPU_DEFAULT.
+#endif
+#endif
+#endif
+#endif
+#endif
+
#ifndef CPP_PREDEFINES
#define CPP_PREDEFINES "-Darm -Acpu(arm) -Amachine(arm)"
#endif
-#ifndef CPP_SPEC
-#define CPP_SPEC "%{m6:-D__arm6__}"
-#endif
+#define CPP_SPEC "\
+%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) \
+%(cpp_endian) %(subtarget_cpp_spec)"
+
+/* Set the architecture define -- if -march= is set, then it overrides
+ the -mcpu= setting. */
+#define CPP_CPU_ARCH_SPEC "\
+%{m2:-D__arm2__ -D__ARM_ARCH_2__} \
+%{m3:-D__arm2__ -D__ARM_ARCH_2__} \
+%{m6:-D__arm6__ -D__ARM_ARCH_3__} \
+%{march=arm2:-D__ARM_ARCH_2__} \
+%{march=arm250:-D__ARM_ARCH_2__} \
+%{march=arm3:-D__ARM_ARCH_2__} \
+%{march=arm6:-D__ARM_ARCH_3__} \
+%{march=arm600:-D__ARM_ARCH_3__} \
+%{march=arm610:-D__ARM_ARCH_3__} \
+%{march=arm7:-D__ARM_ARCH_3__} \
+%{march=arm700:-D__ARM_ARCH_3__} \
+%{march=arm710:-D__ARM_ARCH_3__} \
+%{march=arm7100:-D__ARM_ARCH_3__} \
+%{march=arm7500:-D__ARM_ARCH_3__} \
+%{march=arm7500fe:-D__ARM_ARCH_3__} \
+%{march=arm7m:-D__ARM_ARCH_3M__} \
+%{march=arm7dm:-D__ARM_ARCH_3M__} \
+%{march=arm7dmi:-D__ARM_ARCH_3M__} \
+%{march=arm7tdmi:-D__ARM_ARCH_4T__} \
+%{march=arm8:-D__ARM_ARCH_4__} \
+%{march=arm810:-D__ARM_ARCH_4__} \
+%{march=strongarm:-D__ARM_ARCH_4__} \
+%{march=strongarm110:-D__ARM_ARCH_4__} \
+%{march=armv2:-D__ARM_ARCH_2__} \
+%{march=armv2a:-D__ARM_ARCH_2__} \
+%{march=armv3:-D__ARM_ARCH_3__} \
+%{march=armv3m:-D__ARM_ARCH_3M__} \
+%{march=armv4:-D__ARM_ARCH_4__} \
+%{march=armv4t:-D__ARM_ARCH_4T__} \
+%{!march=*: \
+ %{mcpu=arm2:-D__ARM_ARCH_2__} \
+ %{mcpu=arm250:-D__ARM_ARCH_2__} \
+ %{mcpu=arm3:-D__ARM_ARCH_2__} \
+ %{mcpu=arm6:-D__ARM_ARCH_3__} \
+ %{mcpu=arm600:-D__ARM_ARCH_3__} \
+ %{mcpu=arm610:-D__ARM_ARCH_3__} \
+ %{mcpu=arm7:-D__ARM_ARCH_3__} \
+ %{mcpu=arm700:-D__ARM_ARCH_3__} \
+ %{mcpu=arm710:-D__ARM_ARCH_3__} \
+ %{mcpu=arm7100:-D__ARM_ARCH_3__} \
+ %{mcpu=arm7500:-D__ARM_ARCH_3__} \
+ %{mcpu=arm7500fe:-D__ARM_ARCH_3__} \
+ %{mcpu=arm7m:-D__ARM_ARCH_3M__} \
+ %{mcpu=arm7dm:-D__ARM_ARCH_3M__} \
+ %{mcpu=arm7dmi:-D__ARM_ARCH_3M__} \
+ %{mcpu=arm7tdmi:-D__ARM_ARCH_4T__} \
+ %{mcpu=arm8:-D__ARM_ARCH_4__} \
+ %{mcpu=arm810:-D__ARM_ARCH_4__} \
+ %{mcpu=strongarm:-D__ARM_ARCH_4__} \
+ %{mcpu=strongarm110:-D__ARM_ARCH_4__} \
+ %{!mcpu*:%{!m6:%{!m2:%{!m3:%(cpp_cpu_arch_default)}}}}} \
+"
+
+/* Define __APCS_26__ if the PC also contains the PSR */
+/* This also examines deprecated -m[236] if neither of -mapcs-{26,32} is set,
+ ??? Delete this for 2.9. */
+#define CPP_APCS_PC_SPEC "\
+%{mapcs-32:%{mapcs-26:%e-mapcs-26 and -mapcs-32 may not be used together} \
+ -D__APCS_32__} \
+%{mapcs-26:-D__APCS_26__} \
+%{!mapcs-32: %{!mapcs-26:%{m6:-D__APCS_32__} %{m2:-D__APCS_26__} \
+ %{m3:-D__APCS_26__} %{!m6:%{!m3:%{!m2:%(cpp_apcs_pc_default)}}}}} \
+"
+
+#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_26__"
+
+#define CPP_FLOAT_SPEC "\
+%{msoft-float:\
+ %{mhard-float:%e-msoft-float and -mhard_float may not be used together} \
+ -D__SOFTFP__} \
+%{!mhard-float:%{!msoft-float:%(cpp_float_default)}} \
+"
+
+/* Default is hard float, which doesn't define anything */
+#define CPP_FLOAT_DEFAULT_SPEC ""
+
+#define CPP_ENDIAN_SPEC "\
+%{mbig-endian: \
+ %{mlittle-endian: \
+ %e-mbig-endian and -mlittle-endian may not be used together} \
+ -D__ARMEB__ %{mwords-little-endian:-D__ARMWEL__}} \
+%{!mlittle-endian:%{!mbig-endian:%(cpp_endian_default)}} \
+"
+
+/* Default is little endian, which doesn't define anything. */
+#define CPP_ENDIAN_DEFAULT_SPEC ""
+
+/* Translate (for now) the old -m[236] option into the appropriate -mcpu=...
+ and -mapcs-xx equivalents.
+ ??? Remove support for this style in 2.9.*/
+#define CC1_SPEC "\
+%{m2:-mcpu=arm2 -mapcs-26} \
+%{m3:-mcpu=arm3 -mapcs-26} \
+%{m6:-mcpu=arm6 -mapcs-32} \
+"
+
+/* 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_arch", CPP_CPU_ARCH_SPEC }, \
+ { "cpp_cpu_arch_default", CPP_ARCH_DEFAULT_SPEC }, \
+ { "cpp_apcs_pc", CPP_APCS_PC_SPEC }, \
+ { "cpp_apcs_pc_default", CPP_APCS_PC_DEFAULT_SPEC }, \
+ { "cpp_float", CPP_FLOAT_SPEC }, \
+ { "cpp_float_default", CPP_FLOAT_DEFAULT_SPEC }, \
+ { "cpp_endian", CPP_ENDIAN_SPEC }, \
+ { "cpp_endian_default", CPP_ENDIAN_DEFAULT_SPEC }, \
+ { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
+
+#define SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_CPP_SPEC ""
+
/* Run-time Target Specification. */
#ifndef TARGET_VERSION
@@ -65,40 +243,85 @@ extern int frame_pointer_needed;
fputs (" (ARM/generic)", stderr);
#endif
-/* Run-time compilation parameters selecting different hardware subsets.
- On the ARM, misuse it in a different way. */
+/* Run-time compilation parameters selecting different hardware subsets. */
extern int target_flags;
+/* The floating point instruction architecture, can be 2 or 3 */
+extern char *target_fp_name;
+
/* Nonzero if the function prologue (and epilogue) should obey
the ARM Procedure Call Standard. */
-#define TARGET_APCS (target_flags & 1)
+#define ARM_FLAG_APCS_FRAME (0x0001)
/* Nonzero if the function prologue should output the function name to enable
the post mortem debugger to print a backtrace (very useful on RISCOS,
- unused on RISCiX). Specifying this flag also enables -mapcs.
+ unused on RISCiX). Specifying this flag also enables
+ -fno-omit-frame-pointer.
XXX Must still be implemented in the prologue. */
-#define TARGET_POKE_FUNCTION_NAME (target_flags & 2)
+#define ARM_FLAG_POKE (0x0002)
/* Nonzero if floating point instructions are emulated by the FPE, in which
case instruction scheduling becomes very uninteresting. */
-#define TARGET_FPE (target_flags & 4)
+#define ARM_FLAG_FPE (0x0004)
/* Nonzero if destined for an ARM6xx. Takes out bits that assume restoration
of condition flags when returning from a branch & link (ie. a function) */
-#define TARGET_6 (target_flags & 8)
-
-/* Leave some bits for new processor variants */
-
-/* Nonzero if shorts must be loaded byte at a time. This is not necessary
- for the arm processor chip, but it is needed for some MMU chips. */
-#define TARGET_SHORT_BY_BYTES (target_flags & 0x200)
-
-/* Nonzero if GCC should use a floating point library.
- GCC will assume the fp regs don't exist and will not emit any fp insns.
- Note that this is different than fp emulation which still uses fp regs
- and insns - the kernel catches the trap and performs the operation. */
-#define TARGET_SOFT_FLOAT (target_flags & 0x400)
-#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
+/* ********* DEPRECATED ******** */
+#define ARM_FLAG_ARM6 (0x0008)
+
+/* ********* DEPRECATED ******** */
+#define ARM_FLAG_ARM3 (0x0010)
+
+/* Nonzero if destined for a processor in 32-bit program mode. Takes out bit
+ that assume restoration of the condition flags when returning from a
+ branch and link (ie a function). */
+#define ARM_FLAG_APCS_32 (0x0020)
+
+/* Nonzero if stack checking should be performed on entry to each function
+ which allocates temporary variables on the stack. */
+#define ARM_FLAG_APCS_STACK (0x0040)
+
+/* Nonzero if floating point parameters should be passed to functions in
+ floating point registers. */
+#define ARM_FLAG_APCS_FLOAT (0x0080)
+
+/* Nonzero if re-entrant, position independent code should be generated.
+ This is equivalent to -fpic. */
+#define ARM_FLAG_APCS_REENT (0x0100)
+
+/* Nonzero if the MMU will trap unaligned word accesses, so shorts must be
+ loaded byte-at-a-time. */
+#define ARM_FLAG_SHORT_BYTE (0x0200)
+
+/* Nonzero if all floating point instructions are missing (and there is no
+ emulator either). Generate function calls for all ops in this case. */
+#define ARM_FLAG_SOFT_FLOAT (0x0400)
+
+/* Nonzero if we should compile with BYTES_BIG_ENDIAN set to 1. */
+#define ARM_FLAG_BIG_END (0x0800)
+
+/* Nonzero if we should compile for Thumb interworking. */
+#define ARM_FLAG_THUMB (0x1000)
+
+/* Nonzero if we should have little-endian words even when compiling for
+ big-endian (for backwards compatibility with older versions of GCC). */
+#define ARM_FLAG_LITTLE_WORDS (0x2000)
+
+#define TARGET_APCS (target_flags & ARM_FLAG_APCS_FRAME)
+#define TARGET_POKE_FUNCTION_NAME (target_flags & ARM_FLAG_POKE)
+#define TARGET_FPE (target_flags & ARM_FLAG_FPE)
+#define TARGET_6 (target_flags & ARM_FLAG_ARM6)
+#define TARGET_3 (target_flags & ARM_FLAG_ARM3)
+#define TARGET_APCS_32 (target_flags & ARM_FLAG_APCS_32)
+#define TARGET_APCS_STACK (target_flags & ARM_FLAG_APCS_STACK)
+#define TARGET_APCS_FLOAT (target_flags & ARM_FLAG_APCS_FLOAT)
+#define TARGET_APCS_REENT (target_flags & ARM_FLAG_APCS_REENT)
+#define TARGET_SHORT_BY_BYTES (target_flags & ARM_FLAG_SHORT_BYTE)
+#define TARGET_SOFT_FLOAT (target_flags & ARM_FLAG_SOFT_FLOAT)
+#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
+#define TARGET_BIG_END (target_flags & ARM_FLAG_BIG_END)
+#define TARGET_THUMB_INTERWORK (target_flags & ARM_FLAG_THUMB)
+#define TARGET_LITTLE_WORDS (target_flags & ARM_FLAG_LITTLE_WORDS)
/* SUBTARGET_SWITCHES is used to add flags on a per-config basis.
Bit 31 is reserved. See riscix.h. */
@@ -108,75 +331,135 @@ extern int target_flags;
#define TARGET_SWITCHES \
{ \
- {"apcs", 1}, \
- {"poke-function-name", 2}, \
- {"fpe", 4}, \
- {"6", 8}, \
- {"2", -8}, \
- {"3", -8}, \
- {"short-load-bytes", (0x200)}, \
- {"no-short-load-bytes", -(0x200)}, \
- {"short-load-words", -(0x200)}, \
- {"no-short-load-words", (0x200)}, \
- {"soft-float", (0x400)}, \
- {"hard-float", -(0x400)}, \
+ {"apcs", ARM_FLAG_APCS_FRAME}, \
+ {"apcs-frame", ARM_FLAG_APCS_FRAME}, \
+ {"no-apcs-frame", -ARM_FLAG_APCS_FRAME}, \
+ {"poke-function-name", ARM_FLAG_POKE}, \
+ {"fpe", ARM_FLAG_FPE}, \
+ {"6", ARM_FLAG_ARM6}, \
+ {"2", ARM_FLAG_ARM3}, \
+ {"3", ARM_FLAG_ARM3}, \
+ {"apcs-32", ARM_FLAG_APCS_32}, \
+ {"apcs-26", -ARM_FLAG_APCS_32}, \
+ {"apcs-stack-check", ARM_FLAG_APCS_STACK}, \
+ {"no-apcs-stack-check", -ARM_FLAG_APCS_STACK}, \
+ {"apcs-float", ARM_FLAG_APCS_FLOAT}, \
+ {"no-apcs-float", -ARM_FLAG_APCS_FLOAT}, \
+ {"apcs-reentrant", ARM_FLAG_APCS_REENT}, \
+ {"no-apcs-reentrant", -ARM_FLAG_APCS_REENT}, \
+ {"short-load-bytes", ARM_FLAG_SHORT_BYTE}, \
+ {"no-short-load-bytes", -ARM_FLAG_SHORT_BYTE}, \
+ {"short-load-words", -ARM_FLAG_SHORT_BYTE}, \
+ {"no-short-load-words", ARM_FLAG_SHORT_BYTE}, \
+ {"soft-float", ARM_FLAG_SOFT_FLOAT}, \
+ {"hard-float", -ARM_FLAG_SOFT_FLOAT}, \
+ {"big-endian", ARM_FLAG_BIG_END}, \
+ {"little-endian", -ARM_FLAG_BIG_END}, \
+ {"thumb-interwork", ARM_FLAG_THUMB}, \
+ {"no-thumb-interwork", -ARM_FLAG_THUMB}, \
+ {"words-little-endian", ARM_FLAG_LITTLE_WORDS}, \
SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT } \
+ {"", TARGET_DEFAULT } \
+}
+
+#define TARGET_OPTIONS \
+{ \
+ {"cpu=", &arm_select[1].string}, \
+ {"arch=", &arm_select[2].string}, \
+ {"tune=", &arm_select[3].string}, \
+ {"fp=", &target_fp_name} \
}
-/* Which processor we are running on. Currently this is only used to
- get the condition code clobbering attribute right when we are running on
- an arm 6 */
+/* arm_select[0] is reserved for the default cpu. */
+struct arm_cpu_select
+{
+ char *string;
+ char *name;
+ int set_tune_p;
+ int set_arch_p;
+};
+extern struct arm_cpu_select arm_select[];
+
+#ifndef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_ARM2
+#endif
+
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT ((char *) 0)
+#endif
+
+/* Which processor we are running on, for instruction scheduling
+ purposes. */
enum processor_type
{
PROCESSOR_ARM2,
PROCESSOR_ARM3,
- PROCESSOR_ARM6
+ PROCESSOR_ARM6,
+ PROCESSOR_ARM7,
+ PROCESSOR_ARM8,
+ PROCESSOR_STARM,
+ PROCESSOR_NONE /* NOTE: This must be last, since it doesn't
+ appear in the attr_cpu list */
};
-/* Recast the cpu class to be the cpu attribute. */
-
/* Recast the cpu class to be the cpu attribute. */
#define arm_cpu_attr ((enum attr_cpu)arm_cpu)
extern enum processor_type arm_cpu;
-/* What sort of floating point unit do we have? Hardware or software. */
+enum prog_mode_type
+{
+ prog_mode26,
+ prog_mode32
+};
+
+/* Recast the program mode class to be the prog_mode attribute */
+#define arm_prog_mode ((enum attr_prog_mode) arm_prgmode)
+
+extern enum prog_mode_type arm_prgmode;
+
+/* What sort of floating point unit do we have? Hardware or software.
+ If software, is it issue 2 or issue 3? */
enum floating_point_type
{
FP_HARD,
- FP_SOFT
+ FP_SOFT2,
+ FP_SOFT3
};
/* Recast the floating point class to be the floating point attribute. */
#define arm_fpu_attr ((enum attr_fpu) arm_fpu)
+/* What type of floating point to tune for */
extern enum floating_point_type arm_fpu;
+/* What type of floating point instructions are available */
+extern enum floating_point_type arm_fpu_arch;
+
+/* Default floating point architecture. Override in sub-target if
+ necessary. */
+#define FP_DEFAULT FP_SOFT2
+
+/* Nonzero if the processor has a fast multiply insn, and one that does
+ a 64-bit multiply of two 32-bit values. */
+extern int arm_fast_multiply;
+
+/* Nonzero if this chip supports the ARM Architecture 4 extensions */
+extern int arm_arch4;
+
#ifndef TARGET_DEFAULT
#define TARGET_DEFAULT 0
#endif
-#define TARGET_MEM_FUNCTIONS 1
+/* The frame pointer register used in gcc has nothing to do with debugging;
+ that is controlled by the APCS-FRAME option. */
+/* Not fully implemented yet */
+/* #define CAN_DEBUG_WITHOUT_FP 1 */
-/* OVERRIDE_OPTIONS takes care of the following:
- - if -mpoke-function-name, then -mapcs.
- - if doing debugging, then -mapcs; if RISCOS, then -mpoke-function-name.
- - if floating point is done by emulation, forget about instruction
- scheduling. Note that this only saves compilation time; it doesn't
- matter for the final code. */
+#define TARGET_MEM_FUNCTIONS 1
-#define OVERRIDE_OPTIONS \
-{ \
- if (write_symbols != NO_DEBUG && flag_omit_frame_pointer) \
- warning ("-g without a frame pointer may not give sensible debugging");\
- if (TARGET_POKE_FUNCTION_NAME) \
- target_flags |= 1; \
- if (TARGET_FPE) \
- flag_schedule_insns = flag_schedule_insns_after_reload = 0; \
- arm_cpu = TARGET_6 ? PROCESSOR_ARM6: PROCESSOR_ARM2; \
-}
+#define OVERRIDE_OPTIONS arm_override_options ()
/* Target machine storage Layout. */
@@ -200,6 +483,11 @@ extern enum floating_point_type arm_fpu;
(MODE) = SImode; \
}
+/* Define this macro if the promotion described by `PROMOTE_MODE'
+ should also be done for outgoing function arguments. */
+/* This is required to ensure that push insns always push a word. */
+#define PROMOTE_FUNCTION_ARGS
+
/* Define for XFmode extended real floating point support.
This will automatically cause REAL_ARITHMETIC to be defined. */
/* For the ARM:
@@ -230,13 +518,23 @@ extern enum floating_point_type arm_fpu;
Most ARM processors are run in little endian mode, so that is the default.
If you want to have it run-time selectable, change the definition in a
cover file to be TARGET_BIG_ENDIAN. */
-#define BYTES_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN (TARGET_BIG_END != 0)
/* Define this if most significant word of a multiword number is the lowest
- numbered. */
-#define WORDS_BIG_ENDIAN 0
+ numbered.
+ This is always false, even when in big-endian mode. */
+#define WORDS_BIG_ENDIAN (BYTES_BIG_ENDIAN && ! TARGET_LITTLE_WORDS)
+
+/* LIBGCC2_WORDS_BIG_ENDIAN has to be a constant, so we define this based
+ on processor pre-defineds when compiling libgcc2.c. */
+#if defined(__ARMEB__) && !defined(__ARMWEL__)
+#define LIBGCC2_WORDS_BIG_ENDIAN 1
+#else
+#define LIBGCC2_WORDS_BIG_ENDIAN 0
+#endif
-/* Define this if most significant word of doubles is the lowest numbered */
+/* Define this if most significant word of doubles is the lowest numbered.
+ This is always true, even when in little-endian mode. */
#define FLOAT_WORDS_BIG_ENDIAN 1
/* Number of bits in an addressable storage unit */
@@ -264,6 +562,9 @@ extern enum floating_point_type arm_fpu;
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
/* Every structures size must be a multiple of 32 bits. */
+/* This is for compatibility with ARMCC. ARM SDT Reference Manual
+ (ARM DUI 0020D) page 2-20 says "Structures are aligned on word
+ boundaries". */
#define STRUCTURE_SIZE_BOUNDARY 32
/* Non-zero if move instructions will actually fail to work
@@ -272,9 +573,6 @@ extern enum floating_point_type arm_fpu;
#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
-/* Define number of bits in most basic integer type.
- (If undefined, default is BITS_PER_WORD). */
-/* #define INT_TYPE_SIZE */
/* Standard register usage. */
@@ -377,6 +675,11 @@ extern enum floating_point_type arm_fpu;
for (regno = 16; regno < 24; ++regno) \
fixed_regs[regno] = call_used_regs[regno] = 1; \
} \
+ if (flag_pic) \
+ { \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 0; \
+ } \
}
/* Return number of consecutive hard regs needed starting at reg REGNO
@@ -542,12 +845,13 @@ enum reg_class
address. This means that the symbol is in the text segment and can be
accessed without using a load. */
-#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
- : (C) == 'R' ? (GET_CODE (OP) == MEM \
- && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF \
- && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) \
- : (C) == 'S' ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) : 0)
+#define EXTRA_CONSTRAINT(OP, C) \
+ ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
+ : (C) == 'R' ? (GET_CODE (OP) == MEM \
+ && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF \
+ && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) \
+ : (C) == 'S' ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) \
+ : 0)
/* Constant letter 'G' for the FPU immediate constants.
'H' means the same constant negated. */
@@ -564,11 +868,9 @@ enum reg_class
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
- (((MODE) == DFmode && (CLASS) == GENERAL_REGS \
- && true_regnum (X) == -1 && TARGET_HARD_FLOAT) \
- ? GENERAL_REGS \
- : ((MODE) == HImode && true_regnum (X) == -1) ? GENERAL_REGS : NO_REGS)
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
+ (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
+ ? GENERAL_REGS : NO_REGS)
/* If we need to load shorts byte-at-a-time, then we need a scratch. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X) \
@@ -608,7 +910,13 @@ enum reg_class
/* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by. */
-#define PUSH_ROUNDING(NPUSHED) (((NPUSHED) + 3) & ~3)
+/* The push insns do not do this rounding implicitly. So don't define this. */
+/* #define PUSH_ROUNDING(NPUSHED) (((NPUSHED) + 3) & ~3) */
+
+/* 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. */
+#define ACCUMULATE_OUTGOING_ARGS
/* Offset of first parameter from the argument pointer register value. */
#define FIRST_PARM_OFFSET(FNDECL) 4
@@ -645,6 +953,18 @@ enum reg_class
#define FUNCTION_VALUE_REGNO_P(REGNO) \
((REGNO) == 0 || ((REGNO) == 16) && TARGET_HARD_FLOAT)
+/* How large values are returned */
+/* A C expression which can inhibit the returning of certain function values
+ in registers, based on the type of value. */
+#define RETURN_IN_MEMORY(TYPE) \
+ (TYPE_MODE ((TYPE)) == BLKmode || \
+ (AGGREGATE_TYPE_P ((TYPE)) && arm_return_in_memory ((TYPE))))
+
+/* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
+ values must be in memory. On the ARM, they need only do so if larger
+ than a word, or if they contain elements offset from zero in the struct. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
/* Define where to put the arguments to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
@@ -688,7 +1008,7 @@ enum reg_class
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0.
On the ARM, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
((CUM) = (((FNTYPE) && aggregate_value_p (TREE_TYPE ((FNTYPE)))) ? 4 : 0))
/* Update the data in CUM to advance over an argument
@@ -730,7 +1050,7 @@ enum reg_class
output_func_prologue ((STREAM), (SIZE))
/* Call the function profiler with a given profile label. The Acorn compiler
- puts this BEFORE the prolog but gcc pust it afterwards. The ``mov ip,lr''
+ puts this BEFORE the prolog but gcc puts it afterwards. The ``mov ip,lr''
seems like a good idea to stick with cc convention. ``prof'' doesn't seem
to mind about this! */
#define FUNCTION_PROFILER(STREAM,LABELNO) \
@@ -793,8 +1113,10 @@ enum reg_class
int volatile_func = arm_volatile_func (); \
if ((FROM) == ARG_POINTER_REGNUM && (TO) == HARD_FRAME_POINTER_REGNUM)\
(OFFSET) = 0; \
- else if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM)\
- (OFFSET) = (get_frame_size () + 3 & ~3); \
+ else if ((FROM) == FRAME_POINTER_REGNUM \
+ && (TO) == STACK_POINTER_REGNUM) \
+ (OFFSET) = (current_function_outgoing_args_size \
+ + (get_frame_size () + 3 & ~3)); \
else \
{ \
int regno; \
@@ -816,8 +1138,10 @@ enum reg_class
{ \
if (! frame_pointer_needed) \
offset -= 16; \
- if (! volatile_func && (regs_ever_live[14] || saved_hard_reg)) \
+ if (! volatile_func \
+ && (regs_ever_live[14] || saved_hard_reg)) \
offset += 4; \
+ offset += current_function_outgoing_args_size; \
(OFFSET) = (get_frame_size () + 3 & ~3) + offset; \
} \
} \
@@ -831,7 +1155,8 @@ enum reg_class
ldr r8, [pc, #0]
ldr pc, [pc]
.word static chain value
- .word function's address */
+ .word function's address
+ ??? FIXME: When the trampoline returns, r8 will be clobbered. */
#define TRAMPOLINE_TEMPLATE(FILE) \
{ \
fprintf ((FILE), "\tldr\t%sr8, [%spc, #0]\n", \
@@ -892,38 +1217,38 @@ enum reg_class
/* Recognize any constant value that is a valid address. */
/* XXX We can address any constant, eventually... */
-#if 0
-#define CONSTANT_ADDRESS_P(X) \
- ( GET_CODE(X) == LABEL_REF \
- || GET_CODE(X) == SYMBOL_REF \
- || GET_CODE(X) == CONST_INT \
- || GET_CODE(X) == CONST )
-#endif
+
+#ifdef AOF_ASSEMBLER
+
+#define CONSTANT_ADDRESS_P(X) \
+ (GET_CODE (X) == SYMBOL_REF \
+ && CONSTANT_POOL_ADDRESS_P (X))
+
+#else
#define CONSTANT_ADDRESS_P(X) \
(GET_CODE (X) == SYMBOL_REF \
&& (CONSTANT_POOL_ADDRESS_P (X) \
|| (optimize > 0 && SYMBOL_REF_FLAG (X))))
+#endif /* AOF_ASSEMBLER */
+
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
On the ARM, allow any integer (invalid ones are removed later by insn
patterns), nice doubles and symbol_refs which refer to the function's
constant pool XXX. */
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) == CONST_INT \
- || (GET_CODE (X) == CONST_DOUBLE \
- && (const_double_rtx_ok_for_fpu (X) \
- || neg_const_double_rtx_ok_for_fpu (X))) \
- || CONSTANT_ADDRESS_P (X))
+#define LEGITIMATE_CONSTANT_P(X) (! label_mentioned_p (X))
/* Symbols in the text segment can be accessed without indirecting via the
constant pool; it may take an extra binary operation, but this is still
faster than indirecting via memory. Don't do this when not optimizing,
since we won't be calculating al of the offsets necessary to do this
simplification. */
-
+/* This doesn't work with AOF syntax, since the string table may be in
+ a different AREA. */
+#ifndef AOF_ASSEMBLER
#define ENCODE_SECTION_INFO(decl) \
{ \
if (optimize > 0 && TREE_CONSTANT (decl) \
@@ -934,6 +1259,7 @@ enum reg_class
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; \
} \
}
+#endif
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
@@ -995,7 +1321,7 @@ do \
HOST_WIDE_INT range; \
enum rtx_code code = GET_CODE (INDEX); \
\
- if (GET_MODE_CLASS (MODE) == MODE_FLOAT) \
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT) \
{ \
if (code == CONST_INT && INTVAL (INDEX) < 1024 \
&& INTVAL (INDEX) > -1024 \
@@ -1006,7 +1332,8 @@ do \
{ \
if (INDEX_REGISTER_RTX_P (INDEX) && GET_MODE_SIZE (MODE) <= 4) \
goto LABEL; \
- if (GET_MODE_SIZE (MODE) <= 4 && code == MULT) \
+ if (GET_MODE_SIZE (MODE) <= 4 && code == MULT \
+ && (! arm_arch4 || (MODE) != HImode)) \
{ \
rtx xiop0 = XEXP (INDEX, 0); \
rtx xiop1 = XEXP (INDEX, 1); \
@@ -1019,7 +1346,8 @@ do \
} \
if (GET_MODE_SIZE (MODE) <= 4 \
&& (code == LSHIFTRT || code == ASHIFTRT \
- || code == ASHIFT || code == ROTATERT)) \
+ || code == ASHIFT || code == ROTATERT) \
+ && (! arm_arch4 || (MODE) != HImode)) \
{ \
rtx op = XEXP (INDEX, 1); \
if (INDEX_REGISTER_RTX_P (XEXP (INDEX, 0)) \
@@ -1027,7 +1355,7 @@ do \
&& INTVAL (op) <= 31) \
goto LABEL; \
} \
- range = (MODE) == HImode ? 4095 : 4096; \
+ range = (MODE) == HImode ? (arm_arch4 ? 256 : 4095) : 4096; \
if (code == CONST_INT && INTVAL (INDEX) < range \
&& INTVAL (INDEX) > -range) \
goto LABEL; \
@@ -1040,7 +1368,7 @@ do \
INDEX+REG, REG-INDEX, and non floating SYMBOL_REF to the constant pool.
Allow REG-only and AUTINC-REG if handling TImode or HImode. Other symbol
refs must be forced though a static cell to ensure addressability. */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
{ \
if (BASE_REGISTER_RTX_P (X)) \
goto LABEL; \
@@ -1048,8 +1376,25 @@ do \
&& GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_PRE_POST_P (XEXP (X, 0))) \
goto LABEL; \
+ else if (GET_MODE_SIZE (MODE) >= 4 && reload_completed \
+ && (GET_CODE (X) == LABEL_REF \
+ || (GET_CODE (X) == CONST \
+ && GET_CODE (XEXP ((X), 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP ((X), 0), 0)) == LABEL_REF \
+ && GET_CODE (XEXP (XEXP ((X), 0), 1)) == CONST_INT)))\
+ goto LABEL; \
else if ((MODE) == TImode) \
; \
+ else if ((MODE) == DImode || (TARGET_SOFT_FLOAT && (MODE) == DFmode)) \
+ { \
+ if (GET_CODE (X) == PLUS && BASE_REGISTER_RTX_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == CONST_INT) \
+ { \
+ HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
+ if (val == 4 || val == -4 || val == -8) \
+ goto LABEL; \
+ } \
+ } \
else if (GET_CODE (X) == PLUS) \
{ \
rtx xop0 = XEXP(X,0); \
@@ -1060,19 +1405,21 @@ do \
else if (BASE_REGISTER_RTX_P (xop1)) \
GO_IF_LEGITIMATE_INDEX (MODE, REGNO (xop1), xop0, LABEL); \
} \
- else if (GET_CODE (X) == MINUS) \
+ /* Reload currently can't handle MINUS, so disable this for now */ \
+ /* else if (GET_CODE (X) == MINUS) \
{ \
rtx xop0 = XEXP (X,0); \
rtx xop1 = XEXP (X,1); \
\
if (BASE_REGISTER_RTX_P (xop0)) \
GO_IF_LEGITIMATE_INDEX (MODE, -1, xop1, LABEL); \
- } \
+ } */ \
else if (GET_MODE_CLASS (MODE) != MODE_FLOAT \
&& GET_CODE (X) == SYMBOL_REF \
&& CONSTANT_POOL_ADDRESS_P (X)) \
goto LABEL; \
else if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_DEC) \
+ && (GET_MODE_SIZE (MODE) <= 4) \
&& GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_PRE_POST_P (XEXP (X, 0))) \
goto LABEL; \
@@ -1094,6 +1441,7 @@ do \
On the ARM, try to convert [REG, #BIGCONST]
into ADD BASE, REG, #UPPERCONST and [BASE, #VALIDCONST],
where VALIDCONST == 0 in case of TImode. */
+extern struct rtx_def *legitimize_pic_address ();
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
{ \
if (GET_CODE (X) == PLUS) \
@@ -1101,9 +1449,9 @@ do \
rtx xop0 = XEXP (X, 0); \
rtx xop1 = XEXP (X, 1); \
\
- if (CONSTANT_P (xop0) && ! LEGITIMATE_CONSTANT_P (xop0)) \
+ if (CONSTANT_P (xop0) && ! symbol_mentioned_p (xop0)) \
xop0 = force_reg (SImode, xop0); \
- if (CONSTANT_P (xop1) && ! LEGITIMATE_CONSTANT_P (xop1)) \
+ if (CONSTANT_P (xop1) && ! symbol_mentioned_p (xop1)) \
xop1 = force_reg (SImode, xop1); \
if (BASE_REGISTER_RTX_P (xop0) && GET_CODE (xop1) == CONST_INT) \
{ \
@@ -1111,7 +1459,7 @@ do \
rtx base_reg, val; \
n = INTVAL (xop1); \
\
- if (MODE == DImode) \
+ if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode)) \
{ \
low_n = n & 0x0f; \
n &= ~0x0f; \
@@ -1144,16 +1492,17 @@ do \
\
if (CONSTANT_P (xop0)) \
xop0 = force_reg (SImode, xop0); \
- if (CONSTANT_P (xop1) && ! LEGITIMATE_CONSTANT_P (xop1)) \
+ if (CONSTANT_P (xop1) && ! symbol_mentioned_p (xop1)) \
xop1 = force_reg (SImode, xop1); \
if (xop0 != XEXP (X, 0) || xop1 != XEXP (X, 1)) \
(X) = gen_rtx (MINUS, SImode, xop0, xop1); \
} \
+ if (flag_pic) \
+ (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX); \
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. */
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
@@ -1200,7 +1549,7 @@ do \
be the code that says which one of the two operations is implicitly
done, NIL if none. */
#define LOAD_EXTEND_OP(MODE) \
- ((MODE) == QImode ? ZERO_EXTEND \
+ ((arm_arch4 || (MODE) == QImode) ? ZERO_EXTEND \
: ((BYTES_BIG_ENDIAN && (MODE) == HImode) ? SIGN_EXTEND : NIL))
/* Define this if zero-extension is slow (more than one real instruction).
@@ -1222,7 +1571,6 @@ do \
rotates is modulo 32 used. */
/* #define SHIFT_COUNT_TRUNCATED 1 */
-/* XX This is not true, is it? */
/* All integers have the same format so truncation is easy. */
#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1
@@ -1271,8 +1619,8 @@ do \
((X) == frame_pointer_rtx || (X) == stack_pointer_rtx \
|| (X) == arg_pointer_rtx)
-#define RTX_COSTS(X,CODE,OUTER_CODE) \
- default: \
+#define RTX_COSTS(X,CODE,OUTER_CODE) \
+ default: \
return arm_rtx_costs (X, CODE, OUTER_CODE);
/* Moves to and from memory are quite expensive */
@@ -1303,6 +1651,27 @@ do \
/* Try to generate sequences that don't involve branches, we can then use
conditional instructions */
#define BRANCH_COST 4
+
+/* A C statement to update the variable COST based on the relationship
+ between INSN that is dependent on DEP through dependence LINK. */
+#define ADJUST_COST(INSN,LINK,DEP,COST) \
+ (COST) = arm_adjust_cost ((INSN), (LINK), (DEP), (COST))
+
+/* Position Independent Code. */
+/* We decide which register to use based on the compilation options and
+ the assembler in use; this is more general than the APCS restriction of
+ using sb (r9) all the time. */
+extern int arm_pic_register;
+
+/* The register number of the register used to address a table of static
+ data addresses in memory. */
+#define PIC_OFFSET_TABLE_REGNUM arm_pic_register
+
+#define FINALIZE_PIC arm_finalize_pic ()
+
+#define LEGITIMATE_PIC_OPERAND_P(X) (! symbol_mentioned_p (X))
+
+
/* Condition code information. */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
@@ -1310,29 +1679,36 @@ do \
CCFPEmode should be used with floating inequalities,
CCFPmode should be used with floating equalities.
CC_NOOVmode should be used with SImode integer equalities.
+ CC_Zmode should be used if only the Z flag is set correctly
CCmode should be used otherwise. */
-#define EXTRA_CC_MODES CC_NOOVmode, CCFPmode, CCFPEmode
-
-#define EXTRA_CC_NAMES "CC_NOOV", "CCFP", "CCFPE"
-
-#define SELECT_CC_MODE(OP,X,Y) \
- (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
- ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \
- : ((GET_MODE (X) == SImode) \
- && ((OP) == EQ || (OP) == NE) \
- && (GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
- || GET_CODE (X) == AND || GET_CODE (X) == IOR \
- || GET_CODE (X) == XOR || GET_CODE (X) == MULT \
- || GET_CODE (X) == NOT || GET_CODE (X) == NEG \
- || GET_CODE (X) == LSHIFTRT \
- || GET_CODE (X) == ASHIFT || GET_CODE (X) == ASHIFTRT \
- || GET_CODE (X) == ROTATERT || GET_CODE (X) == ZERO_EXTRACT) \
- ? CC_NOOVmode \
- : GET_MODE (X) == QImode ? CC_NOOVmode : CCmode))
+#define EXTRA_CC_MODES CC_NOOVmode, CC_Zmode, CC_SWPmode, \
+ CCFPmode, CCFPEmode, CC_DNEmode, CC_DEQmode, CC_DLEmode, \
+ CC_DLTmode, CC_DGEmode, CC_DGTmode, CC_DLEUmode, CC_DLTUmode, \
+ CC_DGEUmode, CC_DGTUmode, CC_Cmode
+
+#define EXTRA_CC_NAMES "CC_NOOV", "CC_Z", "CC_SWP", "CCFP", "CCFPE", \
+ "CC_DNE", "CC_DEQ", "CC_DLE", "CC_DLT", "CC_DGE", "CC_DGT", "CC_DLEU", \
+ "CC_DLTU", "CC_DGEU", "CC_DGTU", "CC_C"
+
+enum machine_mode arm_select_cc_mode ();
+#define SELECT_CC_MODE(OP,X,Y) arm_select_cc_mode ((OP), (X), (Y))
#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode)
+enum rtx_code arm_canonicalize_comparison ();
+#define CANONICALIZE_COMPARISON(CODE,OP0,OP1) \
+do \
+{ \
+ if (GET_CODE (OP1) == CONST_INT \
+ && ! (const_ok_for_arm (INTVAL (OP1)) \
+ || (const_ok_for_arm (- INTVAL (OP1))))) \
+ { \
+ rtx const_op = OP1; \
+ CODE = arm_canonicalize_comparison ((CODE), &const_op); \
+ } \
+} while (0)
+
#define STORE_FLAG_VALUE 1
/* Define the information needed to generate branch insns. This is
@@ -1345,11 +1721,14 @@ extern int arm_compare_fp;
/* Define the codes that are matched by predicates in arm.c */
#define PREDICATE_CODES \
{"s_register_operand", {SUBREG, REG}}, \
+ {"f_register_operand", {SUBREG, REG}}, \
{"arm_add_operand", {SUBREG, REG, CONST_INT}}, \
{"fpu_add_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"arm_rhs_operand", {SUBREG, REG, CONST_INT}}, \
{"fpu_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"arm_not_operand", {SUBREG, REG, CONST_INT}}, \
+ {"offsettable_memory_operand", {MEM}}, \
+ {"alignable_memory_operand", {MEM}}, \
{"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \
{"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \
{"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, MULT}}, \
@@ -1364,154 +1743,38 @@ extern int arm_compare_fp;
{"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \
{"multi_register_push", {PARALLEL}}, \
{"cc_register", {REG}}, \
- {"reversible_cc_register", {REG}},
+ {"dominant_cc_register", {REG}},
-/* Assembler output control */
-
-#ifndef ARM_OS_NAME
-#define ARM_OS_NAME "(generic)"
-#endif
-
-/* The text to go at the start of the assembler file */
-#define ASM_FILE_START(STREAM) \
-{ \
- extern char *version_string; \
- fprintf (STREAM,"%s Generated by gcc %s for ARM/%s\n", \
- ASM_COMMENT_START, version_string, ARM_OS_NAME); \
- fprintf (STREAM,"%srfp\t.req\t%sr9\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf (STREAM,"%ssl\t.req\t%sr10\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf (STREAM,"%sfp\t.req\t%sr11\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf (STREAM,"%sip\t.req\t%sr12\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf (STREAM,"%ssp\t.req\t%sr13\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf (STREAM,"%slr\t.req\t%sr14\n", REGISTER_PREFIX, REGISTER_PREFIX); \
- fprintf (STREAM,"%spc\t.req\t%sr15\n", REGISTER_PREFIX, REGISTER_PREFIX); \
-}
-
-#define ASM_APP_ON ""
-#define ASM_APP_OFF ""
-
-/* Switch to the text or data segment. */
-#define TEXT_SECTION_ASM_OP ".text"
-#define DATA_SECTION_ASM_OP ".data"
-
-#define REGISTER_PREFIX ""
-#define USER_LABEL_PREFIX "_"
-#define LOCAL_LABEL_PREFIX ""
-
-/* The assembler's names for the registers. */
-#ifndef REGISTER_NAMES
-#define REGISTER_NAMES \
-{ \
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
- "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", \
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \
- "cc", "sfp", "afp" \
-}
-#endif
-
-#ifndef ADDITIONAL_REGISTER_NAMES
-#define ADDITIONAL_REGISTER_NAMES \
-{ \
- {"a1", 0}, \
- {"a2", 1}, \
- {"a3", 2}, \
- {"a4", 3}, \
- {"v1", 4}, \
- {"v2", 5}, \
- {"v3", 6}, \
- {"v4", 7}, \
- {"v5", 8}, \
- {"v6", 9}, \
- {"rfp", 9}, /* Gcc used to call it this */ \
- {"sb", 9}, \
- {"v7", 10}, \
- {"r10", 10}, \
- {"r11", 11}, /* fp */ \
- {"r12", 12}, /* ip */ \
- {"r13", 13}, /* sp */ \
- {"r14", 14}, /* lr */ \
- {"r15", 15} /* pc */ \
-}
-#endif
-
-/* Arm Assembler barfs on dollars */
-#define DOLLARS_IN_IDENTIFIERS 0
-#define NO_DOLLAR_IN_LABEL
+/* Gcc puts the pool in the wrong place for ARM, since we can only
+ load addresses a limited distance around the pc. We do some
+ special munging to move the constant pool values to the correct
+ point in the code. */
+#define MACHINE_DEPENDENT_REORG(INSN) arm_reorg ((INSN))
-/* DBX register number for a given compiler register number */
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-
-/* Generate DBX debugging information. riscix.h will undefine this because
- the native assembler does not support stabs. */
-#define DBX_DEBUGGING_INFO 1
-
-/* Acorn dbx moans about continuation chars, so don't use any. */
-#ifndef DBX_CONTIN_LENGTH
-#define DBX_CONTIN_LENGTH 0
-#endif
-
-/* Output a source filename for the debugger. RISCiX dbx insists that the
- ``desc'' field is set to compiler version number >= 315 (sic). */
-#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM,NAME) \
-do { \
- fprintf (STREAM, ".stabs \"%s\",%d,0,315,%s\n", (NAME), N_SO, \
- &ltext_label_name[1]); \
- text_section (); \
- ASM_OUTPUT_INTERNAL_LABEL (STREAM, "Ltext", 0); \
-} while (0)
-
-/* Output a label definition. */
-#define ASM_OUTPUT_LABEL(STREAM,NAME) \
- arm_asm_output_label ((STREAM), (NAME))
-
-/* Output a function label definition. */
-#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
- ASM_OUTPUT_LABEL(STREAM, NAME)
-
-/* Output a globalising directive for a label. */
-#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
- (fprintf (STREAM, "\t.global\t"), \
- assemble_name (STREAM, NAME), \
- fputc ('\n',STREAM)) \
-
-/* Output a reference to a label. */
-#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
- fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, NAME)
-
-/* Make an internal label into a string. */
-#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
- sprintf (STRING, "*%s%d", PREFIX, NUM)
+/* The pool is empty, since we have moved everything into the code. */
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE,X,MODE,ALIGN,LABELNO,JUMPTO) \
+ goto JUMPTO
/* Output an internal label definition. */
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) \
- do \
- { \
- char *s = (char *) alloca (11 + strlen (PREFIX)); \
- extern int arm_target_label, arm_ccfsm_state; \
- extern rtx arm_target_insn; \
- \
- if (arm_ccfsm_state == 3 && arm_target_label == (NUM) \
- && !strcmp (PREFIX, "L")) \
- { \
- arm_ccfsm_state = 0; \
- arm_target_insn = NULL; \
- } \
- strcpy (s, "*"); \
- sprintf (&s[strlen (s)], "%s%d", (PREFIX), (NUM)); \
- arm_asm_output_label (STREAM, s); \
+#define ASM_OUTPUT_INTERNAL_LABEL(STREAM, PREFIX, NUM) \
+ do \
+ { \
+ char *s = (char *) alloca (40 + strlen (PREFIX)); \
+ extern int arm_target_label, arm_ccfsm_state; \
+ extern rtx arm_target_insn; \
+ \
+ if (arm_ccfsm_state == 3 && arm_target_label == (NUM) \
+ && !strcmp (PREFIX, "L")) \
+ { \
+ arm_ccfsm_state = 0; \
+ arm_target_insn = NULL; \
+ } \
+ ASM_GENERATE_INTERNAL_LABEL (s, (PREFIX), (NUM)); \
+ ASM_OUTPUT_LABEL (STREAM, s); \
} while (0)
-/* Nothing special is done about jump tables */
-/* #define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) */
-/* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE) */
-
-/* Construct a private name. */
-#define ASM_FORMAT_PRIVATE_NAME(OUTVAR,NAME,NUMBER) \
- ((OUTVAR) = (char *) alloca (strlen (NAME) + 10), \
- sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)))
-
/* Output a push or a pop instruction (only used when profiling). */
#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
fprintf(STREAM,"\tstmfd\t%ssp!,{%s%s}\n", \
@@ -1521,132 +1784,6 @@ do { \
fprintf(STREAM,"\tldmfd\t%ssp!,{%s%s}\n", \
REGISTER_PREFIX, REGISTER_PREFIX, reg_names[REGNO])
-/* Output a relative address. Not needed since jump tables are absolute
- but we must define it anyway. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL) \
- fputs ("- - - ASM_OUTPUT_ADDR_DIFF_ELT called!\n", STREAM)
-
-/* Output an element of a dispatch table. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
- fprintf (STREAM, "\t.word\tL%d\n", VALUE)
-
-/* Output various types of constants. For real numbers we output hex, with
- a comment containing the "human" value, this allows us to pass NaN's which
- the riscix assembler doesn't understand (it also makes cross-assembling
- less likely to fail). */
-
-#define ASM_OUTPUT_LONG_DOUBLE(STREAM,VALUE) \
-do { char dstr[30]; \
- long l[3]; \
- arm_increase_location (12); \
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
- if (sizeof (int) == sizeof (long)) \
- fprintf (STREAM, "\t.long 0x%x,0x%x,0x%x\t%s long double %s\n", \
- l[2], l[1], l[0], ASM_COMMENT_START, dstr); \
- else \
- fprintf (STREAM, "\t.long 0x%lx,0x%lx,0x%lx\t%s long double %s\n",\
- l[0], l[1], l[2], ASM_COMMENT_START, dstr); \
- } while (0)
-
-
-#define ASM_OUTPUT_DOUBLE(STREAM, VALUE) \
-do { char dstr[30]; \
- long l[2]; \
- arm_increase_location (8); \
- REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.14g", dstr); \
- if (sizeof (int) == sizeof (long)) \
- fprintf (STREAM, "\t.long 0x%x, 0x%x\t%s double %s\n", l[0], \
- l[1], ASM_COMMENT_START, dstr); \
- else \
- fprintf (STREAM, "\t.long 0x%lx, 0x%lx\t%s double %s\n", l[0], \
- l[1], ASM_COMMENT_START, dstr); \
- } while (0)
-
-#define ASM_OUTPUT_FLOAT(STREAM, VALUE) \
-do { char dstr[30]; \
- long l; \
- arm_increase_location (4); \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.7g", dstr); \
- if (sizeof (int) == sizeof (long)) \
- fprintf (STREAM, "\t.word 0x%x\t%s float %s\n", l, \
- ASM_COMMENT_START, dstr); \
- else \
- fprintf (STREAM, "\t.word 0x%lx\t%s float %s\n", l, \
- ASM_COMMENT_START, dstr); \
- } while (0);
-
-#define ASM_OUTPUT_INT(STREAM, EXP) \
- (fprintf (STREAM, "\t.word\t"), \
- output_addr_const (STREAM, (EXP)), \
- arm_increase_location (4), \
- fputc ('\n', STREAM))
-
-#define ASM_OUTPUT_SHORT(STREAM, EXP) \
- (fprintf (STREAM, "\t.short\t"), \
- output_addr_const (STREAM, (EXP)), \
- arm_increase_location (2), \
- fputc ('\n', STREAM))
-
-#define ASM_OUTPUT_CHAR(STREAM, EXP) \
- (fprintf (STREAM, "\t.byte\t"), \
- output_addr_const (STREAM, (EXP)), \
- arm_increase_location (1), \
- fputc ('\n', STREAM))
-
-#define ASM_OUTPUT_BYTE(STREAM, VALUE) \
- (fprintf (STREAM, "\t.byte\t%d\n", VALUE), \
- arm_increase_location (1))
-
-#define ASM_OUTPUT_ASCII(STREAM, PTR, LEN) \
- output_ascii_pseudo_op ((STREAM), (unsigned char *)(PTR), (LEN))
-
-/* Output a gap. In fact we fill it with nulls. */
-#define ASM_OUTPUT_SKIP(STREAM, NBYTES) \
- (arm_increase_location (NBYTES), \
- fprintf (STREAM, "\t.space\t%d\n", NBYTES))
-
-/* Align output to a power of two. Horrible /bin/as. */
-#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
- do \
- { \
- register int amount = 1 << (POWER); \
- extern int arm_text_location; \
- \
- if (amount == 2) \
- fprintf (STREAM, "\t.even\n"); \
- else \
- fprintf (STREAM, "\t.align\t%d\n", amount - 4); \
- \
- if (in_text_section ()) \
- arm_text_location = ((arm_text_location + amount - 1) \
- & ~(amount - 1)); \
- } while (0)
-
-/* Output a common block */
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (fprintf (STREAM, "\t.comm\t"), \
- assemble_name ((STREAM), (NAME)), \
- fprintf(STREAM, ", %d\t%s %d\n", ROUNDED, ASM_COMMENT_START, SIZE))
-
-/* Output a local common block. /bin/as can't do this, so hack a `.space' into
- the bss segment. Note that this is *bad* practice. */
-#define ASM_OUTPUT_LOCAL(STREAM,NAME,SIZE,ROUNDED) \
- output_lcomm_directive (STREAM, NAME, SIZE, ROUNDED)
-
-/* Output a source line for the debugger. */
-/* #define ASM_OUTPUT_SOURCE_LINE(STREAM,LINE) */
-
-/* Output a #ident directive. */
-#define ASM_OUTPUT_IDENT(STREAM,STRING) \
- fprintf (STREAM,"- - - ident %s\n",STRING)
-
-/* The assembler's parentheses characters. */
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
/* Target characters. */
#define TARGET_BELL 007
#define TARGET_BS 010
@@ -1662,10 +1799,6 @@ do { char dstr[30]; \
if (optimize) \
final_prescan_insn (INSN, OPVEC, NOPERANDS)
-#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "@"
-#endif
-
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
((CODE) == '?' || (CODE) == '|' || (CODE) == '@')
/* Output an operand of an instruction. */
@@ -1757,3 +1890,171 @@ do { char dstr[30]; \
} \
else output_addr_const(STREAM, X); \
}
+
+/* Handles PIC addr specially */
+#define OUTPUT_INT_ADDR_CONST(STREAM,X) \
+ { \
+ if (flag_pic && GET_CODE(X) == CONST && is_pic(X)) \
+ { \
+ output_addr_const(STREAM, XEXP (XEXP (XEXP (X, 0), 0), 0)); \
+ fputs(" - (", STREAM); \
+ output_addr_const(STREAM, XEXP (XEXP (XEXP (X, 0), 1), 0)); \
+ fputs(")", STREAM); \
+ } \
+ else output_addr_const(STREAM, X); \
+ }
+
+/* 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 mi_delta = (DELTA); \
+ char *mi_op = mi_delta < 0 ? "sub" : "add"; \
+ int shift = 0; \
+ int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) \
+ ? 1 : 0); \
+ if (mi_delta < 0) mi_delta = -mi_delta; \
+ while (mi_delta != 0) \
+ { \
+ if (mi_delta & (3 << shift) == 0) \
+ shift += 2; \
+ else \
+ { \
+ fprintf (FILE, "\t%s\t%s%s, %s%s, #%d\n", \
+ mi_op, REGISTER_PREFIX, reg_names[this_regno], \
+ REGISTER_PREFIX, reg_names[this_regno], \
+ mi_delta & (0xff << shift)); \
+ mi_delta &= ~(0xff << shift); \
+ shift += 8; \
+ } \
+ } \
+ fputs ("\tb\t", FILE); \
+ assemble_name (FILE, \
+ IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \
+ fputc ('\n', FILE); \
+} while (0)
+
+/* A C expression whose value is RTL representing the value of the return
+ address for the frame COUNT steps up from the current frame. */
+
+#define RETURN_ADDR_RTX(COUNT, FRAME) \
+ ((COUNT == 0) \
+ ? gen_rtx (MEM, Pmode, plus_constant (FRAME, -4)) \
+ : NULL_RTX)
+
+/* Used to mask out junk bits from the return address, such as
+ processor state, interrupt status, condition codes and the like. */
+#define MASK_RETURN_ADDR \
+ /* 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 address. This does not apply to ARM6 and later processors \
+ when running in 32 bit mode. */ \
+ ((!TARGET_APCS_32) ? (GEN_INT (0x03fffffc)) : (GEN_INT (0xffffffff)))
+
+/* Prototypes for arm.c -- actually, they aren't since the types aren't
+ fully defined yet. */
+
+void arm_override_options (/* void */);
+int use_return_insn (/* void */);
+int const_ok_for_arm (/* HOST_WIDE_INT */);
+int const_ok_for_op (/* HOST_WIDE_INT, enum rtx_code,
+ enum machine_mode */);
+int arm_split_constant (/* enum rtx_code, enum machine_mode,
+ HOST_WIDE_INT, struct rtx_def *,
+ struct rtx_def *, int */);
+enum rtx_code arm_canonicalize_comparison (/* enum rtx_code,
+ struct rtx_def ** */);
+int arm_return_in_memory (/* union tree_node * */);
+int legitimate_pic_operand_p (/* struct rtx_def * */);
+struct rtx_def *legitimize_pic_address (/* struct rtx_def *,
+ enum machine_mode,
+ struct rtx_def * */);
+int is_pic (/* struct rtx_def * */);
+void arm_finalize_pic (/* void */);
+int arm_rtx_costs (/* struct rtx_def *, enum rtx_code, enum rtx_code */);
+int arm_adjust_code (/* struct rtx_def *, struct rtx_def *,
+ struct rtx_def *, int */);
+int const_double_rtx_ok_for_fpu (/* struct rtx_def * */);
+int neg_const_double_rtx_ok_for_fpu (/* struct rtx_def * */);
+int s_register_operand (/* struct rtx_def *, enum machine_mode */);
+int f_register_operand (/* struct rtx_def *, enum machine_mode */);
+int reg_or_int_operand (/* struct rtx_def *, enum machine_mode */);
+int reload_memory_operand (/* struct rtx_def *, enum machine_mode */);
+int arm_rhs_operand (/* struct rtx_def *, enum machine_mode */);
+int arm_rhsm_operand (/* struct rtx_def *, enum machine_mode */);
+int arm_add_operand (/* struct rtx_def *, enum machine_mode */);
+int arm_not_operand (/* struct rtx_def *, enum machine_mode */);
+int offsettable_memory_operand (/* struct rtx_def *, enum machine_mode */);
+int alignable_memory_operand (/* struct rtx_def *, enum machine_mode */);
+int fpu_rhs_operand (/* struct rtx_def *, enum machine_mode */);
+int fpu_add_operand (/* struct rtx_def *, enum machine_mode */);
+int power_of_two_operand (/* struct rtx_def *, enum machine_mode */);
+int di_operand (/* struct rtx_def *, enum machine_mode */);
+int soft_df_operand (/* struct rtx_def *, enum machine_mode */);
+int index_operand (/* struct rtx_def *, enum machine_mode */);
+int const_shift_operand (/* struct rtx_def *, enum machine_mode */);
+int shiftable_operator (/* struct rtx_def *, enum machine_mode */);
+int shift_operator (/* struct rtx_def *, enum machine_mode */);
+int equality_operator (/* struct rtx_def *, enum machine_mode */);
+int minmax_operator (/* struct rtx_def *, enum machine_mode */);
+int cc_register (/* struct rtx_def *, enum machine_mode */);
+int dominant_cc_register (/* struct rtx_def *, enum machine_mode */);
+int symbol_mentioned_p (/* struct rtx_def * */);
+int label_mentioned_p (/* struct rtx_def * */);
+enum rtx_code minmax_code (/* struct rtx_def * */);
+int adjacent_mem_locations (/* struct rtx_def *, struct rtx_def * */);
+int load_multiple_operation (/* struct rtx_def *, enum machine_mode */);
+int store_multiple_operation (/* struct rtx_def *, enum machine_mode */);
+int load_multiple_sequence (/* struct rtx_def **, int, int *, int *,
+ HOST_WIDE_INT * */);
+char *emit_ldm_seq (/* struct rtx_def **, int */);
+int store_multiple_sequence (/* struct rtx_def **, int, int *, int *,
+ HOST_WIDE_INT * */);
+char *emit_stm_seq (/* struct rtx_def **, int */);
+int multi_register_push (/* struct rtx_def *, enum machine_mode */);
+int arm_valid_machine_decl_attribute (/* union tree_node *, union tree_node *,
+ union tree_node *,
+ union tree_node * */);
+struct rtx_def *arm_gen_load_multiple (/* int, int, struct rtx_def *,
+ int, int, int, int */);
+struct rtx_def *arm_gen_store_multiple (/* int, int, struct rtx_def *,
+ int, int, int, int */);
+int arm_gen_movstrqi (/* struct rtx_def ** */);
+struct rtx_def *gen_rotated_half_load (/* struct rtx_def * */);
+enum machine_mode arm_select_cc_mode (/* enum rtx_code, struct rtx_def *,
+ struct rtx_def * */);
+struct rtx_def *gen_compare_reg (/* enum rtx_code, struct rtx_def *,
+ struct rtx_def * */);
+void arm_reload_in_hi (/* struct rtx_def ** */);
+void arm_reload_out_hi (/* struct rtx_def ** */);
+void arm_reorg (/* struct rtx_def * */);
+char *fp_immediate_constant (/* struct rtx_def * */);
+void print_multi_reg (/* FILE *, char *, int, int */);
+char *output_call (/* struct rtx_def ** */);
+char *output_call_mem (/* struct rtx_def ** */);
+char *output_mov_long_double_fpu_from_arm (/* struct rtx_def ** */);
+char *output_mov_long_double_arm_from_fpu (/* struct rtx_def ** */);
+char *output_mov_long_double_arm_from_arm (/* struct rtx_def ** */);
+char *output_mov_double_fpu_from_arm (/* struct rtx_def ** */);
+char *output_mov_double_arm_from_fpu (/* struct rtx_def ** */);
+char *output_move_double (/* struct rtx_def ** */);
+char *output_mov_immediate (/* struct rtx_def ** */);
+char *output_add_immediate (/* struct rtx_def ** */);
+char *arithmetic_instr (/* struct rtx_def *, int */);
+void output_ascii_pseudo_op (/* FILE *, unsigned char *, int */);
+char *output_return_instruction (/* struct rtx_def *, int, int */);
+int arm_volatile_func (/* void */);
+void output_func_prologue (/* FILE *, int */);
+void output_func_epilogue (/* FILE *, int */);
+void arm_expand_prologue (/* void */);
+void arm_print_operand (/* FILE *, struct rtx_def *, int */);
+void final_prescan_insn (/* struct rtx_def *, struct rtx_def **, int */);
+#ifdef AOF_ASSEMBLER
+struct rtx_def *aof_pic_entry (/* struct rtx_def * */);
+void aof_dump_pic_table (/* FILE * */);
+char *aof_text_section (/* void */);
+char *aof_data_section (/* void */);
+void aof_add_import (/* char * */);
+void aof_delete_import (/* char * */);
+void aof_dump_imports (/* FILE * */);
+#endif
diff --git a/gnu/usr.bin/gcc/config/arm/lib1funcs.asm b/gnu/usr.bin/gcc/config/arm/lib1funcs.asm
index acb0c1fca65..35e6bd0d0bc 100644
--- a/gnu/usr.bin/gcc/config/arm/lib1funcs.asm
+++ b/gnu/usr.bin/gcc/config/arm/lib1funcs.asm
@@ -1,9 +1,7 @@
@ libgcc1 routines for ARM cpu.
-@ Division and remainder, from Appendix E of the Sparc Version 8
-@ Architecture Manual, with fixes from Gordon Irlam.
-@ Rewritten for the ARM by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
+@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
-/* Copyright (C) 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996 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
@@ -35,1565 +33,391 @@ Boston, MA 02111-1307, USA. */
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
-/*
- * Input: dividend and divisor in r0 and r1 respectively.
- *
- * m4 parameters:
- * NAME name of function to generate
- * OP OP=div => r0 / r1; OP=mod => r0 % r1
- * S S=true => signed; S=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.
- */
+#ifdef __APCS_26__
+#define RET movs
+#define RETc(x) mov##x##s
+#define RETCOND ^
+#else
+#define RET mov
+#define RETc(x) mov##x
+#define RETCOND
+#endif
-/*
-define(N, `4')dnl
-define(WORDSIZE, `32')dnl
-define(TOPBITS, eval(WORDSIZE - N*((WORDSIZE-1)/N)))dnl
-dnl
-define(dividend, `r0')dnl
-define(divisor, `r1')dnl
-define(Q, `r2')dnl
-define(R, `r3')dnl
-define(ITER, `ip')dnl
-define(V, `lr')dnl
-dnl
-dnl m4 reminder: ifelse(a,b,c,d) => if a is b, then c, else d
-define(T, `r4')dnl
-define(SC, `r5')dnl
-ifelse(S, `true', `define(SIGN, `r6')')dnl
-define(REGLIST, `ifelse(S, `true', `{r4, r5, r6,', `{r4, r5,')')dnl
-define(ret, `ldmia sp!, REGLIST pc}')dnl
-dnl
-dnl This is the recursive definition for developing quotient digits.
-dnl
-dnl Parameters:
-dnl $1 the current depth, 1 <= $1 <= N
-dnl $2 the current accumulation of quotient bits
-dnl N max depth
-dnl
-dnl We add a new bit to $2 and either recurse or insert the bits in
-dnl the quotient. R, Q, and V are inputs and outputs as defined above;
-dnl the condition codes are expected to reflect the input R, and are
-dnl modified to reflect the output R.
-dnl
-define(DEVELOP_QUOTIENT_BITS,
-` @ depth $1, accumulated bits $2
- mov V, V, lsr #1
- blt L.$1.eval(2^N+$2+999)
- @ remainder is positive
- subs R, R, V
- ifelse($1, N,
- ` ifelse(eval(2*$2+1<0), `0',
- `add Q, Q, `#'eval($2*2+1)',
- `sub Q, Q, `#'eval(-($2*2+1))')
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
- b 9f
- ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2+1)')')
-L.$1.eval(2^N+$2+999):
- @ remainder is negative
- adds R, R, V
- ifelse($1, N,
- ` ifelse(eval(2*$2-1<0), `0',
- `add Q, Q, `#'eval($2*2-1)',
- `sub Q, Q, `#'eval(-($2*2-1))')
- b 9f
+/* ANSI concatenation macros. */
- ', ` DEVELOP_QUOTIENT_BITS(incr($1), `eval(2*$2-1)')')
- ifelse($1, 1, `9:')')dnl
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
-#include "trap.h"
+/* Use the right prefix for global labels. */
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-.text
- .globl NAME
- .align 0
-NAME:
- stmdb sp!, REGLIST lr}
-ifelse(S, `true',
-` @ compute sign of result; if neither is negative, no problem
- ifelse(OP, `div', `eor SIGN, divisor, dividend @ compute sign',
- `mov SIGN, dividend')
- cmp divisor, #0
- rsbmi divisor, divisor, #0
- beq Ldiv_zero
- mov V, divisor
- movs R, dividend
- rsbmi R, R, #0 @ make dividend nonnegative
-',
-` @ Ready to divide. Compute size of quotient; scale comparand.
- movs V, divisor
- mov R, dividend
- beq Ldiv_zero
-')
-
- cmp R, V @ if divisor exceeds dividend, done
- mov Q, #0
- bcc Lgot_result @ (and algorithm fails otherwise)
- mov T, `#'(1 << (WORDSIZE - TOPBITS - 1))
- cmp R, T
- mov ITER, #0
- bcc Lnot_really_big
-
- @ `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.'
- mov SC, #1
- 1:
- cmp V, T
- bcs 3f
- mov V, V, lsl `#'N
- add ITER, ITER, #1
- b 1b
-
- @ Now compute SC.
- 2: adds V, V, V
- add SC, SC, #1
- bcc Lnot_too_big
-
- @ We get here if the divisor overflowed while shifting.
- @ This means that R has the high-order bit set.
- @ Restore V and subtract from R.
- mov T, T, lsl `#'TOPBITS
- mov V, V, lsr #1
- add V, T, V
- sub SC, SC, #1
- b Ldo_single_div
-
- Lnot_too_big:
- 3: cmp V, R
- bcc 2b
-@ beq Ldo_single_div
-
- /-* NB: these are commented out in the V8-Sparc manual as well *-/
- /-* (I do not understand this) *-/
- @ V > R: went too far: back up 1 step
- @ srl V, 1, V
- @ dec SC
- @ do single-bit divide steps
- @
- @ We have to be careful here. We know that R >= V, so we can do the
- @ first divide step without thinking. BUT, the others are conditional,
- @ and are only done if R >= 0. Because both R and V 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...
- Ldo_single_div:
- subs SC, SC, #1
- blt Lend_regular_divide
- sub R, R, V
- mov Q, #1
- b Lend_single_divloop
- Lsingle_divloop:
- cmp R, #0
- mov Q, Q, lsl #1
- mov V, V, lsr #1
- @ R >= 0
- subpl R, R, V
- addpl Q, Q, #1
- @ R < 0
- addmi R, R, V
- submi Q, Q, #1
- Lend_single_divloop:
- subs SC, SC, #1
- bge Lsingle_divloop
- b Lend_regular_divide
-
-1:
- add ITER, ITER, #1
-Lnot_really_big:
- mov V, V, lsl `#'N
- cmp V, R
- bls 1b
- @
- @ HOW CAN ITER EVER BE -1 HERE ?????
- @
- cmn ITER, #1
- beq Lgot_result
-
-Ldivloop:
- cmp R, #0 @ set up for initial iteration
- mov Q, Q, lsl `#'N
- DEVELOP_QUOTIENT_BITS(1, 0)
-Lend_regular_divide:
- subs ITER, ITER, #1
- bge Ldivloop
- cmp R, #0
- @ non-restoring fixup here (one instruction only!)
-ifelse(OP, `div',
-` sublt Q, Q, #1
-', ` addlt R, divisor, R
-')
-
-Lgot_result:
-ifelse(S, `true',
-` @ check to see if answer should be < 0
- cmp SIGN, #0
- ifelse(OP, `div', `rsbmi Q, Q, #0', `rsbmi R, R, #0')
-')
- ifelse(OP, `div', `mov r0, Q', `mov r0, R')
- ret
-
-Ldiv_zero:
- @ Divide by zero trap. If it returns, return 0 (about as
- @ wrong as possible, but that is what SunOS does...).
- bl ___div0
- mov r0, #0
- ret
-*/
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
#ifdef L_udivsi3
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-.text
- .globl ___udivsi3
+dividend .req r0
+divisor .req r1
+result .req r2
+curbit .req r3
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+ .text
+ .globl SYM (__udivsi3)
.align 0
-___udivsi3:
- stmdb sp!, {r4, r5, lr}
- @ Ready to divide. Compute size of quotient; scale comparand.
- movs lr, r1
- mov r3, r0
- beq Ldiv_zero
-
-
- cmp r3, lr @ if r1 exceeds r0, done
- mov r2, #0
- bcc Lgot_result @ (and algorithm fails otherwise)
- mov r4, #(1 << (32 - 4 - 1))
- cmp r3, r4
- mov ip, #0
- bcc Lnot_really_big
-
- @ 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.
- mov r5, #1
- 1:
- cmp lr, r4
- bcs 3f
- mov lr, lr, lsl #4
- add ip, ip, #1
- b 1b
-
- @ Now compute r5.
- 2: adds lr, lr, lr
- add r5, r5, #1
- bcc Lnot_too_big
-
- @ We get here if the r1 overflowed while shifting.
- @ This means that r3 has the high-order bit set.
- @ Restore lr and subtract from r3.
- mov r4, r4, lsl #4
- mov lr, lr, lsr #1
- add lr, r4, lr
- sub r5, r5, #1
- b Ldo_single_div
-
- Lnot_too_big:
- 3: cmp lr, r3
- bcc 2b
-@ beq Ldo_single_div
-
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- @ lr > r3: went too far: back up 1 step
- @ srl lr, 1, lr
- @ dec r5
- @ do single-bit divide steps
- @
- @ We have to be careful here. We know that r3 >= lr, so we can do the
- @ first divide step without thinking. BUT, the others are conditional,
- @ and are only done if r3 >= 0. Because both r3 and lr 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...
- Ldo_single_div:
- subs r5, r5, #1
- blt Lend_regular_divide
- sub r3, r3, lr
- mov r2, #1
- b Lend_single_divloop
- Lsingle_divloop:
- cmp r3, #0
- mov r2, r2, lsl #1
- mov lr, lr, lsr #1
- @ r3 >= 0
- subpl r3, r3, lr
- addpl r2, r2, #1
- @ r3 < 0
- addmi r3, r3, lr
- submi r2, r2, #1
- Lend_single_divloop:
- subs r5, r5, #1
- bge Lsingle_divloop
- b Lend_regular_divide
-
-1:
- add ip, ip, #1
-Lnot_really_big:
- mov lr, lr, lsl #4
- cmp lr, r3
- bls 1b
- @
- @ HOW CAN ip EVER BE -1 HERE ?????
- @
- cmn ip, #1
- beq Lgot_result
-
-Ldivloop:
- cmp r3, #0 @ set up for initial iteration
- mov r2, r2, lsl #4
- @ depth 1, accumulated bits 0
- mov lr, lr, lsr #1
- blt L.1.1015
- @ remainder is positive
- subs r3, r3, lr
- @ depth 2, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.2.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.3.1018
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 7
- mov lr, lr, lsr #1
- blt L.4.1022
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #15
-
- b 9f
-
-L.4.1022:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #13
- b 9f
-
-
-
-L.3.1018:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 5
- mov lr, lr, lsr #1
- blt L.4.1020
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #11
-
- b 9f
-
-L.4.1020:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #9
- b 9f
-
-
-
-
-L.2.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.3.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.4.1018
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #7
-
- b 9f
-
-L.4.1018:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #5
- b 9f
-
-
-
-L.3.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.4.1016
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #3
-
- b 9f
-
-L.4.1016:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #1
- b 9f
-
-
-
-
-
-L.1.1015:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 2, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.2.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.3.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.4.1014
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #1
-
- b 9f
-
-L.4.1014:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #3
- b 9f
-
-
-
-L.3.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.4.1012
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #5
-
- b 9f
-
-L.4.1012:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #7
- b 9f
-
-
-
-
-L.2.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.3.1012
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -5
- mov lr, lr, lsr #1
- blt L.4.1010
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #9
-
- b 9f
-
-L.4.1010:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #11
- b 9f
-
-
-
-L.3.1012:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -7
- mov lr, lr, lsr #1
- blt L.4.1008
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #13
-
- b 9f
-
-L.4.1008:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #15
- b 9f
-
-
-
-
-
- 9:
-Lend_regular_divide:
- subs ip, ip, #1
- bge Ldivloop
- cmp r3, #0
- @ non-restoring fixup here (one instruction only!)
- sublt r2, r2, #1
-
+SYM (__udivsi3):
+ cmp divisor, #0
+ beq Ldiv0
+ mov curbit, #1
+ mov result, #0
+ cmp dividend, divisor
+ bcc Lgot_result
+Loop1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc Loop1
+
+Lbignum:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc Lbignum
+
+Loop3:
+ @ Test for possible subtractions, and note which bits
+ @ are done in the result. On the final pass, this may subtract
+ @ too much from the dividend, but the result will be ok, since the
+ @ "bit" will have been shifted out at the bottom.
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ orrcs result, result, curbit
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs result, result, curbit, lsr #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs result, result, curbit, lsr #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs result, result, curbit, lsr #3
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne Loop3
Lgot_result:
+ mov r0, result
+ RET pc, lr
- mov r0, r2
- ldmia sp!, {r4, r5, pc}
-
-Ldiv_zero:
- @ Divide by zero trap. If it returns, return 0 (about as
- @ wrong as possible, but that is what SunOS does...).
- bl ___div0
- mov r0, #0
- ldmia sp!, {r4, r5, pc}
+Ldiv0:
+ str lr, [sp, #-4]!
+ bl SYM (__div0)
+ mov r0, #0 @ about as wrong as it could be
+ ldmia sp!, {pc}RETCOND
#endif /* L_udivsi3 */
-#ifdef L_divsi3
-
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-.text
- .globl ___divsi3
- .align 0
-___divsi3:
- stmdb sp!, {r4, r5, r6, lr}
- @ compute sign of result; if neither is negative, no problem
- eor r6, r1, r0 @ compute sign
- cmp r1, #0
- rsbmi r1, r1, #0
- beq Ldiv_zero
- mov lr, r1
- movs r3, r0
- rsbmi r3, r3, #0 @ make dividend nonnegative
-
-
- cmp r3, lr @ if r1 exceeds r0, done
- mov r2, #0
- bcc Lgot_result @ (and algorithm fails otherwise)
- mov r4, #(1 << (32 - 4 - 1))
- cmp r3, r4
- mov ip, #0
- bcc Lnot_really_big
-
- @ 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.
- mov r5, #1
- 1:
- cmp lr, r4
- bcs 3f
- mov lr, lr, lsl #4
- add ip, ip, #1
- b 1b
-
- @ Now compute r5.
- 2: adds lr, lr, lr
- add r5, r5, #1
- bcc Lnot_too_big
-
- @ We get here if the r1 overflowed while shifting.
- @ This means that r3 has the high-order bit set.
- @ Restore lr and subtract from r3.
- mov r4, r4, lsl #4
- mov lr, lr, lsr #1
- add lr, r4, lr
- sub r5, r5, #1
- b Ldo_single_div
-
- Lnot_too_big:
- 3: cmp lr, r3
- bcc 2b
-@ beq Ldo_single_div
-
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- @ lr > r3: went too far: back up 1 step
- @ srl lr, 1, lr
- @ dec r5
- @ do single-bit divide steps
- @
- @ We have to be careful here. We know that r3 >= lr, so we can do the
- @ first divide step without thinking. BUT, the others are conditional,
- @ and are only done if r3 >= 0. Because both r3 and lr 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...
- Ldo_single_div:
- subs r5, r5, #1
- blt Lend_regular_divide
- sub r3, r3, lr
- mov r2, #1
- b Lend_single_divloop
- Lsingle_divloop:
- cmp r3, #0
- mov r2, r2, lsl #1
- mov lr, lr, lsr #1
- @ r3 >= 0
- subpl r3, r3, lr
- addpl r2, r2, #1
- @ r3 < 0
- addmi r3, r3, lr
- submi r2, r2, #1
- Lend_single_divloop:
- subs r5, r5, #1
- bge Lsingle_divloop
- b Lend_regular_divide
-
-1:
- add ip, ip, #1
-Lnot_really_big:
- mov lr, lr, lsl #4
- cmp lr, r3
- bls 1b
- @
- @ HOW CAN ip EVER BE -1 HERE ?????
- @
- cmn ip, #1
- beq Lgot_result
-
-Ldivloop:
- cmp r3, #0 @ set up for initial iteration
- mov r2, r2, lsl #4
- @ depth 1, accumulated bits 0
- mov lr, lr, lsr #1
- blt L.1.1015
- @ remainder is positive
- subs r3, r3, lr
- @ depth 2, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.2.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.3.1018
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 7
- mov lr, lr, lsr #1
- blt L.4.1022
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #15
-
- b 9f
-
-L.4.1022:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #13
- b 9f
-
-
-
-L.3.1018:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 5
- mov lr, lr, lsr #1
- blt L.4.1020
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #11
-
- b 9f
-
-L.4.1020:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #9
- b 9f
-
-
-
-
-L.2.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.3.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.4.1018
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #7
-
- b 9f
-
-L.4.1018:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #5
- b 9f
-
-
-
-L.3.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.4.1016
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #3
-
- b 9f
-
-L.4.1016:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #1
- b 9f
-
-
-
-
-
-L.1.1015:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 2, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.2.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.3.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.4.1014
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #1
-
- b 9f
-
-L.4.1014:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #3
- b 9f
-
-
-
-L.3.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.4.1012
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #5
-
- b 9f
-
-L.4.1012:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #7
- b 9f
-
-
-
-
-L.2.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.3.1012
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -5
- mov lr, lr, lsr #1
- blt L.4.1010
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #9
-
- b 9f
-
-L.4.1010:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #11
- b 9f
-
-
-
-L.3.1012:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -7
- mov lr, lr, lsr #1
- blt L.4.1008
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #13
-
- b 9f
-
-L.4.1008:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #15
- b 9f
-
-
-
-
-
- 9:
-Lend_regular_divide:
- subs ip, ip, #1
- bge Ldivloop
- cmp r3, #0
- @ non-restoring fixup here (one instruction only!)
- sublt r2, r2, #1
-
-
-Lgot_result:
- @ check to see if answer should be < 0
- cmp r6, #0
- rsbmi r2, r2, #0
-
- mov r0, r2
- ldmia sp!, {r4, r5, r6, pc}
-
-Ldiv_zero:
- @ Divide by zero trap. If it returns, return 0 (about as
- @ wrong as possible, but that is what SunOS does...).
- bl ___div0
- mov r0, #0
- ldmia sp!, {r4, r5, r6, pc}
-
-#endif /* L_divsi3 */
-
#ifdef L_umodsi3
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-.text
- .globl ___umodsi3
+dividend .req r0
+divisor .req r1
+overdone .req r2
+curbit .req r3
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+ .text
+ .globl SYM (__umodsi3)
.align 0
-___umodsi3:
- stmdb sp!, {r4, r5, lr}
- @ Ready to divide. Compute size of quotient; scale comparand.
- movs lr, r1
- mov r3, r0
- beq Ldiv_zero
-
-
- cmp r3, lr @ if r1 exceeds r0, done
- mov r2, #0
- bcc Lgot_result @ (and algorithm fails otherwise)
- mov r4, #(1 << (32 - 4 - 1))
- cmp r3, r4
- mov ip, #0
- bcc Lnot_really_big
-
- @ 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.
- mov r5, #1
- 1:
- cmp lr, r4
- bcs 3f
- mov lr, lr, lsl #4
- add ip, ip, #1
- b 1b
-
- @ Now compute r5.
- 2: adds lr, lr, lr
- add r5, r5, #1
- bcc Lnot_too_big
-
- @ We get here if the r1 overflowed while shifting.
- @ This means that r3 has the high-order bit set.
- @ Restore lr and subtract from r3.
- mov r4, r4, lsl #4
- mov lr, lr, lsr #1
- add lr, r4, lr
- sub r5, r5, #1
- b Ldo_single_div
-
- Lnot_too_big:
- 3: cmp lr, r3
- bcc 2b
-@ beq Ldo_single_div
-
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- @ lr > r3: went too far: back up 1 step
- @ srl lr, 1, lr
- @ dec r5
- @ do single-bit divide steps
- @
- @ We have to be careful here. We know that r3 >= lr, so we can do the
- @ first divide step without thinking. BUT, the others are conditional,
- @ and are only done if r3 >= 0. Because both r3 and lr 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...
- Ldo_single_div:
- subs r5, r5, #1
- blt Lend_regular_divide
- sub r3, r3, lr
- mov r2, #1
- b Lend_single_divloop
- Lsingle_divloop:
- cmp r3, #0
- mov r2, r2, lsl #1
- mov lr, lr, lsr #1
- @ r3 >= 0
- subpl r3, r3, lr
- addpl r2, r2, #1
- @ r3 < 0
- addmi r3, r3, lr
- submi r2, r2, #1
- Lend_single_divloop:
- subs r5, r5, #1
- bge Lsingle_divloop
- b Lend_regular_divide
-
-1:
- add ip, ip, #1
-Lnot_really_big:
- mov lr, lr, lsl #4
- cmp lr, r3
- bls 1b
- @
- @ HOW CAN ip EVER BE -1 HERE ?????
- @
- cmn ip, #1
- beq Lgot_result
-Ldivloop:
- cmp r3, #0 @ set up for initial iteration
- mov r2, r2, lsl #4
- @ depth 1, accumulated bits 0
- mov lr, lr, lsr #1
- blt L.1.1015
- @ remainder is positive
- subs r3, r3, lr
- @ depth 2, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.2.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.3.1018
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 7
- mov lr, lr, lsr #1
- blt L.4.1022
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #15
-
- b 9f
-
-L.4.1022:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #13
- b 9f
-
-
-
-L.3.1018:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 5
- mov lr, lr, lsr #1
- blt L.4.1020
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #11
-
- b 9f
-
-L.4.1020:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #9
- b 9f
-
-
-
-
-L.2.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.3.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.4.1018
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #7
-
- b 9f
-
-L.4.1018:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #5
- b 9f
-
-
-
-L.3.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.4.1016
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #3
-
- b 9f
-
-L.4.1016:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #1
- b 9f
-
-
-
-
-
-L.1.1015:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 2, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.2.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.3.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.4.1014
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #1
-
- b 9f
-
-L.4.1014:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #3
- b 9f
-
-
-
-L.3.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.4.1012
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #5
-
- b 9f
-
-L.4.1012:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #7
- b 9f
-
-
-
-
-L.2.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.3.1012
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -5
- mov lr, lr, lsr #1
- blt L.4.1010
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #9
-
- b 9f
-
-L.4.1010:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #11
- b 9f
-
-
-
-L.3.1012:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -7
- mov lr, lr, lsr #1
- blt L.4.1008
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #13
+SYM (__umodsi3):
+ cmp divisor, #0
+ beq Ldiv0
+ mov curbit, #1
+ cmp dividend, divisor
+ RETc(cc) pc, lr
+Loop1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc Loop1
+
+Lbignum:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc Lbignum
+
+Loop3:
+ @ Test for possible subtractions. On the final pass, this may
+ @ subtract too much from the dividend, so keep track of which
+ @ subtractions are done, we can fix them up afterwards...
+ mov overdone, #0
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs overdone, overdone, curbit, ror #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs overdone, overdone, curbit, ror #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs overdone, overdone, curbit, ror #3
+ mov ip, curbit
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne Loop3
+
+ @ Any subtractions that we should not have done will be recorded in
+ @ the top three bits of "overdone". Exactly which were not needed
+ @ are governed by the position of the bit, stored in ip.
+ @ If we terminated early, because dividend became zero,
+ @ then none of the below will match, since the bit in ip will not be
+ @ in the bottom nibble.
+ ands overdone, overdone, #0xe0000000
+ RETc(eq) pc, lr @ No fixups needed
+ tst overdone, ip, ror #3
+ addne dividend, dividend, divisor, lsr #3
+ tst overdone, ip, ror #2
+ addne dividend, dividend, divisor, lsr #2
+ tst overdone, ip, ror #1
+ addne dividend, dividend, divisor, lsr #1
+ RET pc, lr
+
+Ldiv0:
+ str lr, [sp, #-4]!
+ bl SYM (__div0)
+ mov r0, #0 @ about as wrong as it could be
+ ldmia sp!, {pc}RETCOND
- b 9f
-
-L.4.1008:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #15
- b 9f
+#endif /* L_umodsi3 */
-
-
-
-
- 9:
-Lend_regular_divide:
- subs ip, ip, #1
- bge Ldivloop
- cmp r3, #0
- @ non-restoring fixup here (one instruction only!)
- addlt r3, r1, r3
+#ifdef L_divsi3
+dividend .req r0
+divisor .req r1
+result .req r2
+curbit .req r3
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+ .text
+ .globl SYM (__divsi3)
+ .align 0
+SYM (__divsi3):
+ eor ip, dividend, divisor @ Save the sign of the result.
+ mov curbit, #1
+ mov result, #0
+ cmp divisor, #0
+ rsbmi divisor, divisor, #0 @ Loops below use unsigned.
+ beq Ldiv0
+ cmp dividend, #0
+ rsbmi dividend, dividend, #0
+ cmp dividend, divisor
+ bcc Lgot_result
+
+Loop1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc Loop1
+
+Lbignum:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc Lbignum
+
+Loop3:
+ @ Test for possible subtractions, and note which bits
+ @ are done in the result. On the final pass, this may subtract
+ @ too much from the dividend, but the result will be ok, since the
+ @ "bit" will have been shifted out at the bottom.
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ orrcs result, result, curbit
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs result, result, curbit, lsr #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs result, result, curbit, lsr #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs result, result, curbit, lsr #3
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne Loop3
Lgot_result:
+ mov r0, result
+ cmp ip, #0
+ rsbmi r0, r0, #0
+ RET pc, lr
- mov r0, r3
- ldmia sp!, {r4, r5, pc}
-
-Ldiv_zero:
- @ Divide by zero trap. If it returns, return 0 (about as
- @ wrong as possible, but that is what SunOS does...).
- bl ___div0
- mov r0, #0
- ldmia sp!, {r4, r5, pc}
+Ldiv0:
+ str lr, [sp, #-4]!
+ bl SYM (__div0)
+ mov r0, #0 @ about as wrong as it could be
+ ldmia sp!, {pc}RETCOND
-#endif /* L_umodsi3 */
+#endif /* L_divsi3 */
#ifdef L_modsi3
-ip .req r12
-sp .req r13
-lr .req r14
-pc .req r15
-.text
- .globl ___modsi3
+dividend .req r0
+divisor .req r1
+overdone .req r2
+curbit .req r3
+ip .req r12
+sp .req r13
+lr .req r14
+pc .req r15
+ .text
+ .globl SYM (__modsi3)
.align 0
-___modsi3:
- stmdb sp!, {r4, r5, r6, lr}
- @ compute sign of result; if neither is negative, no problem
- mov r6, r0
- cmp r1, #0
- rsbmi r1, r1, #0
- beq Ldiv_zero
- mov lr, r1
- movs r3, r0
- rsbmi r3, r3, #0 @ make dividend nonnegative
-
-
- cmp r3, lr @ if r1 exceeds r0, done
- mov r2, #0
- bcc Lgot_result @ (and algorithm fails otherwise)
- mov r4, #(1 << (32 - 4 - 1))
- cmp r3, r4
- mov ip, #0
- bcc Lnot_really_big
-
- @ 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.
- mov r5, #1
- 1:
- cmp lr, r4
- bcs 3f
- mov lr, lr, lsl #4
- add ip, ip, #1
- b 1b
-
- @ Now compute r5.
- 2: adds lr, lr, lr
- add r5, r5, #1
- bcc Lnot_too_big
-
- @ We get here if the r1 overflowed while shifting.
- @ This means that r3 has the high-order bit set.
- @ Restore lr and subtract from r3.
- mov r4, r4, lsl #4
- mov lr, lr, lsr #1
- add lr, r4, lr
- sub r5, r5, #1
- b Ldo_single_div
- Lnot_too_big:
- 3: cmp lr, r3
- bcc 2b
-@ beq Ldo_single_div
-
- /* NB: these are commented out in the V8-Sparc manual as well */
- /* (I do not understand this) */
- @ lr > r3: went too far: back up 1 step
- @ srl lr, 1, lr
- @ dec r5
- @ do single-bit divide steps
- @
- @ We have to be careful here. We know that r3 >= lr, so we can do the
- @ first divide step without thinking. BUT, the others are conditional,
- @ and are only done if r3 >= 0. Because both r3 and lr 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...
- Ldo_single_div:
- subs r5, r5, #1
- blt Lend_regular_divide
- sub r3, r3, lr
- mov r2, #1
- b Lend_single_divloop
- Lsingle_divloop:
- cmp r3, #0
- mov r2, r2, lsl #1
- mov lr, lr, lsr #1
- @ r3 >= 0
- subpl r3, r3, lr
- addpl r2, r2, #1
- @ r3 < 0
- addmi r3, r3, lr
- submi r2, r2, #1
- Lend_single_divloop:
- subs r5, r5, #1
- bge Lsingle_divloop
- b Lend_regular_divide
-
-1:
- add ip, ip, #1
-Lnot_really_big:
- mov lr, lr, lsl #4
- cmp lr, r3
- bls 1b
- @
- @ HOW CAN ip EVER BE -1 HERE ?????
- @
- cmn ip, #1
+SYM (__modsi3):
+ mov curbit, #1
+ cmp divisor, #0
+ rsbmi divisor, divisor, #0 @ Loops below use unsigned.
+ beq Ldiv0
+ @ Need to save the sign of the dividend, unfortunately, we need
+ @ ip later on; this is faster than pushing lr and using that.
+ str dividend, [sp, #-4]!
+ cmp dividend, #0
+ rsbmi dividend, dividend, #0
+ cmp dividend, divisor
+ bcc Lgot_result
+
+Loop1:
+ @ Unless the divisor is very big, shift it up in multiples of
+ @ four bits, since this is the amount of unwinding in the main
+ @ division loop. Continue shifting until the divisor is
+ @ larger than the dividend.
+ cmp divisor, #0x10000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #4
+ movcc curbit, curbit, lsl #4
+ bcc Loop1
+
+Lbignum:
+ @ For very big divisors, we must shift it a bit at a time, or
+ @ we will be in danger of overflowing.
+ cmp divisor, #0x80000000
+ cmpcc divisor, dividend
+ movcc divisor, divisor, lsl #1
+ movcc curbit, curbit, lsl #1
+ bcc Lbignum
+
+Loop3:
+ @ Test for possible subtractions. On the final pass, this may
+ @ subtract too much from the dividend, so keep track of which
+ @ subtractions are done, we can fix them up afterwards...
+ mov overdone, #0
+ cmp dividend, divisor
+ subcs dividend, dividend, divisor
+ cmp dividend, divisor, lsr #1
+ subcs dividend, dividend, divisor, lsr #1
+ orrcs overdone, overdone, curbit, ror #1
+ cmp dividend, divisor, lsr #2
+ subcs dividend, dividend, divisor, lsr #2
+ orrcs overdone, overdone, curbit, ror #2
+ cmp dividend, divisor, lsr #3
+ subcs dividend, dividend, divisor, lsr #3
+ orrcs overdone, overdone, curbit, ror #3
+ mov ip, curbit
+ cmp dividend, #0 @ Early termination?
+ movnes curbit, curbit, lsr #4 @ No, any more bits to do?
+ movne divisor, divisor, lsr #4
+ bne Loop3
+
+ @ Any subtractions that we should not have done will be recorded in
+ @ the top three bits of "overdone". Exactly which were not needed
+ @ are governed by the position of the bit, stored in ip.
+ @ If we terminated early, because dividend became zero,
+ @ then none of the below will match, since the bit in ip will not be
+ @ in the bottom nibble.
+ ands overdone, overdone, #0xe0000000
beq Lgot_result
-
-Ldivloop:
- cmp r3, #0 @ set up for initial iteration
- mov r2, r2, lsl #4
- @ depth 1, accumulated bits 0
- mov lr, lr, lsr #1
- blt L.1.1015
- @ remainder is positive
- subs r3, r3, lr
- @ depth 2, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.2.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.3.1018
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 7
- mov lr, lr, lsr #1
- blt L.4.1022
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #15
-
- b 9f
-
-L.4.1022:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #13
- b 9f
-
-
-
-L.3.1018:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 5
- mov lr, lr, lsr #1
- blt L.4.1020
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #11
-
- b 9f
-
-L.4.1020:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #9
- b 9f
-
-
-
-
-L.2.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.3.1016
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits 3
- mov lr, lr, lsr #1
- blt L.4.1018
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #7
-
- b 9f
-
-L.4.1018:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #5
- b 9f
-
-
-
-L.3.1016:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits 1
- mov lr, lr, lsr #1
- blt L.4.1016
- @ remainder is positive
- subs r3, r3, lr
- add r2, r2, #3
-
- b 9f
-
-L.4.1016:
- @ remainder is negative
- adds r3, r3, lr
- add r2, r2, #1
- b 9f
-
-
-
-
-
-L.1.1015:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 2, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.2.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 3, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.3.1014
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -1
- mov lr, lr, lsr #1
- blt L.4.1014
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #1
-
- b 9f
-
-L.4.1014:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #3
- b 9f
-
-
-
-L.3.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.4.1012
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #5
-
- b 9f
-
-L.4.1012:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #7
- b 9f
-
-
-
-
-L.2.1014:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 3, accumulated bits -3
- mov lr, lr, lsr #1
- blt L.3.1012
- @ remainder is positive
- subs r3, r3, lr
- @ depth 4, accumulated bits -5
- mov lr, lr, lsr #1
- blt L.4.1010
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #9
-
- b 9f
-
-L.4.1010:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #11
- b 9f
-
-
-
-L.3.1012:
- @ remainder is negative
- adds r3, r3, lr
- @ depth 4, accumulated bits -7
- mov lr, lr, lsr #1
- blt L.4.1008
- @ remainder is positive
- subs r3, r3, lr
- sub r2, r2, #13
-
- b 9f
-
-L.4.1008:
- @ remainder is negative
- adds r3, r3, lr
- sub r2, r2, #15
- b 9f
-
-
-
-
-
- 9:
-Lend_regular_divide:
- subs ip, ip, #1
- bge Ldivloop
- cmp r3, #0
- @ non-restoring fixup here (one instruction only!)
- addlt r3, r1, r3
-
-
+ tst overdone, ip, ror #3
+ addne dividend, dividend, divisor, lsr #3
+ tst overdone, ip, ror #2
+ addne dividend, dividend, divisor, lsr #2
+ tst overdone, ip, ror #1
+ addne dividend, dividend, divisor, lsr #1
Lgot_result:
- @ check to see if answer should be < 0
- cmp r6, #0
- rsbmi r3, r3, #0
+ ldr ip, [sp], #4
+ cmp ip, #0
+ rsbmi dividend, dividend, #0
+ RET pc, lr
- mov r0, r3
- ldmia sp!, {r4, r5, r6, pc}
-
-Ldiv_zero:
- @ Divide by zero trap. If it returns, return 0 (about as
- @ wrong as possible, but that is what SunOS does...).
- bl ___div0
- mov r0, #0
- ldmia sp!, {r4, r5, r6, pc}
+Ldiv0:
+ str lr, [sp, #-4]!
+ bl SYM (__div0)
+ mov r0, #0 @ about as wrong as it could be
+ ldmia sp!, {pc}RETCOND
#endif /* L_modsi3 */
#ifdef L_dvmd_tls
- .globl ___div0
+ .globl SYM (__div0)
.align 0
-___div0:
- mov pc, lr
+SYM (__div0):
+ RET pc, lr
#endif /* L_divmodsi_tools */
+
+#ifdef L_dvmd_lnx
+@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
+
+#include <asm/unistd.h>
+#define SIGFPE 8 @ cant use <asm/signal.h> as it
+ @ contains too much C rubbish
+ .globl SYM (__div0)
+ .align 0
+SYM (__div0):
+ stmfd sp!, {r1, lr}
+ swi __NR_getpid
+ cmn r0, #1000
+ ldmgefd sp!, {r1, pc}RETCOND @ not much we can do
+ mov r1, #SIGFPE
+ swi __NR_kill
+ ldmfd sp!, {r1, pc}RETCOND
+
+#endif /* L_dvmd_lnx */
diff --git a/gnu/usr.bin/gcc/config/arm/riscix.h b/gnu/usr.bin/gcc/config/arm/riscix.h
index a3b9c3d0702..5ccb2131e6e 100644
--- a/gnu/usr.bin/gcc/config/arm/riscix.h
+++ b/gnu/usr.bin/gcc/config/arm/riscix.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. ARM RISCiX version.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rwe11@cl.cam.ac.uk), based on original
work by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
@@ -51,13 +51,6 @@ Boston, MA 02111-1307, USA. */
"-Darm -Driscix -Dunix -Asystem(unix) -Acpu(arm) -Amachine(arm)"
#endif
-#ifndef CPP_SPEC
-#define CPP_SPEC "%{m6:-D__arm6__} \
- %{mbsd:%{pedantic:%e-mbsd and -pedantic incompatible} -D_BSD_C} \
- %{mxopen:%{mbsd:%e-mbsd and -mxopen incompatible} \
- %{pedantic:%e-mxopen and -pedantic incompatible} -D_XOPEN_C} \
- %{!mbsd:%{!mxopen:%{!ansi: -D_BSD_C}}}"
-#endif
/* RISCiX has some weird symbol name munging, that is done to the object module
after assembly, which enables multiple libraries to be supported within
@@ -123,7 +116,24 @@ Boston, MA 02111-1307, USA. */
/* Maths operation domain error number, EDOM */
#define TARGET_EDOM 33
-#include "arm/arm.h"
+
+/* Override the normal default CPU */
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm2
+
+#include "arm/aout.h"
+
+/* The RISCiX assembler does not understand .set */
+#undef SET_ASM_OP
+
+/* Override CPP_SPEC, there's no point handling endianness (and probably
+ not much point handling apcs_pc), and we want to add the right #defines
+ when using the include files. */
+#undef CPP_SPEC
+#define CPP_SPEC "%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) \
+ %{mbsd:%{pedantic:%e-mbsd and -pedantic incompatible} -D_BSD_C} \
+ %{mxopen:%{mbsd:%e-mbsd and -mxopen incompatible} \
+ %{pedantic:%e-mxopen and -pedantic incompatible} -D_XOPEN_C} \
+ %{!mbsd:%{!mxopen:%{!ansi: -D_BSD_C}}}"
/* The native RISCiX assembler does not support stabs of any kind; because
the native assembler is not used by the compiler, Acorn didn't feel it was
diff --git a/gnu/usr.bin/gcc/config/arm/riscix1-1.h b/gnu/usr.bin/gcc/config/arm/riscix1-1.h
index 8be8539b892..3718635430d 100644
--- a/gnu/usr.bin/gcc/config/arm/riscix1-1.h
+++ b/gnu/usr.bin/gcc/config/arm/riscix1-1.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. ARM RISCiX 1.1x version.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rwe11@cl.cam.ac.uk), based on original
work by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
@@ -21,7 +21,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. */
-/* RISCix 1.1x is basically the same as 1.2x except that it doesn't have
+/* RISCiX 1.1x is basically the same as 1.2x except that it doesn't have
symrename or atexit. */
/* Translation to find startup files. On RISCiX boxes, gcrt0.o is in
@@ -33,10 +33,6 @@ Boston, MA 02111-1307, USA. */
#define CPP_PREDEFINES "-Darm -Driscix -Dunix -Asystem(unix) -Acpu(arm) -Amachine(arm)"
#endif
-#ifndef CPP_SPEC
-#define CPP_SPEC "%{m6:-D__arm6__} %{!ansi: -D_BSD_C}"
-#endif
-
/* Riscix 1.1 doesn't have X/OPEN support, so only accept -mbsd (but ignore
it).
By not having -mxopen and -mno-symrename, we get warning messages,
@@ -81,7 +77,16 @@ Boston, MA 02111-1307, USA. */
#define SYMBOL__MAIN __gccmain
#endif
-#include "arm/arm.h"
+/* Override the normal default CPU */
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm2
+
+#include "arm/aout.h"
+
+#undef CPP_SPEC
+#define CPP_SPEC "\
+%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %{!ansi: -D_BSD_C} \
+"
+
/* The native RISCiX assembler does not support stabs of any kind; because
the native assembler is not used by the compiler, Acorn didn't feel it was
diff --git a/gnu/usr.bin/gcc/config/arm/semi.h b/gnu/usr.bin/gcc/config/arm/semi.h
index d282ac319e6..346c61329b8 100644
--- a/gnu/usr.bin/gcc/config/arm/semi.h
+++ b/gnu/usr.bin/gcc/config/arm/semi.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. ARM on semi-hosted platform
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (richard.earnshaw@armltd.co.uk)
This file is part of GNU CC.
@@ -23,16 +23,18 @@ Boston, MA 02111-1307, USA. */
#define LIB_SPEC "-lc"
-#define LINK_SPEC "-X"
-
#define CPP_PREDEFINES \
- "-Darm -Dsemi -Acpu(arm) -Amachine(arm)"
+ "-Darm -D__semi__ -Acpu(arm) -Amachine(arm)"
+
+#define ASM_SPEC "%{mbig-endian:-EB}"
+
+#define LINK_SPEC "%{mbig-endian:-EB} -X"
#define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
-#define TARGET_DEFAULT 8 /* APCS-32 (ARM 6) */
+#define TARGET_DEFAULT ARM_FLAG_APCS_32
-/* Currently we have no support for atexit. */
-#define EXIT_BODY {}
+#include "arm/aout.h"
-#include "arm/arm.h"
+#undef CPP_APCS_PC_DEFAULT_SPEC
+#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
diff --git a/gnu/usr.bin/gcc/config/arm/t-semi b/gnu/usr.bin/gcc/config/arm/t-semi
index aee22a9ccf9..9e4ddba3716 100644
--- a/gnu/usr.bin/gcc/config/arm/t-semi
+++ b/gnu/usr.bin/gcc/config/arm/t-semi
@@ -1,11 +1,44 @@
# Just for these, we omit the frame pointer since it makes such a big
# difference. It is then pointless adding debugging.
-LIBGCC2_CFLAGS=-O2 -fomit-frame-pointer $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -g0 \
- -Dinhibit_libc
+LIBGCC2_CFLAGS=-O2 -fomit-frame-pointer $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -g0
# Don't build enquire
ENQUIRE=
+# Can't test libgcc1 since it tries to bring in things like malloc, and
+# there probably isn't a libc to link against until we have a compiler.
+LIBGCC1_TEST =
+
CROSS_LIBGCC1 = libgcc1-asm.a
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls
+
+# These are really part of libgcc1, but this will cause them to be
+# built correctly, so...
+
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __SOFTFP__' > fp-bit.c
+ echo '#define FLOAT' >> fp-bit.c
+ echo '#ifndef __ARMEB__' >> fp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+ echo '#endif' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+ echo '#endif' >> fp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __SOFTFP__' > dp-bit.c
+ echo '#ifndef __ARMEB__' >> dp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+ echo '#define FLOAT_WORD_ORDER_MISMATCH' >> dp-bit.c
+ echo '#endif' >> dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+ echo '#endif' >> dp-bit.c
+
+MULTILIB_OPTIONS = msoft-float mapcs-26 mbig-endian mwords-little-endian
+MULTILIB_DIRNAMES = soft apcs26 big wlittle
+MULTILIB_EXCEPTIONS = *mapcs-26/*mbig-endian* mwords-little-endian *mapcs-26/mwords-little-endian msoft-float/mwords-little-endian
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/arm/xm-arm.h b/gnu/usr.bin/gcc/config/arm/xm-arm.h
index 00818e75eab..a6143fa9abf 100644
--- a/gnu/usr.bin/gcc/config/arm/xm-arm.h
+++ b/gnu/usr.bin/gcc/config/arm/xm-arm.h
@@ -44,12 +44,6 @@ Boston, MA 02111-1307, USA. */
#define USE_C_ALLOCA
#endif
-/* Define this if the library function putenv is available on your machine */
-#define HAVE_PUTENV 1
-
-/* Define this if the library function vprintf is available on your machine */
-#define HAVE_VPRINTF 1
-
/* Define this to be 1 if you know the host compiler supports prototypes, even
if it doesn't define __STDC__, or define it to be 0 if you do not want any
prototypes when compiling GNU CC. */
diff --git a/gnu/usr.bin/gcc/config/clipper/clipper.c b/gnu/usr.bin/gcc/config/clipper/clipper.c
index 9ee6f444981..f3bae7eead4 100644
--- a/gnu/usr.bin/gcc/config/clipper/clipper.c
+++ b/gnu/usr.bin/gcc/config/clipper/clipper.c
@@ -1,6 +1,5 @@
/* Subroutines for insn-output.c for Clipper
- Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
-
+ Copyright (C) 1987, 1988, 1991, 1997 Free Software Foundation, Inc.
Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)
This file is part of GNU CC.
@@ -20,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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -438,10 +437,45 @@ clipper_builtin_saveregs (arglist)
gen_rtx (CONST_INT, Pmode, 16))),
scratch);
+
+ if (flag_check_memory_usage)
+ {
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ addr, ptr_mode,
+ GEN_INT (5 * GET_MODE_SIZE (SImode)),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ f0_addr, ptr_mode,
+ GEN_INT (GET_MODE_SIZE (DFmode)),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ f1_addr, ptr_mode,
+ GEN_INT (GET_MODE_SIZE (DFmode)),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ r0_addr, ptr_mode,
+ GEN_INT (GET_MODE_SIZE (SImode)),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ r1_addr, ptr_mode,
+ GEN_INT (GET_MODE_SIZE (SImode)),
+ 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. This fails when not optimizing and produces worse code when
optimizing. */
-
return XEXP (block, 0);
}
diff --git a/gnu/usr.bin/gcc/config/clipper/clipper.h b/gnu/usr.bin/gcc/config/clipper/clipper.h
index 53b90f70e99..9600df34177 100644
--- a/gnu/usr.bin/gcc/config/clipper/clipper.h
+++ b/gnu/usr.bin/gcc/config/clipper/clipper.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Clipper version.
- Copyright (C) 1987, 88, 91, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 93-95, 1996 Free Software Foundation, Inc.
Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)
This file is part of GNU CC.
@@ -461,7 +461,7 @@ struct _clipper_cum_args { int num; int size; };
clipper passes the address of a struct in r0, set num = 1 in this case */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM).num = ((FNTYPE) != 0 && aggregate_value_p (TREE_TYPE (FNTYPE))), \
(CUM).size = 0)
@@ -1055,6 +1055,7 @@ do \
/* This says how to output an assembler line
to define a local common symbol. */
+/* ??? The use of .bss here seems odd. */
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE,NAME,SIZE,ALIGN) \
( data_section (), \
diff --git a/gnu/usr.bin/gcc/config/clipper/clipper.md b/gnu/usr.bin/gcc/config/clipper/clipper.md
index 7230b224499..e045ce9acc8 100644
--- a/gnu/usr.bin/gcc/config/clipper/clipper.md
+++ b/gnu/usr.bin/gcc/config/clipper/clipper.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU compiler, Clipper Version
-;; Copyright (C) 1987, 1988, 1991, 1993, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 88, 91, 93, 94, 1997 Free Software Foundation, Inc.
;; Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)
;; This file is part of GNU CC.
@@ -532,8 +532,8 @@
operands[6] = addr0;
operands[7] = 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);
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = force_reg (SImode, operands[2]);
@@ -1362,6 +1362,43 @@
""
"call sp,%1")
+;; Call subroutine returning any type.
+
+(define_expand "untyped_call"
+ [(parallel [(call (match_operand 0 "" "")
+ (const_int 0))
+ (match_operand 1 "" "")
+ (match_operand 2 "" "")])]
+ ""
+ "
+{
+ int i;
+
+ emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_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)]
+ ""
+ "")
+
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
diff --git a/gnu/usr.bin/gcc/config/clipper/clix.h b/gnu/usr.bin/gcc/config/clipper/clix.h
index 897267d317d..c36e4de46a0 100644
--- a/gnu/usr.bin/gcc/config/clipper/clix.h
+++ b/gnu/usr.bin/gcc/config/clipper/clix.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Clipper/Clix version.
- Copyright (C) 1988, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1993, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,10 +18,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 "clipper/clipper.h"
-
-#include "svr3.h"
-
/* Names to predefine in the preprocessor for this target machine. */
#define CPP_PREDEFINES "-Dclipper -Dunix -Asystem(unix) -Asystem(svr3) -Acpu(clipper) -Amachine(clipper)"
@@ -35,6 +31,8 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
+#define TARGET_MEM_FUNCTIONS
+
#undef HAVE_ATEXIT
#define HAVE_ATEXIT
diff --git a/gnu/usr.bin/gcc/config/clipper/xm-clix.h b/gnu/usr.bin/gcc/config/clipper/xm-clix.h
index 5485c242539..726660df46a 100644
--- a/gnu/usr.bin/gcc/config/clipper/xm-clix.h
+++ b/gnu/usr.bin/gcc/config/clipper/xm-clix.h
@@ -27,13 +27,4 @@
/* isinf isn't there, but finite is. */
#define isinf(x) (!finite(x))
-
#define USG
-
-#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 index strchr
-#define rindex strrchr
-
-#define TARGET_MEM_FUNCTIONS
diff --git a/gnu/usr.bin/gcc/config/convex/convex.c b/gnu/usr.bin/gcc/config/convex/convex.c
index 05e3ef1b572..cd2eb55c964 100644
--- a/gnu/usr.bin/gcc/config/convex/convex.c
+++ b/gnu/usr.bin/gcc/config/convex/convex.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Convex.
- Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1993, 1994, 1997 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 <stdio.h>
#include "tree.h"
#include "rtl.h"
#include "regs.h"
@@ -31,9 +32,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "expr.h"
-#undef NULL
-#include <stdio.h>
-
/* Tables used in convex.h */
char regno_ok_for_index_p_base[1 + LAST_VIRTUAL_REGISTER + 1];
@@ -403,7 +401,9 @@ expand_movstr_call (operands)
VOIDmode, 3,
XEXP (operands[0], 0), Pmode,
XEXP (operands[1], 0), Pmode,
- operands[2], SImode);
+ convert_to_mode (TYPE_MODE (sizetype), operands[2],
+ TREE_UNSIGNED (sizetype)),
+ TYPE_MODE (sizetype));
}
#if _IEEE_FLOAT_
diff --git a/gnu/usr.bin/gcc/config/convex/convex.h b/gnu/usr.bin/gcc/config/convex/convex.h
index 0ac8c90c46c..41f1bacf5d9 100644
--- a/gnu/usr.bin/gcc/config/convex/convex.h
+++ b/gnu/usr.bin/gcc/config/convex/convex.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Convex version.
- Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -45,7 +45,7 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
#ifndef TARGET_DEFAULT
-#error Use one of convex1.h, convex2.h, etc.
+#define TARGET_DEFAULT 0
#endif
#define TARGET_SWITCHES \
@@ -62,7 +62,7 @@ extern int target_flags;
{ "volatile-nocache", 0400 }, \
{ "long64", 01000 }, \
{ "long32", -01000 }, \
- { "", TARGET_DEFAULT }}
+ { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}}
/* Macros used in the machine description to test the flags. */
@@ -77,12 +77,9 @@ extern int target_flags;
#define OVERRIDE_OPTIONS \
{ \
- extern int dollars_in_ident; \
init_convex (); \
- /* To compile system header files, allow $ in identifiers even if -ansi */ \
- dollars_in_ident = 1; \
- if ((target_flags & 077) != (TARGET_DEFAULT & 077)) \
- target_flags &= ~TARGET_DEFAULT; \
+ if ((target_flags & 077) != ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 077)) \
+ target_flags &= ~ (TARGET_DEFAULT | TARGET_CPU_DEFAULT); \
if (target_flags & 001) \
target_cpu = 0; \
else if (target_flags & 006) \
@@ -106,7 +103,7 @@ extern int target_flags;
Make a target-dependent __convex_cxx__ define to relay the target cpu
to the program being compiled. */
-#if TARGET_DEFAULT & 1
+#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1
/* C1 default */
@@ -158,7 +155,7 @@ extern int target_flags;
#endif
-#if TARGET_DEFAULT & 2
+#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 2
/* C2 default */
@@ -210,7 +207,7 @@ extern int target_flags;
#endif
-#if TARGET_DEFAULT & 4
+#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 4
/* C32 default */
@@ -262,7 +259,7 @@ extern int target_flags;
#endif
-#if TARGET_DEFAULT & 010
+#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 010
/* C34 default */
@@ -314,7 +311,7 @@ extern int target_flags;
#endif
-#if TARGET_DEFAULT & 020
+#if (TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 020
/* C38 default */
@@ -417,10 +414,6 @@ extern int target_flags;
#define LINK_LIBGCC_SPECIAL_1
-/* Allow $ in identifiers. */
-
-#define DOLLARS_IN_IDENTIFIERS 2
-
/* Since IEEE support was added to gcc, most things seem to like it
better if we disable exceptions and check afterward for infinity. */
@@ -791,7 +784,7 @@ enum reg_class {
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) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
@@ -1182,7 +1175,7 @@ extern double atof();
/* Check a `double' value for validity for a particular machine mode. */
#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
- overflow = check_float_value (MODE, &D, OVERFLOW)
+ OVERFLOW = check_float_value (MODE, &D, OVERFLOW)
/* Tell final.c how to eliminate redundant test instructions. */
@@ -1237,21 +1230,6 @@ extern double atof();
#define BSS_SECTION_ASM_OP (current_section_is_text = 0, ".bss")
-/* Define the .bss section for ASM_OUTPUT_LOCAL to use. */
-
-#define EXTRA_SECTIONS in_bss
-
-#define EXTRA_SECTION_FUNCTIONS \
-void \
-bss_section () \
-{ \
- if (in_section != in_bss) \
- { \
- fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \
- in_section = in_bss; \
- } \
-}
-
/* This is how to output an assembler line
that says to advance the location counter
to a multiple of 2**LOG bytes. */
@@ -1307,10 +1285,9 @@ bss_section () \
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs (".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. */
+/* 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/gnu/usr.bin/gcc/config/convex/xm-convex.h b/gnu/usr.bin/gcc/config/convex/xm-convex.h
index ebe334579ec..aaaa3b1464c 100644
--- a/gnu/usr.bin/gcc/config/convex/xm-convex.h
+++ b/gnu/usr.bin/gcc/config/convex/xm-convex.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for Convex.
- Copyright (C) 1989, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -42,11 +42,6 @@ Boston, MA 02111-1307, USA. */
#define P_tmpdir "/tmp/"
-/* Use memcpy and memset -- either would work but these get inlined. */
-
-#define bcopy(a,b,c) memcpy (b,a,c)
-#define bzero(a,b) memset (a,0,b)
-
/* Convex uses Vax or IEEE floats.
Both formats have Vax semantics. */
diff --git a/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.c b/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.c
index 90b316d5a1c..f108ef926f6 100644
--- a/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.c
+++ b/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.c
@@ -1,5 +1,5 @@
/* Subroutines for assembler code output on the DSP1610.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by Michael Collison (collison@world.std.com).
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. */
/* Some output-actions in dsp1600.md need these. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.h b/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.h
index 6e32594b6e7..3047372cc71 100644
--- a/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.h
+++ b/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. AT&T DSP1600.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Michael Collison (collison@world.std.com).
This file is part of GNU CC.
@@ -142,10 +142,10 @@ extern char *output_block_move();
#define STANDARD_EXEC_PREFIX "/d1600/bin"
/* Command line options to the AT&T assembler */
-#define ASM_SPEC "%{V} %{v:%{!V:-V}} %{g*:-g}"
+#define ASM_SPEC "%{v:-V} %{g*:-g}"
/* Command line options for the AT&T linker */
-#define LINK_SPEC "%{V} %{v:%{!V:-V}} %{minit:-i} \
+#define LINK_SPEC "%{v:-V} %{minit:-i} \
%{!ifile*:%{mmap1:-ifile m1_deflt.if%s} \
%{mmap2:-ifile m2_deflt.if%s} \
%{mmap3:-ifile m3_deflt.if%s} \
@@ -440,7 +440,7 @@ extern int target_flags;
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
- The registers are layed out as follows:
+ The registers are laid out as follows:
{a0,a0l,a1,a1l,x,y,yl,p,pl} - Data Arithmetic Unit
{r0,r1,r2,r3,j,k,ybase} - Y Space Address Arithmetic Unit
@@ -946,7 +946,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
/* Macros to check register numbers against specific register classes. */
@@ -1192,7 +1192,7 @@ extern struct dsp16xx_frame_info current_frame_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. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) ((CUM) = 0)
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0)
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.
@@ -1609,9 +1609,9 @@ extern struct dsp16xx_frame_info current_frame_info;
specify it. */
#define DEFAULT_CHIP_NAME "1610"
-/* A list of names for sections other than the standard two, which are
- 'in_text' and 'in_data'. */
-#define EXTRA_SECTIONS in_bss, in_const
+/* A list of names for sections other than the standard ones, which are
+ 'in_text' and 'in_data' (and .bss if BSS_SECTION_ASM_OP is defined). */
+#define EXTRA_SECTIONS in_const
#define EXTRA_SECTION_FUNCTIONS \
void \
@@ -1622,16 +1622,7 @@ const_section () \
fprintf (asm_out_file, "%s\n", READONLY_SECTION_ASM_OP); \
in_section = in_const; \
} \
-} \
-void \
-bss_section () \
-{ \
- if (in_section != in_bss) { \
- fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \
- in_section = in_bss; \
- } \
}
-
/* THE OVERALL FRAMEWORK OF AN ASSEMBLER FILE */
@@ -1661,7 +1652,7 @@ bss_section () \
/* This is how to output an assembler line defining a `float' constant. */
#define ASM_OUTPUT_FLOAT(FILE,VALUE) asm_output_float (FILE, VALUE)
-/* This is how to output and assembler line defininf a 'float' constant of
+/* This is how to output an assembler line defining a 'float' constant of
size HFmode. */
#define ASM_OUTPUT_SHORT_FLOAT(FILE,VALUE) asm_output_float (FILE, VALUE)
@@ -1678,7 +1669,9 @@ bss_section () \
#define ASM_OUTPUT_INT(FILE, EXP) asm_output_long(FILE,INTVAL(EXP))
/* This is how to output an assembler line for a numeric constant byte. */
-#define ASM_OUTPUT_BYTE(FILE,VALUE) ASM_OUTPUT_CHAR(FILE,VALUE)
+#define ASM_OUTPUT_BYTE(FILE,VALUE) \
+ fprintf ((FILE), "\tint %ld\n", (long)(VALUE))
+
/* This is how we output a 'c' character string. For the 16xx
assembler we have to do it one letter at a time */
@@ -1805,10 +1798,10 @@ bss_section () \
assemble_name (FILE, XSTR (FUN, 0)); \
fprintf (FILE, "\n"); \
}
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, "_%s", NAME)
+
+/* The prefix to add to user-visible assembler symbols. */
+
+#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/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.md b/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.md
index 4e8f31dfe6a..9274f47082e 100644
--- a/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.md
+++ b/gnu/usr.bin/gcc/config/dsp16xx/dsp16xx.md
@@ -1,5 +1,5 @@
;;- Machine description for the AT&T DSP1600 for GNU C compiler
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
;; Contributed by Michael Collison (collison@world.std.com).
;; This file is part of GNU CC.
@@ -1136,8 +1136,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);
}")
(define_insn ""
diff --git a/gnu/usr.bin/gcc/config/elxsi/elxsi.c b/gnu/usr.bin/gcc/config/elxsi/elxsi.c
index e2dadb99a39..b8818531b84 100644
--- a/gnu/usr.bin/gcc/config/elxsi/elxsi.c
+++ b/gnu/usr.bin/gcc/config/elxsi/elxsi.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for GNU compiler. Elxsi version.
- Copyright (C) 1987, 1992 Free Software Foundation, Inc
+ Copyright (C) 1987, 1992, 1997 Free Software Foundation, Inc
This port, done by Mike Stump <mrs@cygnus.com> in 1988, and is the first
64 bit port of GNU CC.
Based upon the VAX port.
@@ -21,8 +21,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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
extern char *reg_names[];
diff --git a/gnu/usr.bin/gcc/config/elxsi/elxsi.h b/gnu/usr.bin/gcc/config/elxsi/elxsi.h
index a6955c13704..d0d4c73807d 100644
--- a/gnu/usr.bin/gcc/config/elxsi/elxsi.h
+++ b/gnu/usr.bin/gcc/config/elxsi/elxsi.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. Elxsi version.
- Copyright (C) 1987, 1988, 1992, 1995 Free Software Foundation, Inc.
- This port, done by Mike Stump <mrs@cygnus.com> in 1988, is the first
+ Copyright (C) 1987, 1988, 1992, 1995, 1996 Free Software Foundation, Inc.
+ This port, contributed by Mike Stump <mrs@cygnus.com> in 1988, is the first
64 bit port of GNU CC.
Based upon the VAX port.
@@ -360,7 +360,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES };
On the vax, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,x) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,x,INDIRECT) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
@@ -689,27 +689,6 @@ enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES };
/* #define UDIVSI3_LIBCALL "*udiv" */
/* #define UMODSI3_LIBCALL "*urem" */
-
-/* Check a `double' value for validity for a particular machine mode. */
-
-/* Note that it is very hard to accidentally create a number that fits in a
- double but not in a float, since their ranges are almost the same. */
-#define CHECK_FLOAT_VALUE(mode, d) \
- if ((mode) == SFmode) \
- { \
- if ((d) > 1.7014117331926443e+38) \
- { error ("magnitude of constant too large for `float'"); \
- (d) = 1.7014117331926443e+38; } \
- else if ((d) < -1.7014117331926443e+38) \
- { error ("magnitude of constant too large for `float'"); \
- (d) = -1.7014117331926443e+38; } \
- else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \
- { warning ("`float' constant truncated to zero"); \
- (d) = 0.0; } \
- else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \
- { warning ("`float' constant truncated to zero"); \
- (d) = 0.0; } \
- }
/* Tell final.c how to eliminate redundant test instructions. */
@@ -797,10 +776,9 @@ enum reg_class { NO_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES };
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs ("\t.extdef\t", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
-/* 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/gnu/usr.bin/gcc/config/fp-bit.c b/gnu/usr.bin/gcc/config/fp-bit.c
index 4ee08f1629b..c05f215c0ee 100644
--- a/gnu/usr.bin/gcc/config/fp-bit.c
+++ b/gnu/usr.bin/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 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
@@ -62,6 +61,49 @@ 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(); }
+#else /* !EXTENDED_FLOAT_STUBS, rest of file */
+
+
typedef SFtype __attribute__ ((mode (SF)));
typedef DFtype __attribute__ ((mode (DF)));
@@ -199,7 +241,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))
@@ -414,7 +456,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;
@@ -441,7 +483,7 @@ static 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 +546,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;
@@ -901,13 +943,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))
{
@@ -1229,7 +1273,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;
@@ -1256,19 +1300,19 @@ 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);
}
@@ -1343,10 +1387,19 @@ 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 /* !EXTENDED_FLOAT_STUBS */
diff --git a/gnu/usr.bin/gcc/config/fx80/fx80.c b/gnu/usr.bin/gcc/config/fx80/fx80.c
index a87be41e5e8..4e8f42086d3 100644
--- a/gnu/usr.bin/gcc/config/fx80/fx80.c
+++ b/gnu/usr.bin/gcc/config/fx80/fx80.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Alliant FX computers.
- Copyright (C) 1989,1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,8 +20,8 @@ Boston, MA 02111-1307, USA. */
/* Some output-actions in alliant.md need these. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gnu/usr.bin/gcc/config/fx80/fx80.h b/gnu/usr.bin/gcc/config/fx80/fx80.h
index 82797fbb402..b56834a372c 100644
--- a/gnu/usr.bin/gcc/config/fx80/fx80.h
+++ b/gnu/usr.bin/gcc/config/fx80/fx80.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Alliant FX version.
- Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Adapted from m68k.h by Paul Petersen (petersen@uicsrd.csrd.uiuc.edu)
and Joe Weening (weening@gang-of-four.stanford.edu).
@@ -503,7 +503,7 @@ extern enum reg_class regno_reg_class[];
On the Alliant, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
@@ -1063,11 +1063,9 @@ extern enum reg_class regno_reg_class[];
#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. */
diff --git a/gnu/usr.bin/gcc/config/fx80/fx80.md b/gnu/usr.bin/gcc/config/fx80/fx80.md
index 641ba9aea80..6862767d764 100644
--- a/gnu/usr.bin/gcc/config/fx80/fx80.md
+++ b/gnu/usr.bin/gcc/config/fx80/fx80.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU C compiler for Alliant FX systems
-;; Copyright (C) 1989, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1994, 1996 Free Software Foundation, Inc.
;; Adapted from m68k.md by Paul Petersen (petersen@uicsrd.csrd.uiuc.edu)
;; and Joe Weening (weening@gang-of-four.stanford.edu).
@@ -195,7 +195,7 @@
;; Recognizers for btst instructions.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
(const_int 1)
(minus:SI (const_int 7)
(match_operand:SI 1 "general_operand" "di"))))]
@@ -203,7 +203,7 @@
"* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
(const_int 1)
(minus:SI (const_int 31)
(match_operand:SI 1 "general_operand" "di"))))]
@@ -215,7 +215,7 @@
;; are automatically masked to 3 or 5 bits.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o")
(const_int 1)
(minus:SI (const_int 7)
(and:SI
@@ -225,7 +225,7 @@
"* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d")
(const_int 1)
(minus:SI (const_int 31)
(and:SI
@@ -237,7 +237,7 @@
;; Nonoffsettable mem refs are ok in this one pattern
;; since we don't try to adjust them.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "md")
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
(const_int 1)
(match_operand:SI 1 "general_operand" "i")))]
"GET_CODE (operands[1]) == CONST_INT
@@ -250,7 +250,7 @@
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "do")
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do")
(const_int 1)
(match_operand:SI 1 "general_operand" "i")))]
"GET_CODE (operands[1]) == CONST_INT"
@@ -1656,7 +1656,7 @@
;; which can usually be done with move instructions.
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+do")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+do")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
(match_operand:SI 3 "general_operand" "d"))]
@@ -1686,7 +1686,7 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=&d")
- (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "do")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i")))]
"TARGET_68020 && TARGET_BITFIELD
@@ -1716,7 +1716,7 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d")
- (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "do")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i")))]
"TARGET_68020 && TARGET_BITFIELD
@@ -1744,26 +1744,42 @@
;; "o,d" constraint causes a nonoffsettable memref to match the "o"
;; so that its address is reloaded.
-(define_insn "extv"
- [(set (match_operand:SI 0 "general_operand" "=d,d")
- (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
- (match_operand:SI 2 "general_operand" "di,di")
- (match_operand:SI 3 "general_operand" "di,di")))]
+(define_expand "extv"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (sign_extract:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (sign_extract:SI (match_operand:QI 1 "memory_operand" "o")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
"TARGET_68020 && TARGET_BITFIELD"
"bfexts [%c3,%c2]%1,%0")
-(define_insn "extzv"
- [(set (match_operand:SI 0 "general_operand" "=d,d")
- (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
- (match_operand:SI 2 "general_operand" "di,di")
- (match_operand:SI 3 "general_operand" "di,di")))]
+(define_expand "extzv"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (zero_extract:SI (match_operand:QI 1 "memory_operand" "o")
+ (match_operand:SI 2 "general_operand" "di")
+ (match_operand:SI 3 "general_operand" "di")))]
"TARGET_68020 && TARGET_BITFIELD"
"bfextu [%c3,%c2]%1,%0")
(define_insn ""
- [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
- (match_operand:SI 1 "general_operand" "di,di")
- (match_operand:SI 2 "general_operand" "di,di"))
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
(xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
(match_operand:SI 3 "const_int_operand" "i,i")))]
"TARGET_68020 && TARGET_BITFIELD
@@ -1777,9 +1793,9 @@
}")
(define_insn ""
- [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
- (match_operand:SI 1 "general_operand" "di,di")
- (match_operand:SI 2 "general_operand" "di,di"))
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
(const_int 0))]
"TARGET_68020 && TARGET_BITFIELD"
"*
@@ -1789,9 +1805,9 @@
}")
(define_insn ""
- [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
- (match_operand:SI 1 "general_operand" "di,di")
- (match_operand:SI 2 "general_operand" "di,di"))
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
(const_int -1))]
"TARGET_68020 && TARGET_BITFIELD"
"*
@@ -1800,11 +1816,19 @@
return \"bfset [%c2,%c1]%0\";
}")
-(define_insn "insv"
- [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
- (match_operand:SI 1 "general_operand" "di,di")
- (match_operand:SI 2 "general_operand" "di,di"))
- (match_operand:SI 3 "general_operand" "d,d"))]
+(define_expand "insv"
+ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" ""))
+ (match_operand:SI 3 "general_operand" ""))]
+ "TARGET_68020 && TARGET_BITFIELD"
+ "")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o")
+ (match_operand:SI 1 "general_operand" "di")
+ (match_operand:SI 2 "general_operand" "di"))
+ (match_operand:SI 3 "general_operand" "d"))]
"TARGET_68020 && TARGET_BITFIELD"
"bfins %3,[%c2,%c1]%0")
@@ -1813,7 +1837,7 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d")
- (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "general_operand" "di")
(match_operand:SI 3 "general_operand" "di")))]
"TARGET_68020 && TARGET_BITFIELD"
@@ -1821,14 +1845,14 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d")
- (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "general_operand" "di")
(match_operand:SI 3 "general_operand" "di")))]
"TARGET_68020 && TARGET_BITFIELD"
"bfextu [%c3,%c2]%1,%0")
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
(match_operand:SI 1 "general_operand" "di")
(match_operand:SI 2 "general_operand" "di"))
(const_int 0))]
@@ -1840,7 +1864,7 @@
}")
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
(match_operand:SI 1 "general_operand" "di")
(match_operand:SI 2 "general_operand" "di"))
(const_int -1))]
@@ -1852,7 +1876,7 @@
}")
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d")
(match_operand:SI 1 "general_operand" "di")
(match_operand:SI 2 "general_operand" "di"))
(match_operand:SI 3 "general_operand" "d"))]
@@ -1893,7 +1917,7 @@
;;; now handle the register cases
(define_insn ""
[(set (cc0)
- (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
+ (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "general_operand" "di")))]
"TARGET_68020 && TARGET_BITFIELD"
@@ -2337,7 +2361,20 @@
;; dbra patterns that use REG_NOTES info generated by strength_reduce.
-(define_insn "decrement_and_branch_until_zero"
+(define_expand "decrement_and_branch_until_zero"
+ [(parallel [(set (pc)
+ (if_then_else
+ (ge (match_operand:SI 0 "general_operand" "")
+ (const_int 1))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))])]
+ ""
+ "")
+
+(define_insn ""
[(set (pc)
(if_then_else
(ge (match_operand:SI 0 "general_operand" "d,m,g")
diff --git a/gnu/usr.bin/gcc/config/gmicro/gmicro.c b/gnu/usr.bin/gcc/config/gmicro/gmicro.c
index 866c6c4a672..2911c9772c8 100644
--- a/gnu/usr.bin/gcc/config/gmicro/gmicro.c
+++ b/gnu/usr.bin/gcc/config/gmicro/gmicro.c
@@ -2,7 +2,7 @@
Ported by Masanobu Yuhara, Fujitsu Laboratories LTD.
(yuhara@flab.fujitsu.co.jp)
- Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -25,8 +25,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gnu/usr.bin/gcc/config/gmicro/gmicro.h b/gnu/usr.bin/gcc/config/gmicro/gmicro.h
index 7ed217c4e4f..29701f25fd7 100644
--- a/gnu/usr.bin/gcc/config/gmicro/gmicro.h
+++ b/gnu/usr.bin/gcc/config/gmicro/gmicro.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Gmicro (TRON) version.
- Copyright (C) 1987, 1988, 1989, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Masanobu Yuhara, Fujitsu Laboratories LTD.
(yuhara@flab.fujitsu.co.jp)
@@ -460,10 +460,10 @@ extern enum reg_class regno_reg_class[];
for the Gmicro. The option name may be changed in the future. */
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \
- ((TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ ((TARGET_RTD && (!(FUNDECL) || TREE_CODE (FUNDECL) != IDENTIFIER_NODE) \
&& (TYPE_ARG_TYPES (FUNTYPE) == 0 \
|| (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \
- = void_type_node))) \
+ == void_type_node))) \
? (SIZE) : 0)
/* Define how to find the value returned by a function.
@@ -516,7 +516,7 @@ extern enum reg_class regno_reg_class[];
On the Gmicro, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
@@ -1279,18 +1279,6 @@ extern enum reg_class regno_reg_class[];
#define BSS_SECTION_ASM_OP ".section bss,data,align=4"
-#define EXTRA_SECTIONS in_bss
-
-#define EXTRA_SECTION_FUNCTIONS \
-void \
-bss_section () \
-{ \
- if (in_section != in_bss) { \
- fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \
- in_section = in_bss; \
- } \
-}
-
/* Output at beginning of assembler file.
It is not appropriate for this to print a list of the options used,
since that's not the convention that we use. */
@@ -1365,11 +1353,9 @@ bss_section () \
}
-/* 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. */
diff --git a/gnu/usr.bin/gcc/config/gmicro/gmicro.md b/gnu/usr.bin/gcc/config/gmicro/gmicro.md
index 9a152fe52c0..0fc44875b6d 100644
--- a/gnu/usr.bin/gcc/config/gmicro/gmicro.md
+++ b/gnu/usr.bin/gcc/config/gmicro/gmicro.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU compiler, Fujitsu Gmicro Version
-;; Copyright (C) 1990, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1990, 1994, 1996 Free Software Foundation, Inc.
;; Contributed by M.Yuhara, Fujitsu Laboratories LTD.
;; This file is part of GNU CC.
@@ -221,21 +221,14 @@
;; Recognizers for btst instructions.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "rm")
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
(const_int 1)
(match_operand:SI 1 "general_operand" "rmi")))]
""
"btst %1.w,%0.b")
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "rm")
- (const_int 1)
- (match_operand:SI 1 "general_operand" "rmi")))]
- ""
- "btst %1.w,%0.h")
-
-(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "rm")
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(match_operand:SI 1 "general_operand" "rmi")))]
""
@@ -246,7 +239,7 @@
;; are automatically masked to 3 or 5 bits when the base is a register.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "r")
+ [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
(const_int 1)
(and:SI
(match_operand:SI 1 "general_operand" "rmi")
@@ -255,7 +248,7 @@
"btst %1.w,%0.b")
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "r")
+ [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
(const_int 1)
(and:SI
(match_operand:SI 1 "general_operand" "rmi")
@@ -268,7 +261,9 @@
(define_insn ""
- [(set (cc0) (and:SI (sign_extend:SI (sign_extend:HI (match_operand:QI 0 "nonimmediate_operand" "rm")))
+ [(set (cc0) (and:SI (sign_extend:SI
+ (sign_extend:HI
+ (match_operand:QI 0 "nonimmediate_operand" "rm")))
(match_operand:SI 1 "general_operand" "i")))]
"(GET_CODE (operands[1]) == CONST_INT
&& (unsigned) INTVAL (operands[1]) < 0x100
@@ -1990,7 +1985,7 @@
;; Should I add mode_dependent_address_p ????
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+rm")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm")
(match_operand:SI 1 "immediate_operand" "i")
(match_operand:SI 2 "immediate_operand" "i"))
(match_operand:SI 3 "general_operand" "rm"))]
@@ -2025,7 +2020,7 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=&r")
- (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "rm")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "rm")
(match_operand:SI 2 "immediate_operand" "i")
(match_operand:SI 3 "immediate_operand" "i")))]
"TARGET_BITFIELD
@@ -2096,7 +2091,7 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=r")
- (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "ro")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "ro")
(match_operand:SI 2 "immediate_operand" "i")
(match_operand:SI 3 "immediate_operand" "i")))]
"TARGET_BITFIELD
@@ -2173,18 +2168,34 @@
;; r.w m r.w/# rmi
;; %0 %1 %2 %3
-(define_insn "extv"
+(define_expand "extv"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (sign_extract:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))]
+ "TARGET_BITFIELD"
+ "")
+
+(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=r")
- (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "m")
+ (sign_extract:SI (match_operand:QI 1 "memory_operand" "m")
(match_operand:SI 2 "general_operand" "ri")
(match_operand:SI 3 "general_operand" "rmi")))]
"TARGET_BITFIELD"
"bfext %3,%2,%1,%0")
-(define_insn "extzv"
+(define_expand "extzv"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (zero_extract:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))]
+ "TARGET_BITFIELD"
+ "")
+
+(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=r")
- (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "m")
+ (zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
(match_operand:SI 2 "general_operand" "ri")
(match_operand:SI 3 "general_operand" "rmi")))]
"TARGET_BITFIELD"
@@ -2198,13 +2209,22 @@
;; 0 1 2 3
-(define_insn "insv"
- [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+m,m")
+(define_expand "insv"
+ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
+ (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" ""))
+ (match_operand:SI 3 "general_operand" ""))]
+ "TARGET_BITFIELD"
+ "")
+
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m,m")
(match_operand:SI 1 "general_operand" "r,i")
(match_operand:SI 2 "general_operand" "rmi,i"))
(match_operand:SI 3 "general_operand" "ri,ri"))]
"TARGET_BITFIELD"
"bfinsu %3,%2,%1,%0")
+
;;; bfins/bfinsu ????????
;; == == == == == == == == == == == == ==
@@ -2225,7 +2245,7 @@
;;
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=r")
- (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "r")
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "i")
(match_operand:SI 3 "immediate_operand" "i")))]
"TARGET_BITFIELD"
@@ -2242,7 +2262,7 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=r")
- (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "r")
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "i")
(match_operand:SI 3 "immediate_operand" "i")))]
"TARGET_BITFIELD"
diff --git a/gnu/usr.bin/gcc/config/gnu.h b/gnu/usr.bin/gcc/config/gnu.h
index 8ea3ead3d67..ce0fb867eb1 100644
--- a/gnu/usr.bin/gcc/config/gnu.h
+++ b/gnu/usr.bin/gcc/config/gnu.h
@@ -2,8 +2,8 @@
/* 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) \
+"-D" machine " -Acpu(" machine ") -Amachine(" machine ") \
+-Dunix -Asystem(unix) \
-DMACH -Asystem(mach) \
-D__GNU__ -Asystem(gnu)"
diff --git a/gnu/usr.bin/gcc/config/h8300/h8300.c b/gnu/usr.bin/gcc/config/h8300/h8300.c
index 8db3c3646e9..6ddd8cd3eeb 100644
--- a/gnu/usr.bin/gcc/config/h8300/h8300.c
+++ b/gnu/usr.bin/gcc/config/h8300/h8300.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Hitachi H8/300.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com),
Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
@@ -20,8 +20,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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -35,16 +35,30 @@ Boston, MA 02111-1307, USA. */
#include "recog.h"
#include "expr.h"
#include "tree.h"
+#include "obstack.h"
/* Forward declarations. */
void print_operand_address ();
char *index ();
+static int h8300_interrupt_function_p PROTO ((tree));
+static int h8300_monitor_function_p PROTO ((tree));
+static int h8300_os_task_function_p PROTO ((tree));
+
/* CPU_TYPE, says what cpu we're compiling for. */
int cpu_type;
-/* True if a #pragma interrupt has been seen for the current function. */
-int pragma_interrupt;
+/* True if the current function is an interrupt handler
+ (either via #pragma or an attribute specification). */
+int interrupt_handler;
+
+/* True if the current function is an OS Task
+ (via an attribute specification). */
+int os_task;
+
+/* True if the current function is a monitor
+ (via an attribute specification). */
+int monitor;
/* True if a #pragma saveall has been seen for the current function. */
int pragma_saveall;
@@ -63,7 +77,6 @@ static char *names_upper_extended[] =
char **h8_reg_names;
/* Various operations needed by the following, indexed by CPU_TYPE. */
-/* ??? The h8/300 assembler doesn't understand pop.w (yet). */
static char *h8_push_ops[2] =
{"push", "push.l"};
@@ -86,6 +99,7 @@ h8300_init_once ()
}
else
{
+ /* For this we treat the H8/300 and H8/S the same. */
cpu_type = (int) CPU_H8300H;
h8_reg_names = names_extended;
}
@@ -101,7 +115,7 @@ byte_reg (x, b)
{
static char *names_small[] =
{"r0l", "r0h", "r1l", "r1h", "r2l", "r2h", "r3l", "r3h",
- "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7lBAD", "r7hBAD"};
+ "r4l", "r4h", "r5l", "r5h", "r6l", "r6h", "r7l", "r7h"};
return names_small[REGNO (x) * 2 + b];
}
@@ -110,26 +124,39 @@ byte_reg (x, b)
#define WORD_REG_USED(regno) \
(regno < 7 && \
- (pragma_interrupt \
+ (interrupt_handler \
|| pragma_saveall \
|| (regno == FRAME_POINTER_REGNUM && regs_ever_live[regno]) \
|| (regs_ever_live[regno] & !call_used_regs[regno])))
/* Output assembly language to FILE for the operation OP with operand size
SIZE to adjust the stack pointer. */
-/* ??? FPED is currently unused. */
static void
-dosize (file, op, size, fped)
+dosize (file, op, size)
FILE *file;
char *op;
unsigned int size;
- int fped;
{
+ /* On the h8300h and h8300s, for sizes <= 8 bytes it is as good or
+ better to use adds/subs insns rather than add.l/sub.l
+ with an immediate value. */
+ if (size > 4 && size <= 8 && (TARGET_H8300H || TARGET_H8300S))
+ {
+ /* Crank the size down to <= 4 */
+ fprintf (file, "\t%ss\t#%d,sp\n", op, 4);
+ size -= 4;
+ }
+
switch (size)
{
case 4:
- /* ??? TARGET_H8300H can do this in one insn. */
+ if (TARGET_H8300H || TARGET_H8300S)
+ {
+ fprintf (file, "\t%ss\t#%d,sp\n", op, 4);
+ size = 0;
+ break;
+ }
case 3:
fprintf (file, "\t%ss\t#%d,sp\n", op, 2);
size -= 2;
@@ -143,7 +170,27 @@ dosize (file, op, size, fped)
break;
default:
if (TARGET_H8300)
- fprintf (file, "\tmov.w\t#%d,r3\n\t%s.w\tr3,sp\n", size, op);
+ {
+ if (current_function_needs_context
+ && strcmp (op, "sub") == 0)
+ {
+ /* Egad. We don't have a temporary to hold the
+ size of the frame in the prologue! Just inline
+ the bastard since this shouldn't happen often. */
+ while (size >= 2)
+ {
+ fprintf (file, "\tsubs\t#2,sp\n");
+ size -= 2;
+ }
+
+ if (size)
+ fprintf (file, "\tsubs\t#1,sp\n");
+
+ size = 0;
+ }
+ else
+ fprintf (file, "\tmov.w\t#%d,r3\n\t%s.w\tr3,sp\n", size, op);
+ }
else
fprintf (file, "\t%s\t#%d,sp\n", op, size);
size = 0;
@@ -153,9 +200,9 @@ dosize (file, op, size, fped)
/* Output assembly language code for the function prologue. */
static int push_order[FIRST_PSEUDO_REGISTER] =
-{6, 5, 4, 3, 2, 1, 0, -1, -1};
+{0, 1, 2, 3, 4, 5, 6, -1, -1, -1};
static int pop_order[FIRST_PSEUDO_REGISTER] =
-{0, 1, 2, 3, 4, 5, 6, -1, -1};
+{6, 5, 4, 3, 2, 1, 0, -1, -1, -1};
/* This is what the stack looks like after the prolog of
a function with a frame has been set up:
@@ -175,11 +222,6 @@ static int pop_order[FIRST_PSEUDO_REGISTER] =
<saved registers> <- sp
*/
-int current_function_anonymous_args;
-
-/* Extra arguments to pop, in words (IE: 2 bytes for 300, 4 for 300h */
-static int extra_pop;
-
void
function_prologue (file, size)
FILE *file;
@@ -188,44 +230,43 @@ function_prologue (file, size)
register int mask = 0;
int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;
int idx;
- extra_pop = 0;
- if (current_function_anonymous_args && TARGET_QUICKCALL)
+ /* Note a function with the interrupt attribute and set interrupt_handler
+ accordingly. */
+ if (h8300_interrupt_function_p (current_function_decl))
+ interrupt_handler = 1;
+
+ /* If the current function has the OS_Task attribute set, then
+ we have a naked prologue. */
+ if (h8300_os_task_function_p (current_function_decl))
{
- /* Push regs as if done by caller, and move around return address. */
+ fprintf (file, ";OS_Task prologue\n");
+ os_task = 1;
+ return;
+ }
- switch (current_function_args_info.nbytes / UNITS_PER_WORD)
+ if (h8300_monitor_function_p (current_function_decl))
+ {
+ /* My understanding of monitor functions is they act just
+ like interrupt functions, except the prologue must
+ mask interrupts. */
+ fprintf (file, ";monitor prologue\n");
+ interrupt_handler = 1;
+ monitor = 1;
+ if (TARGET_H8300)
{
- case 0:
- /* get ret addr */
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[1]);
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[0]);
- /* push it again */
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);
- extra_pop = 3;
- break;
- case 1:
- /* get ret addr */
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[1]);
- /* push it again */
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);
- extra_pop = 2;
- break;
- case 2:
- /* get ret addr */
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[2]);
- /* push it again */
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[3]);
- extra_pop = 1;
- break;
- default:
- fprintf (file, "; varargs\n");
- break;
+ fprintf (file, "\tsubs\t#2,sp\n");
+ fprintf (file, "\tpush\tr0\n");
+ fprintf (file, "\tstc\tccr,r0l\n");
+ fprintf (file, "\torc\t#128,ccr\n");
+ fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");
+ }
+ else
+ {
+ fprintf (file, "\tpush\ter0\n");
+ fprintf (file, "\tstc\tccr,r0l\n");
+ fprintf (file, "\torc\t#128,ccr\n");
+ fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");
}
}
@@ -237,28 +278,88 @@ function_prologue (file, size)
fprintf (file, "\t%s\t%s,%s\n", h8_mov_op,
h8_reg_names[STACK_POINTER_REGNUM],
h8_reg_names[FRAME_POINTER_REGNUM]);
+ }
- /* leave room for locals */
- dosize (file, "sub", fsize, 1);
-
- /* Push the rest of the registers */
- for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
- {
- int regno = push_order[idx];
+ /* leave room for locals */
+ dosize (file, "sub", fsize);
- if (regno >= 0 && WORD_REG_USED (regno) && regno != FRAME_POINTER_REGNUM)
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]);
- }
- }
- else
+ /* Push the rest of the registers */
+ for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
{
- dosize (file, "sub", fsize, 0);
- for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
- {
- int regno = push_order[idx];
+ int regno = push_order[idx];
- if (regno >= 0 && WORD_REG_USED (regno))
- fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]);
+ if (regno >= 0
+ && WORD_REG_USED (regno)
+ && (!frame_pointer_needed || regno != FRAME_POINTER_REGNUM))
+ {
+ if (TARGET_H8300S)
+ {
+ /* Try to push multiple registers. */
+ if (regno == 0 || regno == 4)
+ {
+ int second_regno = push_order[idx + 1];
+ int third_regno = push_order[idx + 2];
+ int fourth_regno = push_order[idx + 3];
+
+ if (fourth_regno >= 0
+ && WORD_REG_USED (fourth_regno)
+ && (!frame_pointer_needed
+ || fourth_regno != FRAME_POINTER_REGNUM)
+ && third_regno >= 0
+ && WORD_REG_USED (third_regno)
+ && (!frame_pointer_needed
+ || third_regno != FRAME_POINTER_REGNUM)
+ && second_regno >= 0
+ && WORD_REG_USED (second_regno)
+ && (!frame_pointer_needed
+ || second_regno != FRAME_POINTER_REGNUM))
+ {
+ fprintf (file, "\tstm.l %s-%s,@-sp\n",
+ h8_reg_names[regno],
+ h8_reg_names[fourth_regno]);
+ idx += 3;
+ continue;
+ }
+ }
+ if (regno == 0 || regno == 4)
+ {
+ int second_regno = push_order[idx + 1];
+ int third_regno = push_order[idx + 2];
+
+ if (third_regno >= 0
+ && WORD_REG_USED (third_regno)
+ && (!frame_pointer_needed
+ || third_regno != FRAME_POINTER_REGNUM)
+ && second_regno >= 0
+ && WORD_REG_USED (second_regno)
+ && (!frame_pointer_needed
+ || second_regno != FRAME_POINTER_REGNUM))
+ {
+ fprintf (file, "\tstm.l %s-%s,@-sp\n",
+ h8_reg_names[regno],
+ h8_reg_names[third_regno]);
+ idx += 2;
+ continue;
+ }
+ }
+ if (regno == 0 || regno == 2 || regno == 4 || regno == 6)
+ {
+ int second_regno = push_order[idx + 1];
+
+ if (second_regno >= 0
+ && WORD_REG_USED (second_regno)
+ && (!frame_pointer_needed
+ || second_regno != FRAME_POINTER_REGNUM))
+ {
+ fprintf (file, "\tstm.l %s-%s,@-sp\n",
+ h8_reg_names[regno],
+ h8_reg_names[second_regno]);
+ idx += 1;
+ continue;
+ }
+ }
+ }
+ fprintf (file, "\t%s\t%s\n", h8_push_op, h8_reg_names[regno]);
}
}
}
@@ -273,68 +374,131 @@ function_epilogue (file, size)
register int regno;
register int mask = 0;
int fsize = (size + STACK_BOUNDARY / 8 - 1) & -STACK_BOUNDARY / 8;
- int nregs;
- int offset;
int idx;
rtx insn = get_last_insn ();
+ if (os_task)
+ {
+ /* OS_Task epilogues are nearly naked -- they just have an
+ rts instruction. */
+ fprintf (file, ";OS_task epilogue\n");
+ fprintf (file, "\trts\n");
+ goto out;
+ }
+
+ /* monitor epilogues are the same as interrupt function epilogues.
+ Just make a note that we're in an monitor epilogue. */
+ if (monitor)
+ fprintf(file, ";monitor epilogue\n");
+
/* If the last insn was a BARRIER, we don't have to write any code. */
if (GET_CODE (insn) == NOTE)
insn = prev_nonnote_insn (insn);
if (insn && GET_CODE (insn) == BARRIER)
return;
- nregs = 0;
-
- if (frame_pointer_needed)
+ /* Pop the saved registers. */
+ for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
{
- /* Pop saved registers */
- for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
- {
- regno = pop_order[idx];
- if (regno >= 0 && regno != FRAME_POINTER_REGNUM && WORD_REG_USED (regno))
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);
- }
- /* deallocate locals */
- dosize (file, "add", fsize, 1);
- /* pop frame pointer */
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[FRAME_POINTER_REGNUM]);
- }
- else
- {
- /* pop saved registers */
- for (idx = 0; idx < FIRST_PSEUDO_REGISTER; idx++)
- {
- regno = pop_order[idx];
- if (regno >= 0 && WORD_REG_USED (regno))
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);
- }
- /* deallocate locals */
- dosize (file, "add", fsize, 0);
- }
+ int regno = pop_order[idx];
- if (extra_pop)
- {
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[3]);
- while (extra_pop)
+ if (regno >= 0
+ && WORD_REG_USED (regno)
+ && (!frame_pointer_needed || regno != FRAME_POINTER_REGNUM))
{
- fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[2]);
- extra_pop--;
+ if (TARGET_H8300S)
+ {
+ /* Try to pop multiple registers. */
+ if (regno == 7 || regno == 3)
+ {
+ int second_regno = pop_order[idx + 1];
+ int third_regno = pop_order[idx + 2];
+ int fourth_regno = pop_order[idx + 3];
+
+ if (fourth_regno >= 0
+ && WORD_REG_USED (fourth_regno)
+ && (!frame_pointer_needed
+ || fourth_regno != FRAME_POINTER_REGNUM)
+ && third_regno >= 0
+ && WORD_REG_USED (third_regno)
+ && (!frame_pointer_needed
+ || third_regno != FRAME_POINTER_REGNUM)
+ && second_regno >= 0
+ && WORD_REG_USED (second_regno)
+ && (!frame_pointer_needed
+ || second_regno != FRAME_POINTER_REGNUM))
+ {
+ fprintf (file, "\tldm.l @sp+,%s-%s\n",
+ h8_reg_names[fourth_regno],
+ h8_reg_names[regno]);
+ idx += 3;
+ continue;
+ }
+ }
+ if (regno == 6 || regno == 2)
+ {
+ int second_regno = pop_order[idx + 1];
+ int third_regno = pop_order[idx + 2];
+
+ if (third_regno >= 0
+ && WORD_REG_USED (third_regno)
+ && (!frame_pointer_needed
+ || third_regno != FRAME_POINTER_REGNUM)
+ && second_regno >= 0
+ && WORD_REG_USED (second_regno)
+ && (!frame_pointer_needed
+ || second_regno != FRAME_POINTER_REGNUM))
+ {
+ fprintf (file, "\tldm.l @sp+,%s-%s\n",
+ h8_reg_names[third_regno],
+ h8_reg_names[regno]);
+ idx += 2;
+ continue;
+ }
+ }
+ if (regno == 7 || regno == 5 || regno == 3 || regno == 1)
+ {
+ int second_regno = pop_order[idx + 1];
+
+ if (second_regno >= 0
+ && WORD_REG_USED (second_regno)
+ && (!frame_pointer_needed
+ || second_regno != FRAME_POINTER_REGNUM))
+ {
+ fprintf (file, "\tldm.l @sp+,%s-%s\n",
+ h8_reg_names[second_regno],
+ h8_reg_names[regno]);
+ idx += 1;
+ continue;
+ }
+ }
+ }
+ fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[regno]);
}
- fprintf (file, "\tjmp @%s\n", h8_reg_names[3]);
}
+
+ /* deallocate locals */
+ dosize (file, "add", fsize);
+
+ /* pop frame pointer if we had one. */
+ if (frame_pointer_needed)
+ fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[FRAME_POINTER_REGNUM]);
+
+ /* If this is a monitor function, there is one register still left on
+ the stack. */
+ if (monitor)
+ fprintf (file, "\t%s\t%s\n", h8_pop_op, h8_reg_names[0]);
+
+ if (interrupt_handler)
+ fprintf (file, "\trte\n");
else
- {
- if (pragma_interrupt)
- fprintf (file, "\trte\n");
- else
- fprintf (file, "\trts\n");
- }
+ fprintf (file, "\trts\n");
- pragma_interrupt = 0;
+out:
+ interrupt_handler = 0;
+ os_task = 0;
+ monitor = 0;
pragma_saveall = 0;
-
- current_function_anonymous_args = 0;
}
/* Output assembly code for the start of the file. */
@@ -349,6 +513,8 @@ asm_file_start (file)
fprintf (file, "; -O%d\n", optimize);
if (TARGET_H8300H)
fprintf (file, "\n\t.h8300h\n");
+ else if (TARGET_H8300S)
+ fprintf (file, "\n\t.h8300s\n");
else
fprintf (file, "\n\n");
output_file_directive (file, main_input_filename);
@@ -470,6 +636,139 @@ call_insn_operand (op, mode)
return 0;
}
+int
+adds_subs_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == CONST_INT)
+ {
+ if (INTVAL (op) <= 4 && INTVAL (op) >= 0)
+ return 1;
+ if (INTVAL (op) >= -4 && INTVAL (op) <= 0)
+ return 1;
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (op) != 7
+ && (INTVAL (op) <= 8 && INTVAL (op) >= 0))
+ return 1;
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (op) != -7
+ && (INTVAL (op) >= -8 && INTVAL (op) <= 0))
+ return 1;
+ }
+ return 0;
+}
+
+/* Return nonzero if op is an adds/subs operand which only requires
+ one insn to implement. It is assumed that OP is already an adds/subs
+ operand. */
+int
+one_insn_adds_subs_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ int val = INTVAL (op);
+
+ if (val == 1 || val == -1
+ || val == 2 || val == -2
+ || ((TARGET_H8300H || TARGET_H8300S)
+ && (val == 4 || val == -4)))
+ return 1;
+ return 0;
+}
+
+char *
+output_adds_subs (operands)
+ rtx *operands;
+{
+ int val = INTVAL (operands[2]);
+
+ /* First get the value into the range -4..4 inclusive.
+
+ The only way it can be out of this range is when TARGET_H8300H
+ or TARGET_H8300S is true, thus it is safe to use adds #4 and subs #4. */
+ if (val > 4)
+ {
+ output_asm_insn ("adds #4,%A0", operands);
+ val -= 4;
+ }
+
+ if (val < -4)
+ {
+ output_asm_insn ("subs #4,%A0", operands);
+ val += 4;
+ }
+
+ /* Handle case were val == 4 or val == -4 and we're compiling
+ for TARGET_H8300H or TARGET_H8300S. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && val == 4)
+ return "adds #4,%A0";
+
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && val == -4)
+ return "subs #4,%A0";
+
+ if (val > 2)
+ {
+ output_asm_insn ("adds #2,%A0", operands);
+ val -= 2;
+ }
+
+ if (val < -2)
+ {
+ output_asm_insn ("subs #2,%A0", operands);
+ val += 2;
+ }
+
+ /* val should be one or two now. */
+ if (val == 2)
+ return "adds #2,%A0";
+
+ if (val == -2)
+ return "subs #2,%A0";
+
+ /* val should be one now. */
+ if (val == 1)
+ return "adds #1,%A0";
+
+ if (val == -1)
+ return "subs #1,%A0";
+
+ /* If not optimizing, we might be asked to add 0. */
+ if (val == 0)
+ return "";
+
+ /* In theory, this can't happen. */
+ abort ();
+}
+
+/* Return true if OP is a valid call operand, and OP represents
+ an operand for a small call (4 bytes instead of 6 bytes). */
+
+int
+small_call_insn_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ if (GET_CODE (op) == MEM)
+ {
+ rtx inside = XEXP (op, 0);
+
+ /* Register indirect is a small call. */
+ if (register_operand (inside, Pmode))
+ return 1;
+
+ /* A call through the function vector is a small
+ call too. */
+ if (GET_CODE (inside) == SYMBOL_REF
+ && SYMBOL_REF_FLAG (inside))
+ return 1;
+ }
+ /* Otherwise it's a large call. */
+ return 0;
+}
+
/* Return true if OP is a valid jump operand. */
int
@@ -527,6 +826,15 @@ bit_operand (op, mode)
}
}
+int
+bit_memory_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (GET_CODE (op) == MEM
+ && EXTRA_CONSTRAINT (op, 'U'));
+}
+
/* Recognize valid operators for bit test. */
int
@@ -548,58 +856,23 @@ eq_operator (x, mode)
with this attribute may be safely used in an interrupt vector. */
int
-handle_pragma (file)
+handle_pragma (file, t)
FILE *file;
+ tree t;
{
- int c;
- char pbuf[20];
- int psize = 0;
-
- c = getc (file);
- while (c == ' ' || c == '\t')
- c = getc (file);
-
- if (c == '\n' || c == EOF)
- return c;
+ int retval = 0;
+ register char *pname;
- /* The only pragmas we understand are interrupt and saveall. */
- while (psize < sizeof (pbuf) - 1
- && isalpha (c))
- {
- pbuf[psize++] = c;
- c = getc (file);
- }
- pbuf[psize] = 0;
-
- if (strcmp (pbuf, "interrupt") == 0)
- pragma_interrupt = 1;
+ if (TREE_CODE (t) != IDENTIFIER_NODE)
+ return 0;
- if (strcmp (pbuf, "saveall") == 0)
- pragma_saveall = 1;
+ pname = IDENTIFIER_POINTER (t);
+ if (strcmp (pname, "interrupt") == 0)
+ interrupt_handler = retval = 1;
+ else if (strcmp (pname, "saveall") == 0)
+ pragma_saveall = retval = 1;
- /* ??? This is deprecated. Delete for gcc 2.8. */
- if (strcmp (pbuf, "section") == 0)
- {
- static int printed_p = 0;
- if (!printed_p)
- {
- warning ("#pragma section is deprecated, use section attributes");
- printed_p = 1;
- }
- while (c && !isalpha (c))
- c = getc (file);
- psize = 0;
- while (psize < sizeof (pbuf) - 1
- && isalpha (c) || isdigit (c) || c == '_')
- {
- pbuf[psize++] = c;
- c = getc (file);
- }
- pbuf[psize] = 0;
- named_section (NULL_TREE, pbuf);
- }
- ungetc (c, file);
- return c;
+ return retval;
}
/* If the next arg with MODE and TYPE is to be passed in a register, return
@@ -640,6 +913,10 @@ function_arg (cum, mode, type, named)
char *fname;
int regpass = 0;
+ /* Never pass unnamed arguments in registers. */
+ if (!named)
+ return 0;
+
/* Pass 3 regs worth of data in regs when user asked on the command line. */
if (TARGET_QUICKCALL)
regpass = 3;
@@ -717,6 +994,12 @@ const_costs (r, c)
case -1:
case -2:
return 0;
+ case 4:
+ case -4:
+ if (TARGET_H8300H || TARGET_H8300S)
+ return 0;
+ else
+ return 1;
default:
return 1;
}
@@ -744,6 +1027,8 @@ const_costs (r, c)
'L' fake label, changed after used twice.
'M' turn a 'M' constant into its negative mod 2.
'P' if operand is incing/decing sp, print .w, otherwise .b.
+ 'R' print operand as a byte:8 address if appropriate, else fall back to
+ 'X' handling.
'S' print operand as a long word
'T' print operand as a word
'U' if operand is incing/decing sp, print l, otherwise nothing.
@@ -751,6 +1036,7 @@ const_costs (r, c)
'W' find the clear bit, and print its number.
'X' print operand as a byte
'Y' print either l or h depending on whether last 'Z' operand < 8 or >= 8.
+ If this operand isn't a register, fall back to 'R' handling.
'Z' print int & 7.
'b' print the bit opcode
'c' print the ibit opcode
@@ -779,12 +1065,8 @@ cond_string (code)
switch (code)
{
case NE:
- if (cc_prev_status.flags & CC_DONE_CBIT)
- return "cs";
return "ne";
case EQ:
- if (cc_prev_status.flags & CC_DONE_CBIT)
- return "cc";
return "eq";
case GE:
return "ge";
@@ -822,8 +1104,7 @@ print_operand (file, x, code)
/* This is used for communication between the 'P' and 'U' codes. */
static char *last_p;
- /* This is used for communication between the 'Z' and 'Y' codes. */
- /* ??? 'V' and 'W' use it too. */
+ /* This is used for communication between codes V,W,Z and Y. */
static int bitint;
switch (code)
@@ -933,6 +1214,7 @@ print_operand (file, x, code)
abort ();
fprintf (file, "#%d", bitint & 7);
break;
+ case 'R':
case 'X':
if (GET_CODE (x) == REG)
fprintf (file, "%s", byte_reg (x, 0));
@@ -945,7 +1227,7 @@ print_operand (file, x, code)
if (GET_CODE (x) == REG)
fprintf (file, "%s%c", names_big[REGNO (x)], bitint > 7 ? 'h' : 'l');
else
- print_operand (file, x, 0);
+ print_operand (file, x, 'R');
bitint = -1;
break;
case 'Z':
@@ -1074,13 +1356,15 @@ print_operand (file, x, code)
if (GET_CODE (x) == CONST_INT)
fprintf (file, "#%d", INTVAL (x) & 0xff);
else
- fprintf (file, "%s", byte_reg (x, TARGET_H8300 ? 2 : 0));
+ fprintf (file, "%s",
+ byte_reg (x, TARGET_H8300 ? 2 : 0));
break;
case 'x':
if (GET_CODE (x) == CONST_INT)
fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
else
- fprintf (file, "%s", byte_reg (x, TARGET_H8300 ? 3 : 1));
+ fprintf (file, "%s",
+ byte_reg (x, TARGET_H8300 ? 3 : 1));
break;
case 'y':
if (GET_CODE (x) == CONST_INT)
@@ -1103,7 +1387,7 @@ print_operand (file, x, code)
switch (GET_MODE (x))
{
case QImode:
-#if 0 /* Is it asm ("mov.b %0,r2l", ...) */
+#if 0 /* Is it asm ("mov.b %0,r2l", ...) */
fprintf (file, "%s", byte_reg (x, 0));
#else /* ... or is it asm ("mov.b %0l,r2l", ...) */
fprintf (file, "%s", names_big[REGNO (x)]);
@@ -1124,6 +1408,16 @@ print_operand (file, x, code)
case MEM:
fprintf (file, "@");
output_address (XEXP (x, 0));
+
+ /* If this is an 'R' operand (reference into the 8-bit area),
+ then specify a symbolic address as "foo:8". */
+ if (code == 'R'
+ && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && SYMBOL_REF_FLAG (XEXP (x, 0)))
+ fprintf (file, ":8");
+ if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && TINY_DATA_NAME_P (XSTR (XEXP (x, 0), 0)))
+ fprintf (file, ":16");
break;
case CONST_INT:
@@ -1293,44 +1587,42 @@ notice_update_cc (body, insn)
switch (get_attr_cc (insn))
{
case CC_NONE:
- /* Insn does not affect the CC at all */
+ /* Insn does not affect CC at all. */
break;
case CC_NONE_0HIT:
- /* Insn does not change the CC, but the 0't operand has been changed. */
-
+ /* Insn does not change CC, but the 0'th operand has been changed. */
if (cc_status.value1 != 0
&& reg_overlap_mentioned_p (recog_operand[0], cc_status.value1))
cc_status.value1 = 0;
-
- if (cc_status.value2 != 0
- && reg_overlap_mentioned_p (recog_operand[0], cc_status.value2))
- cc_status.value2 = 0;
-
break;
- case CC_SET:
- /* Insn sets CC to recog_operand[0], but overflow is impossible. */
+ case CC_SET_ZN:
+ /* Insn sets the Z,N flags of CC to recog_operand[0].
+ The V flag is unusable. The C flag may or may not be known but
+ that's ok because alter_cond will change tests to use EQ/NE. */
CC_STATUS_INIT;
- cc_status.flags |= CC_NO_OVERFLOW;
+ cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
cc_status.value1 = recog_operand[0];
break;
- case CC_COMPARE:
- /* The insn is a compare instruction */
+ case CC_SET_ZNV:
+ /* Insn sets the Z,N,V flags of CC to recog_operand[0].
+ The C flag may or may not be known but that's ok because
+ alter_cond will change tests to use EQ/NE. */
CC_STATUS_INIT;
- cc_status.value1 = SET_SRC (body);
+ cc_status.flags |= CC_NO_CARRY;
+ cc_status.value1 = recog_operand[0];
break;
- case CC_CBIT:
+ case CC_COMPARE:
+ /* The insn is a compare instruction. */
CC_STATUS_INIT;
- cc_status.flags |= CC_DONE_CBIT;
- cc_status.value1 = 0;
+ cc_status.value1 = SET_SRC (body);
break;
- case CC_WHOOPS:
case CC_CLOBBER:
- /* Insn clobbers CC. */
+ /* Insn doesn't leave CC in a usable state. */
CC_STATUS_INIT;
break;
}
@@ -1353,83 +1645,171 @@ bit_operator (x, mode)
/* Shifts.
We devote a fair bit of code to getting efficient shifts since we can only
- shift one bit at a time. See the .md file for more comments.
+ shift one bit at a time on the H8/300 and H8/300H and only one or two
+ bits at a time on the H8/S.
+
+ The basic shift methods:
+
+ * loop shifts -- emit a loop using one (or two on H8/S) bit shifts;
+ this is the default. SHIFT_LOOP
+
+ * inlined shifts -- emit straight line code for the shift; this is
+ used when a straight line shift is about the same size or smaller
+ than a loop. We allow the inline version to be slightly longer in
+ some cases as it saves a register. SHIFT_INLINE
+
+ * rotate + and -- rotate the value the opposite direction, then
+ mask off the values we don't need. This is used when only a few
+ of the bits in the original value will survive in the shifted value.
+ Again, this is used when it's about the same size or smaller than
+ a loop. We allow this version to be slightly longer as it is usually
+ much faster than a loop. SHIFT_ROT_AND
+
+ * swap (+ shifts) -- often it's possible to swap bytes/words to
+ simulate a shift by 8/16. Once swapped a few inline shifts can be
+ added if the shift count is slightly more than 8 or 16. This is used
+ when it's about the same size or smaller than a loop. We allow this
+ version to be slightly longer as it is usually much faster than a loop.
+ SHIFT_SPECIAL
+
+ * There other oddballs. Not worth explaining. SHIFT_SPECIAL
+
Here are some thoughts on what the absolutely positively best code is.
"Best" here means some rational trade-off between code size and speed,
where speed is more preferred but not at the expense of generating 20 insns.
+ A trailing '*' after the shift count indicates the "best" mode isn't
+ implemented.
+
H8/300 QImode shifts
- 1-4 - do them inline
- 5-6 - ASHIFT | LSHIFTRT: rotate, mask off other bits
- ASHIFTRT: loop
- 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits
- ASHIFTRT: shll, subx (propagate carry bit to all bits)
+ 1-4 - do them inline
+ 5-6 - ASHIFT | LSHIFTRT: rotate, mask off other bits
+ ASHIFTRT: loop
+ 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits
+ ASHIFTRT: shll, subx (propagate carry bit to all bits)
H8/300 HImode shifts
- 1-4 - do them inline
- 5-6 - loop
- 7 - shift other way once, move byte into place, move carry bit into place
- 8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
- 9 - inline shift 1-4, move byte, set other byte
- 13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
- - ASHIFTRT: loop
- 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
- - ASHIFTRT: shll, subx, set other byte
+ 1-4 - do them inline
+ 5-6 - loop
+ 7 - shift 2nd half other way into carry.
+ copy 1st half into 2nd half
+ rotate 2nd half other way with carry
+ rotate 1st half other way (no carry)
+ mask off bits in 1st half (ASHIFT | LSHIFTRT).
+ sign extend 1st half (ASHIFTRT)
+ 8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
+ 9-12 - do shift by 8, inline remaining shifts
+ 13-14* - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
+ - ASHIFTRT: loop
+ 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
+ - ASHIFTRT: shll, subx, set other byte
H8/300 SImode shifts
- 1-2 - do them inline
- 3-6 - loop
- 7 - shift other way once, move bytes into place,
- move carry into place (possibly with sign extension)
- 8 - move bytes into place, zero or sign extend other
- 9-14 - loop
- 15 - shift other way once, move word into place, move carry into place
- 16 - move word, zero or sign extend other
- 17-23 - loop
- 24 - move bytes into place, zero or sign extend other
- 25-27 - loop
- 28-30 - ASHIFT | LSHIFTRT: rotate top byte, mask, move byte into place,
- zero others
- ASHIFTRT: loop
- 31 - ASHIFT | LSHIFTRT: rotate top byte, mask, byte byte into place,
- zero others
- ASHIFTRT: shll top byte, subx, copy to other bytes
-
- H8/300H QImode shifts
- - same as H8/300
+ 1-2 - do them inline
+ 3-6 - loop
+ 7* - shift other way once, move bytes into place,
+ move carry into place (possibly with sign extension)
+ 8 - move bytes into place, zero or sign extend other
+ 9-14 - loop
+ 15* - shift other way once, move word into place, move carry into place
+ 16 - move word, zero or sign extend other
+ 17-23 - loop
+ 24* - move bytes into place, zero or sign extend other
+ 25-27 - loop
+ 28-30* - ASHIFT | LSHIFTRT: rotate top byte, mask, move byte into place,
+ zero others
+ ASHIFTRT: loop
+ 31 - ASHIFT | LSHIFTRT: rotate top byte, mask, byte byte into place,
+ zero others
+ ASHIFTRT: shll top byte, subx, copy to other bytes
+
+ H8/300H QImode shifts (same as H8/300 QImode shifts)
+ 1-4 - do them inline
+ 5-6 - ASHIFT | LSHIFTRT: rotate, mask off other bits
+ ASHIFTRT: loop
+ 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits
+ ASHIFTRT: shll, subx (propagate carry bit to all bits)
+
H8/300H HImode shifts
- - same as H8/300
+ 1-4 - do them inline
+ 5-6 - loop
+ 7 - shift 2nd half other way into carry.
+ copy 1st half into 2nd half
+ rotate entire word other way using carry
+ mask off remaining bits (ASHIFT | LSHIFTRT)
+ sign extend remaining bits (ASHIFTRT)
+ 8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
+ 9-12 - do shift by 8, inline remaining shifts
+ 13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
+ - ASHIFTRT: loop
+ 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
+ - ASHIFTRT: shll, subx, set other byte
H8/300H SImode shifts
(These are complicated by the fact that we don't have byte level access to
the top word.)
A word is: bytes 3,2,1,0 (msb -> lsb), word 1,0 (msw -> lsw)
- 1-4 - do them inline
- 5-14 - loop
- 15 - shift other way once, move word into place, move carry into place
- (with sign extension for ASHIFTRT)
- 16 - move word into place, zero or sign extend other
- 17-23 - loop
- 24 - ASHIFT: move byte 0(msb) to byte 1, zero byte 0,
- move word 0 to word 1, zero word 0
- LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
- zero word 1, zero byte 1
- ASHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
- sign extend byte 0, sign extend word 0
- 25-27 - either loop, or
- do 24 bit shift, inline rest
- 28-30 - ASHIFT: rotate 4/3/2, mask
- LSHIFTRT: rotate 4/3/2, mask
- ASHIFTRT: loop
- 31 - shll, subx byte 0, sign extend byte 0, sign extend word 0
-
- Don't Panic!!!
-
- All of these haven't been implemented. I've just documented them and
- provided hooks so they can be.
-*/
+ 1-4 - do them inline
+ 5-14 - loop
+ 15* - shift other way once, move word into place, move carry into place
+ (with sign extension for ASHIFTRT)
+ 16 - move word into place, zero or sign extend other
+ 17-20 - do 16bit shift, then inline remaining shifts
+ 20-23 - loop
+ 24* - ASHIFT: move byte 0(msb) to byte 1, zero byte 0,
+ move word 0 to word 1, zero word 0
+ LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
+ zero word 1, zero byte 1
+ ASHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
+ sign extend byte 0, sign extend word 0
+ 25-27* - either loop, or
+ do 24 bit shift, inline rest
+ 28-30 - ASHIFT: rotate 4/3/2, mask
+ LSHIFTRT: rotate 4/3/2, mask
+ ASHIFTRT: loop
+ 31 - shll, subx byte 0, sign extend byte 0, sign extend word 0
+
+ H8/S QImode shifts
+ 1-6 - do them inline
+ 7 - ASHIFT | LSHIFTRT: rotate, mask off other bits
+ ASHIFTRT: shll, subx (propagate carry bit to all bits)
+
+ H8/S HImode shifts
+ 1-7 - do them inline
+ 8 - move byte, zero (ASHIFT | LSHIFTRT) or sign extend other (ASHIFTRT)
+ 9-12 - do shift by 8, inline remaining shifts
+ 13-14 - ASHIFT | LSHIFTRT: rotate 3/2, mask, move byte, set other byte to 0
+ - ASHIFTRT: loop
+ 15 - ASHIFT | LSHIFTRT: rotate 1, mask, move byte, set other byte to 0
+ - ASHIFTRT: shll, subx, set other byte
+
+ H8/S SImode shifts
+ (These are complicated by the fact that we don't have byte level access to
+ the top word.)
+ A word is: bytes 3,2,1,0 (msb -> lsb), word 1,0 (msw -> lsw)
+ 1-10 - do them inline
+ 11-14 - loop
+ 15* - shift other way once, move word into place, move carry into place
+ (with sign extension for ASHIFTRT)
+ 16 - move word into place, zero or sign extend other
+ 17-20 - do 16bit shift, then inline remaining shifts
+ 20-23 - loop
+ 24* - ASHIFT: move byte 0(msb) to byte 1, zero byte 0,
+ move word 0 to word 1, zero word 0
+ LSHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
+ zero word 1, zero byte 1
+ ASHIFTRT: move word 1 to word 0, move byte 1 to byte 0,
+ sign extend byte 0, sign extend word 0
+ 25-27* - either loop, or
+ do 24 bit shift, inline rest
+ 28-30 - ASHIFT: rotate 4/3/2, mask
+ LSHIFTRT: rotate 4/3/2, mask
+ ASHIFTRT: loop
+ 31 - shll, subx byte 0, sign extend byte 0, sign extend word 0
+
+ Panic!!! */
int
nshift_operator (x, mode)
@@ -1458,8 +1838,6 @@ expand_a_shift (mode, code, operands)
int code;
rtx operands[];
{
- extern int rtx_equal_function_value_matters;
-
emit_move_insn (operands[0], operands[1]);
/* need a loop to get all the bits we want - we generate the
@@ -1508,8 +1886,9 @@ enum shift_mode
QIshift, HIshift, SIshift
};
-/* For single bit shift insns, record assembler and whether the condition code
- is valid afterwards. */
+/* For single bit shift insns, record assembler and what bits of the
+ condition code are valid afterwards (represented as various CC_FOO
+ bits, 0 means CC isn't left in a usable state). */
struct shift_insn
{
@@ -1529,46 +1908,68 @@ static const struct shift_insn shift_one[2][3][3] =
{
/* SHIFT_ASHIFT */
{
- { "shal %X0", 1 },
- { "add.w %T0,%T0\t; shal.w", 1 },
- { "add.w %f0,%f0\t; shal.l\n\taddx %y0,%y0\n\taddx %z0,%z0\t; end shal.l", 0 }
+ { "shll\t%X0", CC_NO_CARRY },
+ { "add.w\t%T0,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
+ { "add.w\t%f0,%f0\n\taddx\t%y0,%y0\n\taddx\t%z0,%z0", 0 }
},
/* SHIFT_LSHIFTRT */
{
- { "shlr %X0", 1 },
- { "shlr %t0\t; shlr.w\n\trotxr %s0\t; end shlr.w", 0 },
- { "shlr %z0\t; shlr.l\n\trotxr %y0\n\trotxr %x0\n\trotxr %w0\t; end shlr.l", 0 }
+ { "shlr\t%X0", CC_NO_CARRY },
+ { "shlr\t%t0\n\trotxr\t%s0", 0 },
+ { "shlr\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 }
},
/* SHIFT_ASHIFTRT */
{
- { "shar %X0", 1 },
- { "shar %t0\t; shar.w\n\trotxr %s0\t; end shar.w", 0 },
- { "shar %z0\t; shar.l\n\trotxr %y0\n\trotxr %x0\n\trotxr %w0\t; end shar.l", 0 }
+ { "shar\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
+ { "shar\t%t0\n\trotxr\t%s0", 0 },
+ { "shar\t%z0\n\trotxr\t%y0\n\trotxr\t%x0\n\trotxr\t%w0", 0 }
}
},
/* H8/300H */
{
/* SHIFT_ASHIFT */
{
- { "shal.b %X0", 1 },
- { "shal.w %T0", 1 },
- { "shal.l %S0", 1 }
+ { "shll.b\t%X0", CC_NO_CARRY },
+ { "shll.w\t%T0", CC_NO_CARRY },
+ { "shll.l\t%S0", CC_NO_CARRY }
},
/* SHIFT_LSHIFTRT */
{
- { "shlr.b %X0", 1 },
- { "shlr.w %T0", 1 },
- { "shlr.l %S0", 1 }
+ { "shlr.b\t%X0", CC_NO_CARRY },
+ { "shlr.w\t%T0", CC_NO_CARRY },
+ { "shlr.l\t%S0", CC_NO_CARRY }
},
/* SHIFT_ASHIFTRT */
{
- { "shar.b %X0", 1 },
- { "shar.w %T0", 1 },
- { "shar.l %S0", 1 }
+ { "shar.b\t%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
+ { "shar.w\t%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
+ { "shar.l\t%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }
}
}
};
+static const struct shift_insn shift_two[3][3] =
+{
+/* SHIFT_ASHIFT */
+ {
+ { "shll.b\t#2,%X0", CC_NO_CARRY },
+ { "shll.w\t#2,%T0", CC_NO_CARRY },
+ { "shll.l\t#2,%S0", CC_NO_CARRY }
+ },
+/* SHIFT_LSHIFTRT */
+ {
+ { "shlr.b\t#2,%X0", CC_NO_CARRY },
+ { "shlr.w\t#2,%T0", CC_NO_CARRY },
+ { "shlr.l\t#2,%S0", CC_NO_CARRY }
+ },
+/* SHIFT_ASHIFTRT */
+ {
+ { "shar.b\t#2,%X0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
+ { "shar.w\t#2,%T0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },
+ { "shar.l\t#2,%S0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY }
+ }
+};
+
/* Rotates are organized by which shift they'll be used in implementing.
There's no need to record whether the cc is valid afterwards because
it is the AND insn that will decide this. */
@@ -1579,20 +1980,20 @@ static const char *const rotate_one[2][3][3] =
{
/* SHIFT_ASHIFT */
{
- "rotr %X0",
- "shlr %t0\t; rotr.w\n\trotxr %s0\n\tbst #7,%t0\t; end rotr.w",
+ "rotr\t%X0",
+ "shlr\t%t0\n\trotxr\t%s0\n\tbst\t#7,%t0",
0
},
/* SHIFT_LSHIFTRT */
{
- "rotl %X0",
- "shll %s0\t; rotl.w\n\trotxl %t0\n\tbst #0,%s0\t; end rotl.w",
+ "rotl\t%X0",
+ "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
0
},
/* SHIFT_ASHIFTRT */
{
- "rotl %X0",
- "shll %s0\t; rotl.w\n\trotxl %t0\n\tbst #0,%s0\t; end rotl.w",
+ "rotl\t%X0",
+ "shll\t%s0\n\trotxl\t%t0\n\tbst\t#0,%s0",
0
}
},
@@ -1600,25 +2001,47 @@ static const char *const rotate_one[2][3][3] =
{
/* SHIFT_ASHIFT */
{
- "rotr.b %X0",
- "rotr.w %T0",
- "rotr.l %S0"
+ "rotr.b\t%X0",
+ "rotr.w\t%T0",
+ "rotr.l\t%S0"
},
/* SHIFT_LSHIFTRT */
{
- "rotl.b %X0",
- "rotl.w %T0",
- "rotl.l %S0"
+ "rotl.b\t%X0",
+ "rotl.w\t%T0",
+ "rotl.l\t%S0"
},
/* SHIFT_ASHIFTRT */
{
- "rotl.b %X0",
- "rotl.w %T0",
- "rotl.l %S0"
+ "rotl.b\t%X0",
+ "rotl.w\t%T0",
+ "rotl.l\t%S0"
}
}
};
+static const char *const rotate_two[3][3] =
+{
+/* SHIFT_ASHIFT */
+ {
+ "rotr.b\t#2,%X0",
+ "rotr.w\t#2,%T0",
+ "rotr.l\t#2,%S0"
+ },
+/* SHIFT_LSHIFTRT */
+ {
+ "rotl.b\t#2,%X0",
+ "rotl.w\t#2,%T0",
+ "rotl.l\t#2,%S0"
+ },
+/* SHIFT_ASHIFTRT */
+ {
+ "rotl.b\t#2,%X0",
+ "rotl.w\t#2,%T0",
+ "rotl.l\t#2,%S0"
+ }
+};
+
/* Given CPU, MODE, SHIFT_TYPE, and shift count COUNT, determine the best
algorithm for doing the shift. The assembler code is stored in ASSEMBLER.
We don't achieve maximum efficiency in all cases, but the hooks are here
@@ -1633,12 +2056,14 @@ static const char *const rotate_one[2][3][3] =
1,2,3,4 will be inlined (1,2 for SI). */
static enum shift_alg
-get_shift_alg (cpu, shift_type, mode, count, assembler_p, cc_valid_p)
+get_shift_alg (cpu, shift_type, mode, count, assembler_p,
+ assembler2_p, cc_valid_p)
enum attr_cpu cpu;
enum shift_type shift_type;
enum machine_mode mode;
int count;
const char **assembler_p;
+ const char **assembler2_p;
int *cc_valid_p;
{
/* The default is to loop. */
@@ -1669,6 +2094,10 @@ get_shift_alg (cpu, shift_type, mode, count, assembler_p, cc_valid_p)
/* Assume either SHIFT_LOOP or SHIFT_INLINE.
It is up to the caller to know that looping clobbers cc. */
*assembler_p = shift_one[cpu][shift_type][shift_mode].assembler;
+ if (TARGET_H8300S)
+ *assembler2_p = shift_two[shift_type][shift_mode].assembler;
+ else
+ *assembler2_p = NULL;
*cc_valid_p = shift_one[cpu][shift_type][shift_mode].cc_valid;
/* Now look for cases we want to optimize. */
@@ -1678,126 +2107,362 @@ get_shift_alg (cpu, shift_type, mode, count, assembler_p, cc_valid_p)
case QIshift:
if (count <= 4)
return SHIFT_INLINE;
- else if (count <= 6)
+ else
{
+ /* Shift by 5/6 are only 3 insns on the H8/S, so it's just as
+ fast as SHIFT_ROT_AND, plus CC is valid. */
+ if (TARGET_H8300S && count <= 6)
+ return SHIFT_INLINE;
+
+ /* For ASHIFTRT by 7 bits, the sign bit is simply replicated
+ through the entire value. */
+ if (shift_type == SHIFT_ASHIFTRT && count == 7)
+ {
+ *assembler_p = "shll\t%X0\n\tsubx\t%X0,%X0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+
+ /* Other ASHIFTRTs are too much of a pain. */
if (shift_type == SHIFT_ASHIFTRT)
+ return SHIFT_LOOP;
+
+ /* Other shifts by 5, 6, or 7 bits use SHIFT_ROT_AND. */
+ *assembler_p = rotate_one[cpu][shift_type][shift_mode];
+ if (TARGET_H8300S)
+ *assembler2_p = rotate_two[shift_type][shift_mode];
+ *cc_valid_p = 0;
+ return SHIFT_ROT_AND;
+ }
+
+ case HIshift:
+ if (count <= 4)
+ return SHIFT_INLINE;
+ else if (TARGET_H8300S && count <= 7)
+ return SHIFT_INLINE;
+ else if (count == 7)
+ {
+ if (shift_type == SHIFT_ASHIFT && TARGET_H8300)
{
- return SHIFT_LOOP;
+ *assembler_p = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.b\t%t0\n\trotr.b\t%s0\n\tand.b\t#0x80,%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
}
- else
+
+ if (shift_type == SHIFT_ASHIFT && TARGET_H8300H)
{
- *assembler_p = rotate_one[cpu][shift_type][shift_mode];
+ *assembler_p = "shar.b\t%t0\n\tmov.b\t%s0,%t0\n\trotxr.w\t%T0\n\tand.b\t#0x80,%s0";
*cc_valid_p = 0;
- return SHIFT_ROT_AND;
+ return SHIFT_SPECIAL;
+ }
+
+ if (shift_type == SHIFT_LSHIFTRT && TARGET_H8300)
+ {
+ *assembler_p = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\trotl.b\t%t0\n\tand.b\t#0x01,%t0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+
+ if (shift_type == SHIFT_LSHIFTRT && TARGET_H8300H)
+ {
+ *assembler_p = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.w\t%T0\n\tand.b\t#0x01,%t0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+
+ if (shift_type == SHIFT_ASHIFTRT)
+ {
+ *assembler_p = "shal.b\t%s0\n\tmov.b\t%t0,%s0\n\trotxl.b\t%s0\n\tsubx\t%t0,%t0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
}
}
- else if (count == 7)
+ else if (count == 8)
{
- if (shift_type == SHIFT_ASHIFTRT)
+ switch (shift_type)
{
- *assembler_p = "shll %X0\t; shar.b(7)\n\tsubx %X0,%X0\t; end shar.b(7)";
+ case SHIFT_ASHIFT:
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ if (TARGET_H8300)
+ *assembler_p = "mov.b\t%t0,%s0\n\tshll\t%t0\n\tsubx\t%t0,%t0\t";
+ else
+ *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
}
- else
+ }
+ else if (count == 9)
+ {
+ switch (shift_type)
{
- *assembler_p = rotate_one[cpu][shift_type][shift_mode];
+ case SHIFT_ASHIFT:
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0";
*cc_valid_p = 0;
- return SHIFT_ROT_AND;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ if (TARGET_H8300)
+ *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0";
+ else
+ *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
}
}
- break;
- case HIshift:
- if (count <= 4)
- return SHIFT_INLINE;
- else if (count == 8)
+ else if (count == 10)
{
switch (shift_type)
{
case SHIFT_ASHIFT:
- *assembler_p = "mov.b %s0,%t0\t; shal.w(8)\n\tsub.b %s0,%s0\t; end shal.w(8)";
+ if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t#2,%t0\n\t";
+ else
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0\n\tshal.b\t%t0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
case SHIFT_LSHIFTRT:
- *assembler_p = "mov.b %t0,%s0\t; shlr.w(8)\n\tsub.b %t0,%t0\t; end shlr.w(8)";
+ if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t#2,%s0";
+ else
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0\n\tshlr.b\t%s0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
case SHIFT_ASHIFTRT:
- if (cpu == CPU_H8300)
- *assembler_p = "mov.b %t0,%s0\t; shar.w(8)\n\tshll %t0\n\tsubx %t0,%t0\t; end shar.w(8)";
+ if (TARGET_H8300)
+ *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0\n\tshar.b\t%s0";
+ else if (TARGET_H8300H)
+ *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t%s0\n\tshar.b\t%s0";
+ else if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t#2,%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+ }
+ else if (count == 11)
+ {
+ switch (shift_type)
+ {
+ case SHIFT_ASHIFT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t#2,%t0\n\tshal.b\t%t0";
else
- *assembler_p = "mov.b %t0,%s0\t; shar.w(8)\n\texts.w %T0\t; end shar.w(8)";
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0\n\tshal.b\t%t0\n\tshal.b\t%t0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t#2,%s0\n\tshlr.b\t%s0";
+ else
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0\n\tshlr.b\t%s0\n\tshlr.b\t%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ if (TARGET_H8300)
+ *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0";
+ else if (TARGET_H8300H)
+ *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0";
+ else if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%t0,%s0\n\texts.w\t%T0\n\tshar.b\t#2,%s0\n\tshar.b\t%s0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
}
- abort ();
}
- else if (count == 15)
+ else if (count == 12)
{
- if (shift_type == SHIFT_ASHIFTRT)
+ switch (shift_type)
+ {
+ case SHIFT_ASHIFT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t#2,%t0\n\tshal.b\t#2,%t0";
+ else
+ *assembler_p = "mov.b\t%s0,%t0\n\tsub.b\t%s0,%s0\n\tshal.b\t%t0\n\tshal.b\t%t0\n\tshal.b\t%t0\n\tshal.b\t%t0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t#2,%s0\n\tshlr.b\t#2,%s0";
+ else
+ *assembler_p = "mov.b\t%t0,%s0\n\tsub.b\t%t0,%t0\n\tshlr.b\t%s0\n\tshlr.b\t%s0\n\tshlr.b\t%s0\n\tshlr.b\t%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ if (TARGET_H8300)
+ *assembler_p = "mov.b\t%t0,%s0\n\tbld\t#7,%s0\n\tsubx\t%t0,%t0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0";
+ else if (TARGET_H8300H)
+ *assembler_p = "mov.b\t%t0,%s0\n\textw.w\t%T0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0\n\tshar.b\t%s0";
+ else if (TARGET_H8300S)
+ *assembler_p = "mov.b\t%t0,%s0\n\textw.w\t%T0\n\tshar.b\t#2,%s0\n\tshar.b\t#2,%s0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+ }
+ else if (!TARGET_H8300 && (count == 13 || count == 14)
+ || count == 15)
+ {
+ if (count == 15 && shift_type == SHIFT_ASHIFTRT)
{
- *assembler_p = "shll %t0,%t0\t; shar.w(15)\n\tsubx %t0,%t0\n\tmov.b %t0,%s0\t; end shar.w(15)";
+ *assembler_p = "shll\t%t0,%t0\n\tsubx\t%t0,%t0\n\tmov.b\t%t0,%s0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
}
- else
+ else if (shift_type != SHIFT_ASHIFTRT)
{
*assembler_p = rotate_one[cpu][shift_type][shift_mode];
+ if (TARGET_H8300S)
+ *assembler2_p = rotate_two[shift_type][shift_mode];
+ else
+ *assembler2_p = NULL;
*cc_valid_p = 0;
return SHIFT_ROT_AND;
}
}
break;
+
case SIshift:
- if (count <= (cpu == CPU_H8300 ? 2 : 4))
+ if (count <= (TARGET_H8300 ? 2 : 4))
return SHIFT_INLINE;
- else if (count == 8)
+ else if (TARGET_H8300S && count <= 10)
+ return SHIFT_INLINE;
+ else if (count == 8 && TARGET_H8300)
{
- if (cpu == CPU_H8300)
+ switch (shift_type)
{
- switch (shift_type)
- {
- case SHIFT_ASHIFT:
- *assembler_p = "mov.b %y0,%z0\t; shal.l(8)\n\tmov.b %x0,%y0\n\tmov.b %w0,%x0\n\tsub.b %w0,%w0\t; end shal.l(8)";
- *cc_valid_p = 0;
- return SHIFT_SPECIAL;
- case SHIFT_LSHIFTRT:
- *assembler_p = "mov.b %x0,%w0\t; shlr.l(8)\n\tmov.b %y0,%x0\n\tmov.b %z0,%y0\n\tsub.b %z0,%z0\t; end shlr.l(8)";
- *cc_valid_p = 0;
- return SHIFT_SPECIAL;
- case SHIFT_ASHIFTRT:
- *assembler_p = "mov.b %x0,%w0\t; shar.l(8)\n\tmov.b %y0,%x0\n\tmov.b %z0,%y0\n\tshll %z0\n\tsubx %z0,%z0; end shar.l(8)";
- *cc_valid_p = 0;
- return SHIFT_SPECIAL;
- }
+ case SHIFT_ASHIFT:
+ *assembler_p = "mov.b\t%y0,%z0n\tmov.b\t%x0,%y0\n\tmov.b\t%w0,%x0\n\tsub.b\t%w0,%w0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ *assembler_p = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tsub.b\t%z0,%z0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ *assembler_p = "mov.b\t%x0,%w0\n\tmov.b\t%y0,%x0\n\tmov.b\t%z0,%y0\n\tshll\t%z0\n\tsubx\t%z0,%z0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
}
- else /* CPU_H8300H */
- /* We don't have byte level access to the high word so this isn't
- easy to do. For now, just loop. */
- ;
}
else if (count == 16)
{
switch (shift_type)
{
case SHIFT_ASHIFT:
- *assembler_p = "mov.w %f0,%e0\t; shal.l(16)\n\tsub.w %f0,%f0\t; end shal.l(16)";
+ *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ if (TARGET_H8300)
+ *assembler_p = "mov.w\t%e0,%f0\n\tshll\t%z0\n\tsubx\t%z0,%z0\n\tmov.b\t%z0,%y0";
+ else
+ *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+ }
+ else if (count == 17 && !TARGET_H8300)
+ {
+ switch (shift_type)
+ {
+ case SHIFT_ASHIFT:
+ *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+ }
+ else if (count == 18 && !TARGET_H8300)
+ {
+ switch (shift_type)
+ {
+ case SHIFT_ASHIFT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t#2,%S0";
+ else
+ *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t%S0\n\tshll.l\t%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t#2,%S0";
+ else
+ *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t%S0\n\tshlr.l\t%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t#2,%S0";
+ else
+ *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t%S0\n\tshar.l\t%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+ }
+ else if (count == 19 && !TARGET_H8300)
+ {
+ switch (shift_type)
+ {
+ case SHIFT_ASHIFT:
+ if (TARGET_H8300S)
+ *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t#2,%S0\n\tshll.l\t%S0";
+ else
+ *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t%S0\n\tshll.l\t%S0\n\tshll.l\t%S0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
case SHIFT_LSHIFTRT:
- *assembler_p = "mov.w %e0,%f0\t; shlr.l(16)\n\tsub.w %e0,%e0\t; end shlr.l(16)";
+ if (TARGET_H8300S)
+ *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t#2,%S0\n\tshlr.l\t%S0";
+ else
+ *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t%S0\n\tshlr.l\t%S0\n\tshlr.l\t%S0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
case SHIFT_ASHIFTRT:
- if (cpu == CPU_H8300)
- *assembler_p = "mov.w %e0,%f0\t; shar.l(16)\n\tshll %z0\n\tsubx %z0,%z0\n\tmov.b %z0,%y0\t; end shar.l(16)";
+ if (TARGET_H8300S)
+ *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t#2,%S0\n\tshar.l\t%S0";
else
- *assembler_p = "mov.w %e0,%f0\t; shar.l(16)\n\texts.l %S0\t; end shar.l(16)";
+ *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t%S0\n\tshar.l\t%S0\n\tshar.l\t%S0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
}
}
- else if (count >= 28 && count <= 30)
+ else if (count == 20 && TARGET_H8300S)
+ {
+ switch (shift_type)
+ {
+ case SHIFT_ASHIFT:
+ *assembler_p = "mov.w\t%f0,%e0\n\tsub.w\t%f0,%f0\n\tshll.l\t#2,%S0\n\tshll.l\t#2,%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_LSHIFTRT:
+ *assembler_p = "mov.w\t%e0,%f0\n\tsub.w\t%e0,%e0\n\tshlr.l\t#2,%S0\n\tshlr.l\t#2,%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ case SHIFT_ASHIFTRT:
+ *assembler_p = "mov.w\t%e0,%f0\n\texts.l\t%S0\n\tshar.l\t#2,%S0\n\tshar.l\t#2,%S0";
+ *cc_valid_p = 0;
+ return SHIFT_SPECIAL;
+ }
+ }
+ else if (count >= 28 && count <= 30 && !TARGET_H8300)
{
if (shift_type == SHIFT_ASHIFTRT)
{
@@ -1805,47 +2470,51 @@ get_shift_alg (cpu, shift_type, mode, count, assembler_p, cc_valid_p)
}
else
{
- if (cpu == CPU_H8300)
- return SHIFT_LOOP;
+ *assembler_p = rotate_one[cpu][shift_type][shift_mode];
+ if (TARGET_H8300S)
+ *assembler2_p = rotate_two[shift_type][shift_mode];
else
- {
- *assembler_p = rotate_one[cpu][shift_type][shift_mode];
- *cc_valid_p = 0;
- return SHIFT_ROT_AND;
- }
+ *assembler2_p = NULL;
+ *cc_valid_p = 0;
+ return SHIFT_ROT_AND;
}
}
else if (count == 31)
{
if (shift_type == SHIFT_ASHIFTRT)
{
- if (cpu == CPU_H8300)
- *assembler_p = "shll %z0\t; shar.l(31)\n\tsubx %w0,%w0\n\tmov.b %w0,%x0\n\tmov.w %f0,%e0\t; end shar.l(31)";
+ if (TARGET_H8300)
+ *assembler_p = "shll\t%z0\n\tsubx %w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0";
else
- *assembler_p = "shll %e0\t; shar.l(31)\n\tsubx %w0,%w0\n\tmov.b %w0,%x0\n\tmov.w %f0,%e0\t; end shar.l(31)";
+ *assembler_p = "shll\t%e0\n\tsubx\t%w0,%w0\n\tmov.b\t%w0,%x0\n\tmov.w\t%f0,%e0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
}
else
{
- if (cpu == CPU_H8300)
+ if (TARGET_H8300)
{
if (shift_type == SHIFT_ASHIFT)
- *assembler_p = "sub.w %e0,%e0\t; shal.l(31)\n\tshlr %w0\n\tmov.w %e0,%f0\n\trotxr %z0\t; end shal.l(31)";
+ *assembler_p = "sub.w\t%e0,%e0\n\tshlr\t%w0\n\tmov.w\t%e0,%f0\n\trotxr\t%z0";
else
- *assembler_p = "sub.w %f0,%f0\t; shlr.l(31)\n\tshll %z0\n\tmov.w %f0,%e0\n\trotxl %w0\t; end shlr.l(31)";
+ *assembler_p = "sub.w\t%f0,%f0\n\tshll\t%z0\n\tmov.w\t%f0,%e0\n\trotxl\t%w0";
*cc_valid_p = 0;
return SHIFT_SPECIAL;
}
else
{
*assembler_p = rotate_one[cpu][shift_type][shift_mode];
+ if (TARGET_H8300S)
+ *assembler2_p = rotate_two[shift_type][shift_mode];
+ else
+ *assembler2_p = NULL;
*cc_valid_p = 0;
return SHIFT_ROT_AND;
}
}
}
break;
+
default:
abort ();
}
@@ -1862,6 +2531,7 @@ emit_a_shift (insn, operands)
{
static int loopend_lab;
char *assembler;
+ char *assembler2;
int cc_valid;
rtx inside = PATTERN (insn);
rtx shift = operands[3];
@@ -1909,7 +2579,8 @@ emit_a_shift (insn, operands)
fprintf (asm_out_file, "\tble .Lle%d\n", loopend_lab);
/* Get the assembler code to do one shift. */
- get_shift_alg (cpu_type, shift_type, mode, 1, &assembler, &cc_valid);
+ get_shift_alg (cpu_type, shift_type, mode, 1, &assembler,
+ &assembler2, &cc_valid);
}
else
{
@@ -1925,16 +2596,34 @@ emit_a_shift (insn, operands)
else if (n > GET_MODE_BITSIZE (mode))
n = GET_MODE_BITSIZE (mode);
- alg = get_shift_alg (cpu_type, shift_type, mode, n, &assembler, &cc_valid);
+ alg = get_shift_alg (cpu_type, shift_type, mode, n, &assembler,
+ &assembler2, &cc_valid);
switch (alg)
{
case SHIFT_INLINE:
- while (--n >= 0)
- output_asm_insn (assembler, operands);
+ /* Emit two bit shifts first. */
+ while (n > 1 && assembler2 != NULL)
+ {
+ output_asm_insn (assembler2, operands);
+ n -= 2;
+ }
+
+ /* Now emit one bit shifts for any residual. */
+ while (n > 0)
+ {
+ output_asm_insn (assembler, operands);
+ n -= 1;
+ }
+
+ /* Keep track of CC. */
if (cc_valid)
- cc_status.value1 = operands[0];
+ {
+ cc_status.value1 = operands[0];
+ cc_status.flags |= cc_valid;
+ }
return "";
+
case SHIFT_ROT_AND:
{
int m = GET_MODE_BITSIZE (mode) - n;
@@ -1946,19 +2635,34 @@ emit_a_shift (insn, operands)
be generated, but let's watch for 'em. */
if (assembler == 0)
abort ();
- while (--m >= 0)
- output_asm_insn (assembler, operands);
+
+ /* Emit two bit rotates first. */
+ while (m > 1 && assembler2 != NULL)
+ {
+ output_asm_insn (assembler2, operands);
+ m -= 2;
+ }
+
+ /* Now single bit rotates for any residual. */
+ while (m > 0)
+ {
+ output_asm_insn (assembler, operands);
+ m -= 1;
+ }
+
+ /* Now mask off the high bits. */
if (TARGET_H8300)
{
switch (mode)
{
case QImode:
- sprintf (insn_buf, "and #%d,%%X0\t; end shift %d via rotate+and",
+ sprintf (insn_buf, "and #%d,%%X0",
mask, n);
cc_status.value1 = operands[0];
+ cc_status.flags |= CC_NO_CARRY;
break;
case HImode:
- sprintf (insn_buf, "and #%d,%%s0\n\tand #%d,%%t0\t; end shift %d via rotate+and",
+ sprintf (insn_buf, "and #%d,%%s0\n\tand #%d,%%t0",
mask & 255, mask >> 8, n);
break;
case SImode:
@@ -1971,6 +2675,7 @@ emit_a_shift (insn, operands)
"bwl"[shift_mode], mask,
mode == QImode ? 'X' : mode == HImode ? 'T' : 'S');
cc_status.value1 = operands[0];
+ cc_status.flags |= CC_NO_CARRY;
}
output_asm_insn (insn_buf, operands);
return "";
@@ -1980,8 +2685,30 @@ emit_a_shift (insn, operands)
return "";
}
- /* Need a loop, move limit to tmp reg */
- fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n, names_big[REGNO (operands[4])]);
+ /* A loop to shift by a "large" constant value.
+ If we have shift-by-2 insns, use them. */
+ if (assembler2 != NULL)
+ {
+ fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n / 2,
+ names_big[REGNO (operands[4])]);
+ fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
+ output_asm_insn (assembler2, operands);
+ output_asm_insn ("add #0xff,%X4", operands);
+ fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
+ if (n % 2)
+ output_asm_insn (assembler, operands);
+ return "";
+ }
+ else
+ {
+ fprintf (asm_out_file, "\tmov.b #%d,%sl\n", n,
+ names_big[REGNO (operands[4])]);
+ fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
+ output_asm_insn (assembler, operands);
+ output_asm_insn ("add #0xff,%X4", operands);
+ fprintf (asm_out_file, "\tbne .Llt%d\n", loopend_lab);
+ return "";
+ }
}
fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);
@@ -2046,3 +2773,325 @@ fix_bit_operand (operands, what, type)
}
return 1;
}
+
+/* Return nonzero if FUNC is an interrupt function as specified
+ by the "interrupt" attribute. */
+
+static int
+h8300_interrupt_function_p (func)
+ tree func;
+{
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("interrupt_handler", DECL_MACHINE_ATTRIBUTES (func));
+ return a != NULL_TREE;
+}
+
+/* Return nonzero if FUNC is an OS_Task function as specified
+ by the "OS_Task" attribute. */
+
+static int
+h8300_os_task_function_p (func)
+ tree func;
+{
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("OS_Task", DECL_MACHINE_ATTRIBUTES (func));
+ return a != NULL_TREE;
+}
+
+/* Return nonzero if FUNC is a monitor function as specified
+ by the "monitor" attribute. */
+
+static int
+h8300_monitor_function_p (func)
+ tree func;
+{
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("monitor", DECL_MACHINE_ATTRIBUTES (func));
+ return a != NULL_TREE;
+}
+
+/* Return nonzero if FUNC is a function that should be called
+ through the function vector. */
+
+int
+h8300_funcvec_function_p (func)
+ tree func;
+{
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("function_vector", DECL_MACHINE_ATTRIBUTES (func));
+ return a != NULL_TREE;
+}
+
+/* Return nonzero if DECL is a variable that's in the eight bit
+ data area. */
+
+int
+h8300_eightbit_data_p (decl)
+ tree decl;
+{
+ tree a;
+
+ if (TREE_CODE (decl) != VAR_DECL)
+ return 0;
+
+ a = lookup_attribute ("eightbit_data", DECL_MACHINE_ATTRIBUTES (decl));
+ return a != NULL_TREE;
+}
+
+/* Return nonzero if DECL is a variable that's in the tiny
+ data area. */
+
+int
+h8300_tiny_data_p (decl)
+ tree decl;
+{
+ tree a;
+
+ if (TREE_CODE (decl) != VAR_DECL)
+ return 0;
+
+ a = lookup_attribute ("tiny_data", DECL_MACHINE_ATTRIBUTES (decl));
+ return a != NULL_TREE;
+}
+
+/* Return nonzero if ATTR is a valid attribute for DECL.
+ ATTRIBUTES are any existing attributes and ARGS are the arguments
+ supplied with ATTR.
+
+ Supported attributes:
+
+ interrupt_handler: output a prologue and epilogue suitable for an
+ interrupt handler.
+
+ function_vector: This function should be called through the
+ function vector.
+
+ eightbit_data: This variable lives in the 8-bit data area and can
+ be referenced with 8-bit absolute memory addresses.
+
+ tiny_data: This variable lives in the tiny data area and can be
+ referenced with 16-bit absolute memory references. */
+
+int
+h8300_valid_machine_decl_attribute (decl, attributes, attr, args)
+ tree decl;
+ tree attributes;
+ tree attr;
+ tree args;
+{
+ if (args != NULL_TREE)
+ return 0;
+
+ if (is_attribute_p ("interrupt_handler", attr)
+ || is_attribute_p ("OS_Task", attr)
+ || is_attribute_p ("monitor", attr)
+ || is_attribute_p ("function_vector", attr))
+ return TREE_CODE (decl) == FUNCTION_DECL;
+
+ if (is_attribute_p ("eightbit_data", attr)
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+ {
+ if (DECL_INITIAL (decl) == NULL_TREE)
+ {
+ warning ("Only initialized variables can be placed into the 8-bit area.");
+ return 0;
+ }
+ DECL_SECTION_NAME (decl) = build_string (7, ".eight");
+ return 1;
+ }
+
+ if (is_attribute_p ("tiny_data", attr)
+ && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
+ {
+ if (DECL_INITIAL (decl) == NULL_TREE)
+ {
+ warning ("Only initialized variables can be placed into the 8-bit area.");
+ return 0;
+ }
+ DECL_SECTION_NAME (decl) = build_string (6, ".tiny");
+ return 1;
+ }
+
+ return 0;
+}
+
+extern struct obstack *saveable_obstack;
+
+h8300_encode_label (decl)
+ tree decl;
+{
+ char *str = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ int len = strlen (str);
+ char *newstr;
+
+ newstr = obstack_alloc (saveable_obstack, len + 2);
+
+ strcpy (newstr + 1, str);
+ *newstr = '*';
+ XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
+}
+
+char *
+output_simode_bld (bild, log2, operands)
+ int bild;
+ int log2;
+ rtx operands[];
+{
+ /* Clear the destination register. */
+ if (TARGET_H8300H || TARGET_H8300S)
+ output_asm_insn ("sub.l\t%S0,%S0", operands);
+ else
+ output_asm_insn ("sub.w\t%e0,%e0\n\tsub.w\t%f0,%f0", operands);
+
+ /* Get the bit number we want to load. */
+ if (log2)
+ operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+
+ /* Now output the bit load or bit inverse load, and store it in
+ the destination. */
+ if (bild)
+ output_asm_insn ("bild\t%Z2,%Y1\n\tbst\t#0,%w0", operands);
+ else
+ output_asm_insn ("bld\t%Z2,%Y1\n\tbst\t#0,%w0", operands);
+
+ /* All done. */
+ return "";
+}
+
+/* Given INSN and it's current length LENGTH, return the adjustment
+ (in bytes) to correctly compute INSN's length.
+
+ We use this to get the lengths of various memory references correct. */
+
+h8300_adjust_insn_length (insn, length)
+ rtx insn;
+ int length;
+{
+ rtx pat = PATTERN (insn);
+
+ /* Adjust length for reg->mem and mem->reg copies. */
+ if (GET_CODE (pat) == SET
+ && (GET_CODE (SET_SRC (pat)) == MEM
+ || GET_CODE (SET_DEST (pat)) == MEM))
+ {
+ /* This insn might need a length adjustment. */
+ rtx addr;
+
+ if (GET_CODE (SET_SRC (pat)) == MEM)
+ addr = XEXP (SET_SRC (pat), 0);
+ else
+ addr = XEXP (SET_DEST (pat), 0);
+
+ /* On the H8/300, only one adjustment is necessary; if the
+ address mode is register indirect, then this insn is two
+ bytes shorter than indicated in the machine description. */
+ if (TARGET_H8300 && GET_CODE (addr) == REG)
+ return -2;
+
+ /* On the H8/300H and H8/S, register indirect is 6 bytes shorter than
+ indicated in the machine description. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && GET_CODE (addr) == REG)
+ return -6;
+
+ /* On the H8/300H and H8/300S, reg + d, for small displacements is 4
+ bytes shorter than indicated in the machine description. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && GET_CODE (addr) == PLUS
+ && GET_CODE (XEXP (addr, 0)) == REG
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT
+ && INTVAL (XEXP (addr, 1)) > -32768
+ && INTVAL (XEXP (addr, 1)) < 32767)
+ return -4;
+
+ /* On the H8/300H and H8/300S, abs:16 is two bytes shorter than the
+ more general abs:24. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && GET_CODE (addr) == SYMBOL_REF
+ && TINY_DATA_NAME_P (XSTR (addr, 0)))
+ return -2;
+ }
+
+ /* Loading some constants needs adjustment. */
+ if (GET_CODE (pat) == SET
+ && GET_CODE (SET_SRC (pat)) == CONST_INT
+ && GET_MODE (SET_DEST (pat)) == SImode
+ && INTVAL (SET_SRC (pat)) != 0)
+ {
+ if (TARGET_H8300
+ && ((INTVAL (SET_SRC (pat)) & 0xffff) == 0
+ || ((INTVAL (SET_SRC (pat)) >> 16) & 0xffff) == 0))
+ return -2;
+
+ if (TARGET_H8300H || TARGET_H8300S)
+ {
+ int val = INTVAL (SET_SRC (pat));
+
+ if (val == (val & 0xff)
+ || val == (val & 0xff00))
+ return -6;
+
+ if (val == -4 || val == -2 || val == -1)
+ return -6;
+ }
+ }
+
+ /* Shifts need various adjustments. */
+ if (GET_CODE (pat) == PARALLEL
+ && GET_CODE (XVECEXP (pat, 0, 0)) == SET
+ && (GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFTRT
+ || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == LSHIFTRT
+ || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFT))
+ {
+ rtx src = SET_SRC (XVECEXP (pat, 0, 0));
+ enum machine_mode mode = GET_MODE (src);
+
+ if (GET_CODE (XEXP (src, 1)) != CONST_INT)
+ return 0;
+
+ /* QImode shifts by small constants take one insn
+ per shift. So the adjustment is 20 (md length) -
+ # shifts * 2. */
+ if (mode == QImode && INTVAL (XEXP (src, 1)) <= 4)
+ return -(20 - INTVAL (XEXP (src, 1)) * 2);
+
+ /* Similarly for HImode and SImode shifts by
+ small constants on the H8/300H and H8/300S. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && (mode == HImode || mode == SImode)
+ && INTVAL (XEXP (src, 1)) <= 4)
+ return -(20 - INTVAL (XEXP (src, 1)) * 2);
+
+ /* HImode shifts by small constants for the H8/300. */
+ if (mode == HImode
+ && INTVAL (XEXP (src, 1)) <= 4)
+ return -(20 - (INTVAL (XEXP (src, 1))
+ * (GET_CODE (src) == ASHIFT ? 2 : 4)));
+
+ /* SImode shifts by small constants for the H8/300. */
+ if (mode == SImode
+ && INTVAL (XEXP (src, 1)) <= 2)
+ return -(20 - (INTVAL (XEXP (src, 1))
+ * (GET_CODE (src) == ASHIFT ? 6 : 8)));
+
+ /* XXX ??? Could check for more shift/rotate cases here. */
+ }
+
+ return 0;
+}
diff --git a/gnu/usr.bin/gcc/config/h8300/h8300.h b/gnu/usr.bin/gcc/config/h8300/h8300.h
index dfe04d1252b..9002098777c 100644
--- a/gnu/usr.bin/gcc/config/h8300/h8300.h
+++ b/gnu/usr.bin/gcc/config/h8300/h8300.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Hitachi H8/300 version generating coff
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com),
Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
@@ -36,16 +36,19 @@ extern char **h8_reg_names;
/* Names to predefine in the preprocessor for this target machine. */
#define CPP_PREDEFINES \
-"-D__LONG_MAX__=2147483647L -D__LONG_LONG_MAX__=2147483647L -D_DOUBLE_IS_32BITS"
+"-D__LONG_MAX__=2147483647L -D__LONG_LONG_MAX__=2147483647L"
#define CPP_SPEC \
- "%{!mh:-D__H8300__} %{mh:-D__H8300H__} \
- %{!mh:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
+ "%{!mh:%{!ms:-D__H8300__}} %{mh:-D__H8300H__} %{ms:-D__H8300S__} \
+ %{!mh:%{!ms:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}} \
%{mh:-D__SIZE_TYPE__=unsigned\\ long -D__PTRDIFF_TYPE__=long} \
- %{!mh:-Acpu(h8300) -Amachine(h8300)} %{mh:-Acpu(h8300h) -Amachine(h8300h)} \
+ %{ms:-D__SIZE_TYPE__=unsigned\\ long -D__PTRDIFF_TYPE__=long} \
+ %{!mh:%{!ms:-Acpu(h8300) -Amachine(h8300)}} \
+ %{mh:-Acpu(h8300h) -Amachine(h8300h)} \
+ %{ms:-Acpu(h8300s) -Amachine(h8300s)} \
%{!mint32:-D__INT_MAX__=32767} %{mint32:-D__INT_MAX__=2147483647}"
-#define LINK_SPEC "%{mh:-m h8300h}"
+#define LINK_SPEC "%{mh:-m h8300h} %{ms:-m h8300s}"
#define LIB_SPEC "%{mrelax:-relax} %{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
@@ -77,8 +80,16 @@ extern int target_flags;
#define TARGET_RTL_DUMP (target_flags & 2048)
/* Select between the h8/300 and h8/300h cpus. */
-#define TARGET_H8300 (! TARGET_H8300H)
+#define TARGET_H8300 (! TARGET_H8300H && ! TARGET_H8300S)
#define TARGET_H8300H (target_flags & 4096)
+#define TARGET_H8300S (target_flags & 1)
+
+/* Align all values on the h8/300h the same way as the h8/300. Specifically,
+ 32 bit and larger values are aligned on 16 bit boundaries.
+ This is all the hardware requires, but the default is 32 bits for the 300h.
+ ??? Now watch someone add hardware floating point requiring 32 bit
+ alignment. */
+#define TARGET_ALIGN_300 (target_flags & 8192)
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
@@ -87,7 +98,9 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
- { {"int32",8}, \
+ { {"s",1 }, \
+ {"no-s",-1}, \
+ {"int32",8}, \
{"addresses",64 }, \
{"quickcall",128}, \
{"no-quickcall",-128}, \
@@ -96,20 +109,15 @@ extern int target_flags;
{"rtl-dump",2048}, \
{"h",4096}, \
{"no-h",-4096}, \
- {"exp",8192}, \
+ {"align-300",8192}, \
{ "", TARGET_DEFAULT}}
-/* Merge the meaning of -mdouble64 and -fshort-double.
- ??? Unfortunately, there's no way to detect -fno-short-double
- (our default is the opposite of theirs).
- Also do other things that must be done once at start up. */
+/* Do things that must be done once at start up. */
#define OVERRIDE_OPTIONS \
-{ \
- /*extern int flag_short_double; \
- flag_short_double = TARGET_DOUBLE32;*/ \
+do { \
h8300_init_once (); \
-}
+} while (0)
/* Default target_flags if no switches specified. */
@@ -123,8 +131,12 @@ extern int target_flags;
/* 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
+ but a CALL with constant address is cheap.
+
+ Calls through a register are cheaper than calls to named
+ functions; however, the register pressure this causes makes
+ CSEing of function addresses generally a lose. */
+#define NO_FUNCTION_CSE
/* Target machine storage layout */
@@ -144,7 +156,7 @@ extern int target_flags;
/* Define this if most significant word of a multiword number is lowest
numbered.
This is true on an H8/300 (actually we can make it up, but we choose to
- be consistent. */
+ be consistent). */
#define WORDS_BIG_ENDIAN 1
/* Number of bits in an addressable storage unit */
@@ -154,21 +166,21 @@ extern int target_flags;
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_H8300H ? 32 : 16)
+#define BITS_PER_WORD (TARGET_H8300H || TARGET_H8300S ? 32 : 16)
#define MAX_BITS_PER_WORD 32
/* Width of a word, in units (bytes). */
-#define UNITS_PER_WORD (TARGET_H8300H ? 4 : 2)
+#define UNITS_PER_WORD (TARGET_H8300H || TARGET_H8300S ? 4 : 2)
#define MIN_UNITS_PER_WORD 2
/* Width in bits of a pointer.
See also the macro `Pmode' defined below. */
-#define POINTER_SIZE (TARGET_H8300H ? 32 : 16)
+#define POINTER_SIZE (TARGET_H8300H || TARGET_H8300S ? 32 : 16)
#define SHORT_TYPE_SIZE 16
#define INT_TYPE_SIZE (TARGET_INT32 ? 32 : 16)
#define LONG_TYPE_SIZE 32
-#define LONG_LONG_TYPE_SIZE 32
+#define LONG_LONG_TYPE_SIZE 32
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 32
#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
@@ -176,22 +188,24 @@ extern int target_flags;
#define MAX_FIXED_MODE_SIZE 32
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
-#define PARM_BOUNDARY (TARGET_H8300H ? 32 : 16)
+#define PARM_BOUNDARY (TARGET_H8300H || TARGET_H8300S ? 32 : 16)
/* Allocation boundary (in *bits*) for the code of a function. */
#define FUNCTION_BOUNDARY 16
/* Alignment of field after `int : 0' in a structure. */
+/* One can argue this should be 32 for -mint32, but since 32 bit ints only
+ need 16 bit alignment, this is left as is so that -mint32 doesn't change
+ structure layouts. */
#define EMPTY_FIELD_BOUNDARY 16
/* A bitfield declared as `int' forces `int' alignment for the struct. */
#define PCC_BITFIELD_TYPE_MATTERS 0
-/* No data type wants to be aligned rounder than this. */
-#define BIGGEST_ALIGNMENT (TARGET_H8300H ? 32 : 16)
-
-/* No structure field wants to be aligned rounder than this. */
-#define BIGGEST_FIELD_ALIGNMENT (TARGET_H8300H ? 32 : 16)
+/* No data type wants to be aligned rounder than this.
+ 32 bit values are aligned as such on the 300h for speed. */
+#define BIGGEST_ALIGNMENT \
+(((TARGET_H8300H || TARGET_H8300S) && ! TARGET_ALIGN_300) ? 32 : 16)
/* The stack goes in 16/32 bit lumps. */
#define STACK_BOUNDARY (TARGET_H8300 ? 16 : 32)
@@ -211,18 +225,18 @@ extern int target_flags;
All registers that the compiler knows about must be given numbers,
even those that are not normally considered general registers.
- Reg 8 does not correspond to any hardware register, but instead
+ Reg 9 does not correspond to any hardware register, but instead
appears in the RTL as an argument pointer prior to reload, and is
eliminated during reloading in favor of either the stack or frame
pointer. */
-#define FIRST_PSEUDO_REGISTER 9
+#define FIRST_PSEUDO_REGISTER 10
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator. */
#define FIXED_REGISTERS \
- { 0, 0, 0, 0, 0, 0, 0, 1, 1}
+ { 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -235,19 +249,28 @@ extern int target_flags;
h8 destroys r0,r1,r2,r3. */
#define CALL_USED_REGISTERS \
- { 1, 1, 1, 1, 0, 0, 0, 1, 1 }
+ { 1, 1, 1, 1, 0, 0, 0, 1, 1, 1 }
#define REG_ALLOC_ORDER \
- { 2, 3, 0, 1, 4, 5, 6, 7, 8}
+ { 2, 3, 0, 1, 4, 5, 6, 8, 7, 9}
+
+#define CONDITIONAL_REGISTER_USAGE \
+{ \
+ if (!TARGET_H8300S) \
+ fixed_regs[8] = call_used_regs[8] = 1;\
+}
/* 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. */
+ but can be less for certain modes in special long registers.
+
+ We pretend the MAC register is 32bits -- we don't have any data
+ types on the H8 series to handle more than 32bits. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
- ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* Value is 1 if hard register REGNO can hold a value of machine-mode
MODE.
@@ -258,7 +281,7 @@ extern int target_flags;
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(TARGET_H8300 ? (((REGNO)&1)==0) || (MODE==HImode) || (MODE==QImode) \
- : 1)
+ : REGNO == 8 ? MODE == SImode : 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.
@@ -286,7 +309,7 @@ extern int target_flags;
#define FRAME_POINTER_REQUIRED 0
/* Base register for access to arguments of the function. */
-#define ARG_POINTER_REGNUM 8
+#define ARG_POINTER_REGNUM 9
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 3
@@ -311,17 +334,16 @@ extern int target_flags;
For any two classes, it is very desirable that there be another
class that represents their union. */
-/* The h8 has only one kind of register, but we mustn't do byte by
- byte operations on the sp, so we keep it as a different class */
-
-enum reg_class { NO_REGS, LONG_REGS, GENERAL_REGS, SP_REG, SP_AND_G_REG, ALL_REGS, LIM_REG_CLASSES };
+enum reg_class {
+ NO_REGS, GENERAL_REGS, MAC_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", "LONG_REGS", "GENERAL_REGS", "SP_REG", "SP_AND_G_REG", "ALL_REGS", "LIM_REGS" }
+{ "NO_REGS", "GENERAL_REGS", "MAC_REGS", "ALL_REGS", "LIM_REGS" }
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
@@ -329,11 +351,9 @@ enum reg_class { NO_REGS, LONG_REGS, GENERAL_REGS, SP_REG, SP_AND_G_REG, ALL_RE
#define REG_CLASS_CONTENTS \
{ 0, /* No regs */ \
- 0x07f, /* LONG_REGS */ \
- 0x07f, /* GENERAL_REGS */ \
- 0x080, /* SP_REG */ \
- 0x0ff, /* SP_AND_G_REG */ \
- 0x1ff, /* ALL_REGS */ \
+ 0x2ff, /* GENERAL_REGS */ \
+ 0x100, /* MAC_REGS */ \
+ 0x3ff, /* ALL_REGS */ \
}
/* The same information, inverted:
@@ -341,20 +361,18 @@ enum reg_class { NO_REGS, LONG_REGS, GENERAL_REGS, SP_REG, SP_AND_G_REG, ALL_RE
reg number REGNO. This could be a conditional expression
or could index an array. */
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) < 7 ? LONG_REGS : \
- (REGNO) == 7 ? SP_REG : \
- GENERAL_REGS)
+#define REGNO_REG_CLASS(REGNO) (REGNO != 8 ? GENERAL_REGS : MAC_REGS)
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS NO_REGS
#define BASE_REG_CLASS GENERAL_REGS
-/* Get reg_class from a letter such as appears in the machine description. */
+/* Get reg_class from a letter such as appears in the machine description.
+
+ 'a' is the MAC register. */
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'a' ? (SP_REG) : (C) == 'l' ? (LONG_REGS) : (NO_REGS))
+#define REG_CLASS_FROM_LETTER(C) ((C) == 'a' ? MAC_REGS : NO_REGS)
/* The letters I, J, K, L, M, N, O, P in a register constraint string
can be used to stand for particular ranges of immediate operands.
@@ -410,7 +428,8 @@ enum reg_class { NO_REGS, LONG_REGS, GENERAL_REGS, SP_REG, SP_AND_G_REG, ALL_RE
so define REGISTER_MOVE_COST to be > 2 so that reload never
shortcuts. */
-#define REGISTER_MOVE_COST(CLASS1, CLASS2) 3
+#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
+ (CLASS1 == MAC_REGS || CLASS2 == MAC_REGS ? 6 : 3)
/* Stack layout; function entry, exit and calling. */
@@ -529,9 +548,8 @@ enum reg_class { NO_REGS, LONG_REGS, GENERAL_REGS, SP_REG, SP_AND_G_REG, ALL_RE
/* 1 if N is a possible register number for function argument passing.
On the H8, no registers are used in this way. */
-/* ??? What about TARGET_QUICKCALL? */
-#define FUNCTION_ARG_REGNO_P(N) 0
+#define FUNCTION_ARG_REGNO_P(N) (TARGET_QUICKCALL ? N < 3 : 0)
/* Register in which address to store a structure value
is passed to a function. */
@@ -539,14 +557,14 @@ enum reg_class { NO_REGS, LONG_REGS, GENERAL_REGS, SP_REG, SP_AND_G_REG, ALL_RE
#define STRUCT_VALUE 0
/* Return true if X should be returned in memory. */
-/* ??? This will return small structs in regs. */
-#define RETURN_IN_MEMORY(X) (GET_MODE_SIZE (TYPE_MODE (X)) > 4)
+#define RETURN_IN_MEMORY(X) \
+ (TYPE_MODE (X) == BLKmode || GET_MODE_SIZE (TYPE_MODE (X)) > 4)
/* When defined, the compiler allows registers explicitly used in the
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 a data type for recording info about an argument list
during the scan of that argument list. This data type should
@@ -567,7 +585,7 @@ struct cum_arg { int nbytes; struct rtx_def * libcall; };
On the H8/300, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM).nbytes = 0, (CUM).libcall = LIBNAME)
/* Update the data in CUM to advance over an argument
@@ -600,13 +618,6 @@ struct rtx_def *function_arg();
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED)
-/* Perform any needed actions needed for a function that is receiving a
- variable number of arguments. */
-
-extern int current_function_anonymous_args;
-#define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST) \
- current_function_anonymous_args = 1;
-
/* Generate assembly output for the start of a function. */
#define FUNCTION_PROLOGUE(FILE, SIZE) \
@@ -701,10 +712,10 @@ extern int current_function_anonymous_args;
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
- enum machine_mode mode = TARGET_H8300H ? SImode : HImode; \
- emit_move_insn (gen_rtx (MEM, mode, plus_constant ((TRAMP), 2)), CXT); \
- emit_move_insn (gen_rtx (MEM, mode, plus_constant ((TRAMP), 6)), FNADDR); \
- if (TARGET_H8300H) \
+ enum machine_mode mode = TARGET_H8300H || TARGET_H8300S? SImode : HImode; \
+ emit_move_insn (gen_rtx (MEM, mode, plus_constant ((TRAMP), 2)), CXT); \
+ emit_move_insn (gen_rtx (MEM, mode, plus_constant ((TRAMP), 6)), FNADDR); \
+ if (TARGET_H8300H || TARGET_H8300S) \
emit_move_insn (gen_rtx (MEM, QImode, plus_constant ((TRAMP), 6)), GEN_INT (0x5A)); \
}
@@ -727,7 +738,7 @@ extern int current_function_anonymous_args;
#define REGNO_OK_FOR_INDEX_P(regno) 0
#define REGNO_OK_FOR_BASE_P(regno) \
- ((regno) < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+ (((regno) < FIRST_PSEUDO_REGISTER && regno != 8) || reg_renumber[regno] >= 0)
/* Maximum number of registers that can appear in a valid memory address. */
@@ -741,8 +752,8 @@ extern int current_function_anonymous_args;
/* We handle signed and unsigned offsets here. */ \
&& INTVAL (X) > (TARGET_H8300 ? -0x10000 : -0x1000000) \
&& INTVAL (X) < (TARGET_H8300 ? 0x10000 : 0x1000000)) \
- || GET_CODE (X) == CONST \
- || GET_CODE (X) == HIGH)
+ || ((GET_CODE (X) == HIGH || GET_CODE (X) == CONST) \
+ && TARGET_H8300))
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
@@ -769,7 +780,9 @@ extern int current_function_anonymous_args;
#define REG_OK_FOR_INDEX_P(X) 0
/* Nonzero if X is a hard reg that can be used as a base reg
or if it is a pseudo reg. */
-#define REG_OK_FOR_BASE_P(X) 1
+/* Don't use REGNO_OK_FOR_BASE_P here because it uses reg_renumber. */
+#define REG_OK_FOR_BASE_P(X) \
+ (REGNO (X) >= FIRST_PSEUDO_REGISTER || REGNO (X) != 8)
#define REG_OK_FOR_INDEX_P_STRICT(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
#define REG_OK_FOR_BASE_P_STRICT(X) REGNO_OK_FOR_BASE_P (REGNO (X))
#define STRICT 0
@@ -785,11 +798,21 @@ extern int current_function_anonymous_args;
#endif
/* Extra constraints - 'U' if for an operand valid for a bset
- destination; i.e. a register or register indirect target. */
+ destination; i.e. a register, register indirect, or the
+ eightbit memory region (a SYMBOL_REF with an SYMBOL_REF_FLAG set).
+
+ On the H8/S 'U' can also be a 16bit or 32bit absolute. */
#define OK_FOR_U(OP) \
((GET_CODE (OP) == REG && REG_OK_FOR_BASE_P (OP)) \
|| (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
- && REG_OK_FOR_BASE_P (XEXP (OP, 0))))
+ && REG_OK_FOR_BASE_P (XEXP (OP, 0))) \
+ || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF \
+ && (TARGET_H8300S || SYMBOL_REF_FLAG (XEXP (OP, 0)))) \
+ || (GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == CONST \
+ && GET_CODE (XEXP (XEXP (OP, 0), 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 0)) == SYMBOL_REF \
+ && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 1)) == CONST_INT) \
+ && (TARGET_H8300S || SYMBOL_REF_FLAG (XEXP (XEXP (OP, 0), 0))))
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'U' ? OK_FOR_U (OP) : 0)
@@ -841,9 +864,7 @@ extern int current_function_anonymous_args;
has an effect that depends on the machine mode it is used for.
On the H8/300, the predecrement and postincrement address depend thus
- (the amount of decrement or increment being the length of the operand)
- and all indexed address depend thus (because the index scale factor
- is the length of the operand). */
+ (the amount of decrement or increment being the length of the operand). */
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
if (GET_CODE (ADDR) == POST_INC || GET_CODE (ADDR) == PRE_DEC) goto LABEL;
@@ -880,7 +901,7 @@ extern int current_function_anonymous_args;
/* Max number of bytes we can move from memory to memory
in one reasonably fast instruction. */
-#define MOVE_MAX (TARGET_H8300H ? 4 : 2)
+#define MOVE_MAX (TARGET_H8300H || TARGET_H8300S ? 4 : 2)
#define MAX_MOVE_MAX 4
/* Define this if zero-extension is slow (more than one real instruction). */
@@ -901,7 +922,7 @@ extern int current_function_anonymous_args;
/* 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_H8300H ? SImode : HImode)
+#define Pmode (TARGET_H8300H || TARGET_H8300S ? SImode : HImode)
/* ANSI C types.
We use longs for the 300h because ints can be 16 or 32.
@@ -920,6 +941,16 @@ extern int current_function_anonymous_args;
so give the MEM rtx a byte's mode. */
#define FUNCTION_MODE QImode
+/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+ is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+extern int h8300_valid_machine_decl_attribute ();
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+h8300_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+ LENGTH += h8300_adjust_insn_length (INSN, LENGTH);
+
/* 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,
@@ -955,7 +986,7 @@ extern int current_function_anonymous_args;
/* Tell final.c how to eliminate redundant test instructions. */
/* Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). No extra ones are needed for the vax. */
+ (see `conditions.h'). No extra ones are needed for the h8300. */
/* Store in cc_status the expressions
that the condition codes will describe
@@ -963,14 +994,15 @@ extern int current_function_anonymous_args;
Do not alter them if the instruction would not alter the cc's. */
#define NOTICE_UPDATE_CC(EXP, INSN) notice_update_cc(EXP, INSN)
-#define CC_DONE_CBIT 0400
-#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
-{ \
- if (cc_status.flags & CC_NO_OVERFLOW) \
- return NO_OV; \
- return NORMAL; \
-}
+/* The add insns don't set overflow in a usable way. */
+#define CC_OVERFLOW_UNUSABLE 01000
+/* The mov,and,or,xor insns don't set carry. That's ok though as the
+ Z bit is all we need when doing unsigned comparisons on the result of
+ these insns (since they're always with 0). However, conditions.h has
+ CC_NO_OVERFLOW defined for this purpose. Rename it to something more
+ understandable. */
+#define CC_NO_CARRY CC_NO_OVERFLOW
/* Control the assembler format that we output. */
@@ -998,7 +1030,14 @@ extern int current_function_anonymous_args;
/* The assembler op to get a word, 2 bytes for the H8/300, 4 for H8/300H. */
#define ASM_WORD_OP (TARGET_H8300 ? ".word" : ".long")
-/* Output before read-only data. */
+/* We define a readonly data section solely to remove readonly data
+ from the instruction stream. This can improve relaxing in two significant
+ ways. First it's more likely that references to readonly data
+ can be done with a 16bit absolute address since they'll be in low
+ memory. Second, it's more likely that jsr instructions can be
+ turned into bsr instructions since read-only data is not in the
+ instruction stream. */
+#define READONLY_DATA_SECTION readonly_data
#define TEXT_SECTION_ASM_OP "\t.section .text"
#define DATA_SECTION_ASM_OP "\t.section .data"
@@ -1006,8 +1045,9 @@ extern int current_function_anonymous_args;
#define INIT_SECTION_ASM_OP "\t.section .init"
#define CTORS_SECTION_ASM_OP "\t.section .ctors"
#define DTORS_SECTION_ASM_OP "\t.section .dtors"
+#define READONLY_DATA_SECTION_ASM_OP "\t.section .rodata"
-#define EXTRA_SECTIONS in_ctors, in_dtors
+#define EXTRA_SECTIONS in_ctors, in_dtors, in_readonly_data
#define EXTRA_SECTION_FUNCTIONS \
\
@@ -1030,6 +1070,18 @@ dtors_section() \
in_section = in_dtors; \
} \
} \
+ \
+void \
+readonly_data() \
+{ \
+ if (in_section != in_readonly_data) \
+ { \
+ fprintf (asm_out_file, "%s\n", READONLY_DATA_SECTION_ASM_OP);\
+ in_section = in_readonly_data; \
+ } \
+}
+
+
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { ctors_section(); \
@@ -1065,11 +1117,34 @@ dtors_section() \
} \
}
+#define TINY_DATA_NAME_P(NAME) (*(NAME) == '*')
+
+/* If we are referencing a function that is supposed to be called
+ through the function vector, the SYMBOL_REF_FLAG in the rtl
+ so the call patterns can generate the correct code. */
+#define ENCODE_SECTION_INFO(DECL) \
+ if (TREE_CODE (DECL) == FUNCTION_DECL \
+ && h8300_funcvec_function_p (DECL)) \
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
+ else if ((TREE_STATIC (DECL) || DECL_EXTERNAL (DECL)) \
+ && TREE_CODE (DECL) == VAR_DECL \
+ && h8300_eightbit_data_p (DECL)) \
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1; \
+ else if ((TREE_STATIC (DECL) || DECL_EXTERNAL (DECL)) \
+ && TREE_CODE (DECL) == VAR_DECL \
+ && h8300_tiny_data_p (DECL)) \
+ h8300_encode_label (DECL);
+
+/* Store the user-specified part of SYMBOL_NAME in VAR.
+ This is sort of inverse to ENCODE_SECTION_INFO. */
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+ (VAR) = (SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*' || (SYMBOL_NAME)[0] == '@');
+
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
#define REGISTER_NAMES \
-{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "ap"}
+{ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", "mac", "ap"}
#define ADDITIONAL_REGISTER_NAMES { { "r7", 7 } }
@@ -1081,20 +1156,26 @@ dtors_section() \
#define SDB_DEBUGGING_INFO
#define SDB_DELIM "\n"
-/* Output DBX (stabs) debugging information if doing -gstabs. */
+/* Support -gstabs. */
-#define DBX_DEBUGGING_INFO
+#include "dbxcoff.h"
-/* Generate SDB debugging information by default. */
+/* Override definition in dbxcoff.h. */
+/* 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 PREFERRED_DEBUGGING_TYPE SDB_DEBUG
+#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
+#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
+ fprintf (FILE, \
+ "\t.text\n.stabs \"\",%d,0,0,.Letext\n.Letext:\n", N_SO)
/* 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. */
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
fprintf (FILE, "\t.section %s\n", NAME)
/* This is how to output the definition of a user-level label named NAME,
@@ -1114,11 +1195,9 @@ dtors_section() \
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
ASM_OUTPUT_LABEL(FILE, NAME)
-/* 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. */
@@ -1221,6 +1300,13 @@ do { char dstr[30]; \
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%d\n", (SIZE)))
+/* This says how to output the assembler to define a global
+ uninitialized but not common symbol.
+ Try to use asm_output_bss to implement this macro. */
+
+#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \
+ asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED))
+
/* This says how to output an assembler line
to define a local common symbol. */
@@ -1261,11 +1347,17 @@ do { char dstr[30]; \
#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE,X,CODE)
/* Print a memory operand whose address is X, on file FILE.
- This uses a function in output-vax.c. */
+ This uses a function in h8300.c. */
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
-#define HANDLE_PRAGMA(FILE) handle_pragma (FILE)
+/* Define this macro if you want to implement any pragmas. If defined, it
+ should be a C expression to be executed when #pragma is seen. The
+ argument STREAM is the stdio input stream from which the source
+ text can be read. CH is the first character after the #pragma. The
+ result of the expression is the terminating character found
+ (newline or EOF). */
+#define HANDLE_PRAGMA(FILE, NODE) handle_pragma (FILE, NODE)
#define FINAL_PRESCAN_INSN(insn, operand, nop) final_prescan_insn (insn, operand,nop)
@@ -1301,5 +1393,7 @@ do { char dstr[30]; \
/* Declarations for functions used in insn-output.c. */
char *emit_a_shift ();
-
+int h8300_funcvec_function_p ();
+char *output_adds_subs ();
+char * output_simode_bld ();
diff --git a/gnu/usr.bin/gcc/config/h8300/h8300.md b/gnu/usr.bin/gcc/config/h8300/h8300.md
index 6ad86168c9c..ebc1a29cea4 100644
--- a/gnu/usr.bin/gcc/config/h8300/h8300.md
+++ b/gnu/usr.bin/gcc/config/h8300/h8300.md
@@ -1,5 +1,5 @@
;; GCC machine description for Hitachi H8/300
-;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
;; Contributed by Steve Chamberlain (sac@cygnus.com),
;; Jim Wilson (wilson@cygnus.com), and Doug Evans (dje@cygnus.com).
@@ -21,7 +21,6 @@
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
-
;; The original PO technology requires these to be ordered by speed,
;; so that assigner will pick the fastest.
@@ -30,10 +29,38 @@
(define_attr "cpu" "h8300,h8300h"
(const (symbol_ref "cpu_type")))
-;; ??? If we can remove the operand type on all the insns, do it.
-;; ??? Otherwise, try to have the operand type on all the insns.
+;; Many logical operations should have "bit" variants if only one
+;; bit is going to be operated on.
+
+;; (and (logical op) (const_int X))
+;; If const_int only specifies a few bits (like a single byte in a 4 byte
+;; operation, then it's more efficient to only apply the and and logical_op
+;; to the bits we care about.
+
+;; Some of the extend instructions accept a general_operand_src, which
+;; allows all the normal memory addressing modes. The length computations
+;; don't take this into account. The lengths in the MD file should be
+;; "worst case" and then be adjusted to their correct values by
+;; h8300_adjust_insn_length.
+
+;; On the h8300h, adds/subs operate on the 32bit "er" registers. Right
+;; now GCC doesn't expose the "e" half to the compiler, so using add/subs
+;; for addhi and subhi is safe.
+;; Long term, we want to expose the "e" half to the compiler (gives us
+;; 8 more 16bit registers). At that point addhi and subhi can't use adds/subs.
+
+;; There's currently no way to have a insv/extzv expander for the h8/300h
+;; because word_mode is different for the h8/300 and h8/300h.
-(define_attr "type" "branch,return,call,arith,move,float,multi"
+;; Shifts/rotates by small constants should be handled by special
+;; patterns so we get the length and cc status correct.
+
+;; Bitfield operations no longer accept memory operands. We need
+;; to add variants which operate on memory back to the MD.
+
+;; ??? Implement remaining bit ops available on the h8300
+
+(define_attr "type" "branch,arith"
(const_string "arith"))
;; The size of instructions in bytes.
@@ -51,16 +78,21 @@
(le (minus (pc) (match_dup 0))
(const_int 32000))))
(const_int 4)
- (const_int 6)))
- (eq_attr "type" "move") (const_int 4)
- (eq_attr "type" "return") (const_int 2)
- (eq_attr "type" "float") (const_int 12)
- (eq_attr "type" "call") (const_int 4)]
+ (const_int 6)))]
(const_int 200)))
-(define_attr "cc" "none,clobber,none_0hit,set,compare,whoops,cbit"
- (const_string "whoops"))
-
+;; Condition code settings.
+;; none - insn does not affect cc
+;; none_0hit - insn does not affect cc but it does modify operand 0
+;; This attribute is used to keep track of when operand 0 changes.
+;; See the description of NOTICE_UPDATE_CC for more info.
+;; set_znv - insn sets z,n,v to usable values (like a tst insn); c is unknown.
+;; set_zn - insn sets z,n to usable values; v,c are unknown.
+;; compare - compare instruction
+;; clobber - value of cc is unknown
+(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber"
+ (const_string "clobber"))
+
;; ----------------------------------------------------------------------
;; MOVE INSTRUCTIONS
;; ----------------------------------------------------------------------
@@ -78,29 +110,26 @@
else
return \"push.l %S1\";
}"
- [(set_attr "type" "move")
- (set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
- (set_attr "cc" "set")])
-
-(define_insn "movqi_internal"
- [(set (match_operand:QI 0 "general_operand_dst" "=r,r,r,o,<,r")
- (match_operand:QI 1 "general_operand_src" "I,r>,io,r,r,c"))]
- "register_operand (operands[0],QImode) || register_operand (operands[1], QImode)"
+ [(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
+ (set_attr "cc" "set_znv")])
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand_dst" "=r,r,<,r,r,m")
+ (match_operand:QI 1 "general_operand_src" "I,r>,r,n,m,r"))]
+ "register_operand (operands[0],QImode)
+ || register_operand (operands[1], QImode)"
"@
sub.b %X0,%X0
- mov.b %X1,%X0
- mov.b %X1,%X0
- mov.b %X1,%X0
- mov.b %X1,%X0
- xor %X0,%X0\;bst #0,%X0"
- [(set_attr "type" "move")
- (set_attr_alternative "length"
- [(const_int 2) (const_int 2)
+ mov.b %R1,%X0
+ mov.b %X1,%R0
+ mov.b %R1,%X0
+ mov.b %R1,%X0
+ mov.b %X1,%R0"
+ [(set_attr_alternative "length"
+ [(const_int 2) (const_int 2) (const_int 2) (const_int 2)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))
- (const_int 4)])
- (set_attr "cc" "set,set,set,set,set,none")])
+ (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
+ (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand_dst" "")
@@ -117,28 +146,26 @@
}")
(define_insn "movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "=r,r,r,o,<"))
- (match_operand:QI 1 "general_operand_src" "I,r,io,r,r"))]
+ [(set (strict_low_part (match_operand:QI 0 "general_operand_dst" "=r,r,r,r"))
+ (match_operand:QI 1 "general_operand_src" "I,r,n,m"))]
""
"@
sub.b %X0,%X0
mov.b %X1,%X0
- mov.b %X1,%X0
- mov.b %X1,%X0
- mov.b %X1,%X0"
- [(set_attr "type" "move")
- (set_attr_alternative "length"
- [(const_int 2) (const_int 2)
- (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))])
- (set_attr "cc" "set")])
+ mov.b %R1,%X0
+ mov.b %R1,%X0"
+ [(set_attr_alternative "length"
+ [(const_int 2) (const_int 2) (const_int 2)
+ (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
+ (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")])
;; movhi
+;; ??? We use push.l on the h8300h to push a 16bit value?!? We have
+;; 16bit push insns!
(define_insn "movhi_push"
[(set (match_operand:HI 0 "push_operand" "=<")
- (match_operand:HI 1 "register_operand" "ra"))]
+ (match_operand:HI 1 "register_operand" "r"))]
""
"*
{
@@ -147,27 +174,26 @@
else
return \"push.l %S1\";
}"
- [(set_attr "type" "move")
- (set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
- (set_attr "cc" "set")])
-
-(define_insn "movhi_internal"
- [(set (match_operand:HI 0 "general_operand_dst" "=ra,ra,ra,o,<")
- (match_operand:HI 1 "general_operand_src" "I,ra>,ion,ra,ra"))]
- ""
+ [(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
+ (set_attr "cc" "set_znv")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,r,m")
+ (match_operand:HI 1 "general_operand_src" "I,r>,r,i,m,r"))]
+ "register_operand (operands[0],HImode)
+ || register_operand (operands[1], HImode)"
"@
sub.w %T0,%T0
mov.w %T1,%T0
mov.w %T1,%T0
mov.w %T1,%T0
+ mov.w %T1,%T0
mov.w %T1,%T0"
- [(set_attr "type" "move")
- (set_attr_alternative "length"
- [(const_int 2) (const_int 2)
+ [(set_attr_alternative "length"
+ [(const_int 2) (const_int 2) (const_int 2) (const_int 4)
(if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))])
- (set_attr "cc" "set")])
+ (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
+ (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand_dst" "")
@@ -184,22 +210,18 @@
}")
(define_insn "movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r,o,<"))
- (match_operand:HI 1 "general_operand_src" "I,r,io,r,r"))]
+ [(set (strict_low_part (match_operand:HI 0 "general_operand_dst" "=r,r,r,r"))
+ (match_operand:HI 1 "general_operand_src" "I,r,i,m"))]
""
"@
sub.w %T0,%T0
mov.w %T1,%T0
mov.w %T1,%T0
- mov.w %T1,%T0
mov.w %T1,%T0"
- [(set_attr "type" "move")
- (set_attr_alternative "length"
- [(const_int 2) (const_int 2)
- (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))
- (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4))])
- (set_attr "cc" "set")])
+ [(set_attr_alternative "length"
+ [(const_int 2) (const_int 2) (const_int 4)
+ (if_then_else (eq_attr "cpu" "h8300") (const_int 4) (const_int 8))])
+ (set_attr "cc" "set_zn,set_znv,set_znv,set_znv")])
;; movsi
@@ -214,7 +236,7 @@
if (do_movsi (operands))
DONE;
}
- else /* TARGET_H8300H */
+ else
{
/* One of the ops has to be in a register. */
if (!register_operand (operand1, SImode)
@@ -236,7 +258,7 @@
if (do_movsi (operands))
DONE;
}
- else /* TARGET_H8300H */
+ else
{
/* One of the ops has to be in a register. */
if (!register_operand (operand1, SFmode)
@@ -249,7 +271,7 @@
(define_insn "movsi_h8300"
[(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,o,<,r")
- (match_operand:SI 1 "general_operand_src" "I,r,ion,r,r,>"))]
+ (match_operand:SI 1 "general_operand_src" "I,r,io,r,r,>"))]
"TARGET_H8300
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
@@ -290,24 +312,31 @@
}
else
{
- return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
+ /* See if either half is zero. If so, use sub.w to clear
+ that half. */
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if ((INTVAL (operands[1]) & 0xffff) == 0)
+ return \"mov.w %e1,%e0\;sub.w %f0,%f0\";
+ if (((INTVAL (operands[1]) >> 16) & 0xffff) == 0)
+ return \"sub.w %e0,%e0\;mov.w %f1,%f0\";
+ }
+ return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
}
-
case 3:
- return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
+ return \"mov.w %e1,%e0\;mov.w %f1,%f0\";
case 4:
return \"mov.w %f1,%T0\;mov.w %e1,%T0\";
case 5:
return \"mov.w %T1,%e0\;mov.w %T1,%f0\";
}
}"
- [(set_attr "type" "move")
- (set_attr "length" "4,4,8,8,4,4")
+ [(set_attr "length" "4,4,8,8,4,4")
(set_attr "cc" "clobber")])
(define_insn "movsf_h8300"
[(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,o,<,r")
- (match_operand:SF 1 "general_operand_src" "I,r,ion,r,r,>"))]
+ (match_operand:SF 1 "general_operand_src" "I,r,io,r,r,>"))]
"TARGET_H8300
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
@@ -361,31 +390,60 @@
}
}"
- [(set_attr "type" "move")
- (set_attr "length" "4,4,8,8,4,4")
+ [(set_attr "length" "4,4,8,8,4,4")
(set_attr "cc" "clobber")])
-(define_insn "movsi_h8300h"
- [(set (match_operand:SI 0 "general_operand_dst" "=ra,ra,ra,o,<,ra")
- (match_operand:SI 1 "general_operand_src" "I,ra,ion,ra,ra,>"))]
- "TARGET_H8300H
+(define_insn "movsi_h8300hs"
+ [(set (match_operand:SI 0 "general_operand_dst" "=r,r,r,m,<,r,*a,*a,r")
+ (match_operand:SI 1 "general_operand_src" "I,r,im,r,r,>,I,r,*a"))]
+ "(TARGET_H8300S || TARGET_H8300H)
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
- "@
- sub.l %S0,%S0
- mov.l %S1,%S0
- mov.l %S1,%S0
- mov.l %S1,%S0
- mov.l %S1,%S0
- mov.l %S1,%S0"
- [(set_attr "type" "move")
- (set_attr "length" "2,2,8,8,4,4")
- (set_attr "cc" "set")])
+ "*
+{
+ if (which_alternative == 0)
+ return \"sub.l %S0,%S0\";
+ if (which_alternative == 6)
+ return \"clrmac\";
+ if (which_alternative == 7)
+ return \"clrmac\;ldmac %1,macl\";
+ if (which_alternative == 8)
+ return \"stmac macl,%0\";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ int val = INTVAL (operands[1]);
+
+ /* Look for constants which can be made by adding an 8-bit
+ number to zero in one of the two low bytes. */
+ if (val == (val & 0xff))
+ {
+ operands[1] = GEN_INT ((char)val & 0xff);
+ return \"sub.l %S0,%S0\;add.b %1,%w0\";
+ }
+
+ if (val == (val & 0xff00))
+ {
+ operands[1] = GEN_INT ((char)(val >> 8) & 0xff);
+ return \"sub.l %S0,%S0\;add.b %1,%x0\";
+ }
+
+ /* Now look for small negative numbers. We can subtract them
+ from zero to get the desired constant. */
+ if (val == -4 || val == -2 || val == -1)
+ {
+ operands[1] = GEN_INT (-INTVAL (operands[1]));
+ return \"sub.l %S0,%S0\;subs %1,%S0\";
+ }
+ }
+ return \"mov.l %S1,%S0\";
+}"
+ [(set_attr "length" "2,2,10,10,4,4,2,6,4")
+ (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv,none_0hit,none_0hit,set_znv")])
(define_insn "movsf_h8300h"
- [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,o,<,r")
- (match_operand:SF 1 "general_operand_src" "I,r,ion,r,r,>"))]
- "TARGET_H8300H
+ [(set (match_operand:SF 0 "general_operand_dst" "=r,r,r,m,<,r")
+ (match_operand:SF 1 "general_operand_src" "I,r,im,r,r,>"))]
+ "(TARGET_H8300H || TARGET_H8300S)
&& (register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode))"
"@
@@ -395,93 +453,137 @@
mov.l %S1,%S0
mov.l %S1,%S0
mov.l %S1,%S0"
- [(set_attr "type" "move")
- (set_attr "length" "2,2,8,8,4,4")
- (set_attr "cc" "set")])
-
+ [(set_attr "length" "2,2,10,10,4,4")
+ (set_attr "cc" "set_zn,set_znv,set_znv,set_znv,set_znv,set_znv")])
+
;; ----------------------------------------------------------------------
;; TEST INSTRUCTIONS
;; ----------------------------------------------------------------------
+(define_insn ""
+ [(set (cc0) (zero_extract:QI (match_operand:QI 0 "bit_memory_operand" "rU")
+ (const_int 1)
+ (match_operand:QI 1 "const_int_operand" "n")))]
+ ""
+ "btst %Z1,%R0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
+(define_insn ""
+ [(set (cc0) (zero_extract:HI (match_operand:QI 0 "bit_memory_operand" "rU")
+ (const_int 1)
+ (match_operand:QI 1 "const_int_operand" "n")))]
+ ""
+ "btst %Z1,%Y0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
+(define_insn ""
+ [(set (cc0) (zero_extract:SI (match_operand:QI 0 "bit_memory_operand" "rU")
+ (const_int 1)
+ (match_operand:QI 1 "const_int_operand" "n")))]
+ ""
+ "btst %Z1,%Y0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
+(define_insn ""
+ [(set (cc0) (zero_extract:QI (match_operand:HI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 1 "const_int_operand" "n")))]
+ ""
+ "btst %Z1,%R0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
+(define_insn ""
+ [(set (cc0) (zero_extract:HI (match_operand:HI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 1 "const_int_operand" "n")))]
+ ""
+ "btst %Z1,%Y0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
+(define_insn ""
+ [(set (cc0) (zero_extract:SI (match_operand:HI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 1 "const_int_operand" "n")))]
+ ""
+ "btst %Z1,%Y0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
+
(define_insn "tstqi"
- [(set (cc0) (match_operand:QI 0 "register_operand" "ra"))]
+ [(set (cc0) (match_operand:QI 0 "register_operand" "r"))]
""
- "*
-{
- /* ??? I don't think this is right. --Jim */
- if (cc_prev_status.flags & CC_DONE_CBIT)
- return \"btst #0,%X0\";
- else
- return \"cmp.b #0,%X0\";
-}"
- [(set_attr "type" "arith")
- (set_attr "length" "4")
- (set_attr "cc" "set")])
+ "mov.b %X0,%X0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
(define_insn "tsthi"
- [(set (cc0) (match_operand:HI 0 "general_operand" "ra"))]
+ [(set (cc0) (match_operand:HI 0 "register_operand" "r"))]
""
- "*
-{
- /* ??? I don't think this is right. --Jim */
- if (cc_prev_status.flags & CC_DONE_CBIT)
- return \"btst #0,%0l\";
- else
- return \"mov.w %T0,%T0\";
-}"
- [(set_attr "type" "arith")
- (set_attr "length" "4")
- (set_attr "cc" "set")])
+ "mov.w %T0,%T0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
(define_insn "tstsi"
- [(set (cc0) (match_operand:SI 0 "general_operand" "ra"))]
- "TARGET_H8300H"
- "*
-{
- /* ??? I don't think this is right. --Jim */
- if (cc_prev_status.flags & CC_DONE_CBIT)
- return \"btst #0,%0l\";
- else
- return \"mov.l %S0,%S0\";
-}"
- [(set_attr "type" "arith")
- (set_attr "length" "4")
- (set_attr "cc" "set")])
+ [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "mov.l %S0,%S0"
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
(define_insn "cmpqi"
[(set (cc0)
- (compare:QI (match_operand:QI 0 "register_operand" "ra")
- (match_operand:QI 1 "nonmemory_operand" "rai")))]
+ (compare:QI (match_operand:QI 0 "register_operand" "r")
+ (match_operand:QI 1 "nonmemory_operand" "rn")))]
""
"cmp.b %X1,%X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
+ [(set_attr "length" "2")
(set_attr "cc" "compare")])
-;; ??? 300h can have an immediate operand here.
-
-(define_insn "cmphi"
+(define_expand "cmphi"
[(set (cc0)
- (compare:HI (match_operand:HI 0 "register_operand" "ra")
- (match_operand:HI 1 "register_operand" "ra")))]
+ (compare:HI (match_operand:HI 0 "register_operand" "")
+ (match_operand:HI 1 "nonmemory_operand" "")))]
""
+ "
+{
+ /* Force operand1 into a register if we're compiling
+ for the h8/300. */
+ if (GET_CODE (operands[1]) != REG && TARGET_H8300)
+ operands[1] = force_reg (HImode, operands[1]);
+}")
+
+(define_insn ""
+ [(set (cc0)
+ (compare:HI (match_operand:HI 0 "register_operand" "r")
+ (match_operand:HI 1 "register_operand" "r")))]
+ "TARGET_H8300"
"cmp.w %T1,%T0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
+ [(set_attr "length" "2")
(set_attr "cc" "compare")])
-;; ??? 300h can have an immediate operand here.
+(define_insn ""
+ [(set (cc0)
+ (compare:HI (match_operand:HI 0 "register_operand" "r,r")
+ (match_operand:HI 1 "nonmemory_operand" "r,n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "cmp.w %T1,%T0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "compare,compare")])
(define_insn "cmpsi"
[(set (cc0)
- (compare:SI (match_operand:SI 0 "register_operand" "ra")
- (match_operand:SI 1 "register_operand" "ra")))]
- "TARGET_H8300H"
+ (compare:SI (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "r,i")))]
+ "TARGET_H8300H || TARGET_H8300S"
"cmp.l %S1,%S0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "compare")])
-
+ [(set_attr "length" "2,6")
+ (set_attr "cc" "compare,compare")])
+
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
;; ----------------------------------------------------------------------
@@ -489,34 +591,12 @@
(define_insn "addqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(plus:QI (match_operand:QI 1 "register_operand" "%0")
- (match_operand:QI 2 "nonmemory_operand" "ri")))]
+ (match_operand:QI 2 "nonmemory_operand" "rn")))]
""
"add.b %X2,%X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "set")])
-
-;; ??? adds operates on the 32bit register. We can use it because we don't
-;; use the e0-7 registers.
-;; ??? 4 can be handled in one insn on the 300h.
-
-(define_insn "addhi3_internal"
- [(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,ra,r,ra")
- (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:HI 2 "nonmemory_operand" "K,M,L,N,n,ra")))]
- ""
- "@
- adds %T2,%A0
- adds #2,%A0\;adds %C2,%A0
- subs %M2,%A0
- subs #2,%A0\;subs %M2,%A0
- add.b %s2,%s0\;addx %t2,%t0
- add.w %T2,%T0"
- [(set_attr "type" "arith,multi,arith,multi,multi,arith")
- (set_attr "length" "2,4,2,4,4,2")
- (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,clobber,set")])
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
-;; ??? Why is this here?
(define_expand "addhi3"
[(set (match_operand:HI 0 "register_operand" "")
(plus:HI (match_operand:HI 1 "register_operand" "")
@@ -524,6 +604,44 @@
""
"")
+;; Specialized version using adds/subs. This must come before
+;; the more general patterns below.
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0")
+ (match_operand:HI 2 "adds_subs_operand" "n")))]
+ ""
+ "* return output_adds_subs (operands);"
+ [(set_attr "cc" "none_0hit")
+ (set (attr "length")
+ (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
+ (const_int 0))
+ (const_int 2)
+ (const_int 4)))])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=&r,r,&r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0,g")
+ (match_operand:HI 2 "nonmemory_operand" "n,r,r")))]
+ "TARGET_H8300"
+ "@
+ add.b %s2,%s0\;addx %t2,%t0
+ add.w %T2,%T0
+ mov.w %T1,%T0\;add.w %T2,%T0"
+ [(set_attr "length" "4,2,6")
+ (set_attr "cc" "clobber,set_zn,set_zn")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (plus:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "n,r")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "@
+ add.w %T2,%T0
+ add.w %T2,%T0"
+ [(set_attr "length" "4,2")
+ (set_attr "cc" "set_zn,set_zn")])
+
(define_expand "addsi3"
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_operand:SI 1 "register_operand" "")
@@ -531,6 +649,21 @@
""
"")
+;; Specialized version using adds/subs. This must come before
+;; the more general patterns below.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "adds_subs_operand" "n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "* return output_adds_subs (operands);"
+ [(set_attr "cc" "none_0hit")
+ (set (attr "length")
+ (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
+ (const_int 0))
+ (const_int 2)
+ (const_int 4)))])
+
(define_insn "addsi_h8300"
[(set (match_operand:SI 0 "register_operand" "=r,r,&r")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,r")
@@ -539,30 +672,20 @@
"@
add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0
- mov %f1,%f0\;mov %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
- [(set_attr "type" "arith")
- (set_attr "length" "8,6,20")
+ mov.w %f1,%f0\;mov.w %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
+ [(set_attr "length" "8,6,10")
(set_attr "cc" "clobber")])
-;; ??? 4 can be handled in one insn on the 300h.
-;; ??? Should the 'n' constraint be 'i' here?
-;; ??? We don't handle (reg + symbol_ref) which the 300h can handle.
-
(define_insn "addsi_h8300h"
- [(set (match_operand:SI 0 "register_operand" "=ra,ra,ra,ra,r,ra")
- (plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,0")
- (match_operand:SI 2 "nonmemory_operand" "K,M,L,N,n,ra")))]
- "TARGET_H8300H"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "i,r")))]
+ "TARGET_H8300H || TARGET_H8300S"
"@
- adds %S2,%S0
- adds #2,%S0\;adds %C2,%S0
- subs %M2,%S0
- subs #2,%S0\;subs %M2,%S0
add.l %S2,%S0
add.l %S2,%S0"
- [(set_attr "type" "multi,multi,multi,multi,arith,arith")
- (set_attr "length" "2,4,2,4,6,2")
- (set_attr "cc" "none_0hit,none_0hit,none_0hit,none_0hit,clobber,clobber")])
+ [(set_attr "length" "6,2")
+ (set_attr "cc" "set_zn,set_zn")])
;; ----------------------------------------------------------------------
;; SUBTRACT INSTRUCTIONS
@@ -571,43 +694,63 @@
(define_insn "subqi3"
[(set (match_operand:QI 0 "register_operand" "=r,r")
(minus:QI (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "r,i")))]
+ (match_operand:QI 2 "nonmemory_operand" "r,n")))]
""
"@
sub.b %X2,%X0
add.b %G2,%X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "set")])
-
-;; ??? subs operates on the 32bit register. We can use it because we don't
-;; use the e0-7 registers.
-;; ??? 4 can be handled in one insn on the 300h.
-;; ??? The fourth alternative can use sub.w on the 300h.
-;; ??? Should the 'n' constraint be an 'i' here?
-
-(define_insn "subhi3_internal"
- [(set (match_operand:HI 0 "register_operand" "=ra,ra,ra,r")
- (minus:HI (match_operand:HI 1 "general_operand" "0,0,0,0")
- (match_operand:HI 2 "nonmemory_operand" "K,M,ra,n")))]
- ""
- "@
- subs %T2,%T0
- subs #2,%T0\;subs %M2,%T0
- sub.w %T2,%T0
- add.b %E2,%s0\;addx %F2,%t0 ; -%0"
- [(set_attr "type" "multi")
- (set_attr "length" "2,4,2,4")
- (set_attr "cc" "none_0hit,none_0hit,set,clobber")])
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
-;; ??? Why is this here?
(define_expand "subhi3"
[(set (match_operand:HI 0 "register_operand" "")
- (minus:HI (match_operand:HI 1 "register_operand" "")
+ (minus:HI (match_operand:HI 1 "general_operand" "")
(match_operand:HI 2 "nonmemory_operand" "")))]
""
"")
+;; Specialized version using adds/subs. This must come before
+;; the more general patterns below. This may not be needed
+;; due to instruction canonicalization.
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (minus:HI (match_operand:HI 1 "register_operand" "r")
+ (match_operand:HI 2 "adds_subs_operand" "n")))]
+ ""
+ "*
+{
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ return output_adds_subs (operands);
+}"
+ [(set_attr "cc" "none_0hit")
+ (set (attr "length")
+ (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
+ (const_int 0))
+ (const_int 2)
+ (const_int 4)))])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,&r")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0")
+ (match_operand:HI 2 "nonmemory_operand" "r,n")))]
+ "TARGET_H8300"
+ "@
+ sub.w %T2,%T0
+ add.b %E2,%s0\;addx %F2,%t0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_zn,clobber")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,&r")
+ (minus:HI (match_operand:HI 1 "general_operand" "0,0")
+ (match_operand:HI 2 "nonmemory_operand" "r,n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "@
+ sub.w %T2,%T0
+ sub.w %T2,%T0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_zn,set_zn")])
+
(define_expand "subsi3"
[(set (match_operand:SI 0 "register_operand" "")
(minus:SI (match_operand:SI 1 "register_operand" "")
@@ -621,26 +764,40 @@
(match_operand:SI 2 "register_operand" "r")))]
"TARGET_H8300"
"sub.w %f2,%f0\;subx %y2,%y0\;subx %z2,%z0"
- [(set_attr "type" "arith")
- (set_attr "length" "6")
+ [(set_attr "length" "6")
(set_attr "cc" "clobber")])
-;; ??? 4 can be handled in one insn on the 300h.
+;; Specialized version using adds/subs. This must come before
+;; the more general patterns below. This may not be needed
+;; due to instruction canonicalization.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "general_operand" "0")
+ (match_operand:SI 2 "adds_subs_operand" "n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "*
+{
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
+ return output_adds_subs (operands);
+}"
+ [(set_attr "cc" "none_0hit")
+ (set (attr "length")
+ (if_then_else (ne (match_operand:HI 2 "one_insn_adds_subs_operand" "")
+ (const_int 0))
+ (const_int 2)
+ (const_int 4)))])
(define_insn "subsi3_h8300h"
- [(set (match_operand:SI 0 "register_operand" "=ra,ra,ra,r")
- (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
- (match_operand:SI 2 "nonmemory_operand" "K,M,ra,n")))]
- "TARGET_H8300H"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,i")))]
+ "TARGET_H8300H || TARGET_H8300S"
"@
- subs %T2,%T0
- subs #2,%T0\;subs %E2,%T0
sub.l %S2,%S0
sub.l %S2,%S0"
- [(set_attr "type" "multi")
- (set_attr "length" "2,4,2,6")
- (set_attr "cc" "none_0hit,none_0hit,set,set")])
-
+ [(set_attr "length" "2,6")
+ (set_attr "cc" "set_zn,set_zn")])
+
;; ----------------------------------------------------------------------
;; MULTIPLY INSTRUCTIONS
;; ----------------------------------------------------------------------
@@ -651,21 +808,19 @@
[(set (match_operand:HI 0 "register_operand" "=r")
(mult:HI (sign_extend:HI (match_operand:QI 1 "general_operand" "%0"))
(sign_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
- "TARGET_H8300H"
+ "TARGET_H8300H || TARGET_H8300S"
"mulxs.b %X2,%T0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "set")])
+ [(set_attr "length" "4")
+ (set_attr "cc" "set_zn")])
(define_insn "mulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (sign_extend:SI (match_operand:HI 1 "general_operand" "%0"))
(sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
- "TARGET_H8300H"
+ "TARGET_H8300H || TARGET_H8300S"
"mulxs.w %T2,%S0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "set")])
+ [(set_attr "length" "4")
+ (set_attr "cc" "set_zn")])
(define_insn "umulqihi3"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -673,18 +828,48 @@
(zero_extend:HI (match_operand:QI 2 "register_operand" "r"))))]
""
"mulxu %X2,%T0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")
+ [(set_attr "length" "2")
(set_attr "cc" "none_0hit")])
(define_insn "umulhisi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "%0"))
(zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
- "TARGET_H8300H"
+ "TARGET_H8300H || TARGET_H8300S"
"mulxu.w %T2,%S0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")
+ [(set_attr "length" "2")
+ (set_attr "cc" "none_0hit")])
+
+;; This is a "bridge" instruction. Combine can't cram enough insns
+;; together to crate a MAC instruction directly, but it can create
+;; this instruction, which then allows combine to create the real
+;; MAC insn.
+;;
+;; Unfortunately, if combine doesn't create a MAC instruction, this
+;; insn must generate reasonably correct code. Egad.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (mult:SI
+ (sign_extend:SI
+ (mem:HI (post_inc:SI (match_operand:SI 1 "register_operand" "r"))))
+ (sign_extend:SI
+ (mem:HI (post_inc:SI (match_operand:SI 2 "register_operand" "r"))))))]
+ "TARGET_H8300S"
+ "clrmac\;mac %2,%1"
+ [(set_attr "length" "6")
+ (set_attr "cc" "none_0hit")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (plus (mult:SI
+ (sign_extend:SI (mem:HI
+ (post_inc:SI (match_operand:SI 1 "register_operand" "r"))))
+ (sign_extend:SI (mem:HI
+ (post_inc:SI (match_operand:SI 2 "register_operand" "r")))))
+ (match_operand:SI 3 "register_operand" "0")))]
+ "TARGET_H8300S"
+ "mac %2,%1"
+ [(set_attr "length" "4")
(set_attr "cc" "none_0hit")])
;; ----------------------------------------------------------------------
@@ -693,44 +878,48 @@
(define_insn "udivqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (udiv:QI (match_operand:HI 1 "general_operand" "0")
- (match_operand:QI 2 "register_operand" "r")))]
+ (truncate:QI
+ (udiv:HI
+ (match_operand:HI 1 "general_operand" "0")
+ (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))))]
""
"divxu %X2,%T0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")
+ [(set_attr "length" "2")
(set_attr "cc" "clobber")])
;; ??? Will divxu always work here?
(define_insn "divqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (div:QI (match_operand:HI 1 "general_operand" "0")
- (match_operand:QI 2 "register_operand" "r")))]
+ (truncate:QI
+ (div:HI
+ (match_operand:HI 1 "general_operand" "0")
+ (sign_extend:HI (match_operand:QI 2 "register_operand" "r")))))]
""
"divxu %X2,%T0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")
+ [(set_attr "length" "2")
(set_attr "cc" "clobber")])
(define_insn "udivhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (udiv:HI (match_operand:SI 1 "general_operand" "0")
- (match_operand:HI 2 "register_operand" "r")))]
- "TARGET_H8300H"
+ (truncate:HI
+ (udiv:SI
+ (match_operand:SI 1 "general_operand" "0")
+ (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))))]
+ "TARGET_H8300H || TARGET_H8300S"
"divxu.w %T2,%S0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")
+ [(set_attr "length" "2")
(set_attr "cc" "clobber")])
(define_insn "divhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (div:HI (match_operand:SI 1 "general_operand" "0")
- (match_operand:HI 2 "register_operand" "r")))]
- "TARGET_H8300H"
+ (truncate:HI
+ (div:SI
+ (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))))]
+ "TARGET_H8300H || TARGET_H8300S"
"divxs.w %T2,%S0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
+ [(set_attr "length" "4")
(set_attr "cc" "clobber")])
;; ----------------------------------------------------------------------
@@ -739,64 +928,67 @@
(define_insn "umodqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (umod:QI (match_operand:HI 1 "general_operand" "0")
- (match_operand:QI 2 "register_operand" "r")))]
+ (truncate:QI
+ (umod:HI
+ (match_operand:HI 1 "general_operand" "0")
+ (zero_extend:HI (match_operand:QI 2 "register_operand" "r")))))]
""
"divxu %X2,%T0\;mov %t0,%s0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
+ [(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "modqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
- (mod:QI (match_operand:HI 1 "general_operand" "0")
- (match_operand:QI 2 "register_operand" "r")))]
- "TARGET_H8300H"
+ (truncate:QI
+ (mod:HI
+ (match_operand:HI 1 "general_operand" "0")
+ (sign_extend:HI (match_operand:QI 2 "register_operand" "r")))))]
+ "TARGET_H8300H || TARGET_H8300S"
"divxs.b %X2,%T0\;mov %t0,%s0"
- [(set_attr "type" "multi")
- (set_attr "length" "6")
+ [(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_insn "umodhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (umod:HI (match_operand:SI 1 "general_operand" "0")
- (match_operand:HI 2 "register_operand" "r")))]
- "TARGET_H8300H"
+ (truncate:HI
+ (umod:SI
+ (match_operand:SI 1 "general_operand" "0")
+ (zero_extend:SI (match_operand:HI 2 "register_operand" "r")))))]
+ "TARGET_H8300H || TARGET_H8300S"
"divxu.w %T2,%S0\;mov %e0,%f0"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
+ [(set_attr "length" "4")
(set_attr "cc" "clobber")])
(define_insn "modhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
- (mod:HI (match_operand:SI 1 "general_operand" "0")
- (match_operand:HI 2 "register_operand" "r")))]
- "TARGET_H8300H"
+ (truncate:HI
+ (mod:SI
+ (match_operand:SI 1 "general_operand" "0")
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))))]
+ "TARGET_H8300H || TARGET_H8300S"
"divxs.w %T2,%S0\;mov %e0,%f0"
- [(set_attr "type" "multi")
- (set_attr "length" "6")
+ [(set_attr "length" "6")
(set_attr "cc" "clobber")])
-
+
;; ----------------------------------------------------------------------
;; AND INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "andqi3_internal"
+(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(and:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,O")))]
"register_operand (operands[0], QImode) || o_operand (operands[2], QImode)"
"@
and %X2,%X0
- bclr %W2,%X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2,4")
- (set_attr "cc" "set,none_0hit")])
+ bclr %W2,%R0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_znv,none_0hit")])
(define_expand "andqi3"
- [(set (match_operand:QI 0 "bit_operand" "=r,U")
- (and:QI (match_operand:QI 1 "bit_operand" "%0,0")
- (match_operand:QI 2 "nonmemory_operand" "rn,O")))]
+ [(set (match_operand:QI 0 "bit_operand" "")
+ (and:QI (match_operand:QI 1 "bit_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
"
{
@@ -804,8 +996,6 @@
DONE;
}")
-;; ??? Should have a bclr case here also.
-
(define_insn "andhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(and:HI (match_operand:HI 1 "register_operand" "%0")
@@ -816,47 +1006,88 @@
if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
+
if ((i & 0x00ff) != 0x00ff)
output_asm_insn (\"and %s2,%s0\", operands);
if ((i & 0xff00) != 0xff00)
output_asm_insn (\"and %t2,%t0\", operands);
return \"\";
}
+ if (TARGET_H8300H || TARGET_H8300S)
+ return \"and.w %T2,%T0\";
return \"and %s2,%s0\;and %t2,%t0;\";
}"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
+ [(set_attr "length" "4")
(set_attr "cc" "clobber")])
-;; ??? There is an iorsi3 for TARGET_H8300. Should we have andsi3?
-
(define_insn "andsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (and:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "nonmemory_operand" "r,i")))]
- "TARGET_H8300H"
- "@
- and %S2,%S0
- and %S2,%S0"
- [(set_attr "type" "arith")
- (set_attr "length" "4,6")
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "nonmemory_operand" "rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+ int upper_cleared, lower_cleared;
+
+ /* The h8300h can't do byte-wise operations on the
+ upper 16bits of 32bit registers. However, if
+ those bits aren't going to change, or they're
+ going to be zero'd out, then we can work on the
+ low-order bits. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && ((i & 0xffff0000) != 0xffff0000
+ || (i & 0xffff0000) == 0x00000000))
+ return \"and.l %S2,%S0\";
+
+ lower_cleared = 0;
+ if ((i & 0x0000ffff) == 0x00000000)
+ {
+ output_asm_insn (\"sub.w %f0,%f0\", operands);
+ lower_cleared = 1;
+ }
+
+ upper_cleared = 0;
+ if ((i & 0xffff0000) == 0x00000000)
+ {
+ output_asm_insn (\"sub.w %e0,%e0\", operands);
+ upper_cleared = 1;
+ }
+
+ if ((i & 0x000000ff) != 0x000000ff && !lower_cleared)
+ output_asm_insn (\"and %w2,%w0\", operands);
+ if ((i & 0x0000ff00) != 0x0000ff00 && !lower_cleared)
+ output_asm_insn (\"and %x2,%x0\", operands);
+ if ((i & 0x00ff0000) != 0x00ff0000 && !upper_cleared)
+ output_asm_insn (\"and %y2,%y0\", operands);
+ if ((i & 0xff000000) != 0xff000000 && !upper_cleared)
+ output_asm_insn (\"and %z2,%z0\", operands);
+ return \"\";
+ }
+ if (TARGET_H8300H || TARGET_H8300S)
+ return \"and.l %S2,%S0\";
+ return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\;\";
+}"
+ [(set_attr "length" "8")
(set_attr "cc" "clobber")])
+
;; ----------------------------------------------------------------------
;; OR INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "iorqi3_internal"
- [(set (match_operand:QI 0 "bit_operand" "=U,r")
+(define_insn ""
+ [(set (match_operand:QI 0 "bit_operand" "=r,U")
(ior:QI (match_operand:QI 1 "bit_operand" "%0,0")
- (match_operand:QI 2 "nonmemory_operand" "P,rn")))]
+ (match_operand:QI 2 "nonmemory_operand" "rn,P")))]
"register_operand (operands[0], QImode) || p_operand (operands[2], QImode)"
"@
- bset %V2,%X0
- or %X2,%X0"
- [(set_attr "type" "arith")
- (set_attr "length" "4,2")
- (set_attr "cc" "none_0hit,set")])
+ or %X2,%X0
+ bset %V2,%R0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_znv,none_0hit")])
(define_expand "iorqi3"
[(set (match_operand:QI 0 "bit_operand" "=r,U")
@@ -869,8 +1100,6 @@
DONE;
}")
-;; ??? Should have a bset case here also.
-
(define_insn "iorhi3"
[(set (match_operand:HI 0 "general_operand" "=r,r")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
@@ -878,76 +1107,73 @@
""
"*
{
- if (TARGET_H8300)
- {
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int i = INTVAL (operands[2]);
- if ((i & 0x00ff) != 0)
- output_asm_insn (\"or %s2,%s0\", operands);
- if ((i & 0xff00) != 0)
- output_asm_insn (\"or %t2,%t0\", operands);
- return \"\";
- }
- return \"or %s2,%s0\;or %t2,%t0; %2 or2\";
- }
- else
+ if (GET_CODE (operands[2]) == CONST_INT)
{
- return \"or %S2,%S0\";
+ int i = INTVAL (operands[2]);
+
+ if ((i & 0x00ff) != 0)
+ output_asm_insn (\"or %s2,%s0\", operands);
+ if ((i & 0xff00) != 0)
+ output_asm_insn (\"or %t2,%t0\", operands);
+ return \"\";
}
+ if (TARGET_H8300H || TARGET_H8300S)
+ return \"or.w %T2,%T0\";
+ return \"or %s2,%s0\;or %t2,%t0; %2 or2\";
}"
- [(set_attr "type" "multi")
- (set_attr "length" "2,4")
+ [(set_attr "length" "2,4")
(set_attr "cc" "clobber,clobber")])
(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (ior:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "nonmemory_operand" "ri")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "J,rn")))]
""
"*
{
- if (TARGET_H8300)
- {
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- int i = INTVAL (operands[2]);
- if ((i & 0x000000ff) != 0)
- output_asm_insn (\"or %w2,%w0\", operands);
- if ((i & 0x0000ff00) != 0)
- output_asm_insn (\"or %x2,%x0\", operands);
- if ((i & 0x00ff0000) != 0)
- output_asm_insn (\"or %y2,%y0\", operands);
- if ((i & 0xff000000) != 0)
- output_asm_insn (\"or %z2,%z0\", operands);
- return \"\";
- }
- return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\;\";
- }
- else
+ if (GET_CODE (operands[2]) == CONST_INT)
{
- return \"or %S2,%S0\";
+ int i = INTVAL (operands[2]);
+
+ /* The h8300h can't do byte-wise operations on the
+ upper 16bits of 32bit registers. However, if
+ those bits aren't going to change, then we can
+ work on the low-order bits. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && (i & 0xffff0000) != 0x00000000)
+ return \"or.l %S2,%S0\";
+
+ if ((i & 0x000000ff) != 0)
+ output_asm_insn (\"or %w2,%w0\", operands);
+ if ((i & 0x0000ff00) != 0)
+ output_asm_insn (\"or %x2,%x0\", operands);
+ if ((i & 0x00ff0000) != 0)
+ output_asm_insn (\"or %y2,%y0\", operands);
+ if ((i & 0xff000000) != 0)
+ output_asm_insn (\"or %z2,%z0\", operands);
+ return \"\";
}
+ if (TARGET_H8300H || TARGET_H8300S)
+ return \"or.l %S2,%S0\";
+ return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\;\";
}"
- [(set_attr "type" "multi")
- (set_attr "length" "8")
- (set_attr "cc" "clobber")])
+ [(set_attr "length" "2,8")
+ (set_attr "cc" "clobber,clobber")])
;; ----------------------------------------------------------------------
;; XOR INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "xorqi3_internal"
+(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(xor:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,P")))]
"register_operand (operands[0], QImode) || p_operand (operands[2], QImode)"
"@
xor %X2,%X0
- bnot %V2,%X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2,4")
- (set_attr "cc" "set,none_0hit")])
+ bnot %V2,%R0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_znv,none_0hit")])
(define_expand "xorqi3"
[(set (match_operand:QI 0 "bit_operand" "=r,U")
@@ -961,35 +1187,65 @@
}")
(define_insn "xorhi3"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (xor:HI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "nonmemory_operand" "rn")))]
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "J,rn")))]
""
"*
{
- if (TARGET_H8300)
- return \"xor %s2,%s0\;xor %t2,%t0\";
- else
- return \"xor %S2,%S0\";
-}"
- [(set_attr "type" "multi")
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
-;; ??? There is an iorsi3 for TARGET_H8300. Should we have xorsi3?
+ if ((i & 0x00ff) != 0)
+ output_asm_insn (\"xor %s2,%s0\", operands);
+ if ((i & 0xff00) != 0)
+ output_asm_insn (\"xor %t2,%t0\", operands);
+ return \"\";
+ }
+ if (TARGET_H8300H || TARGET_H8300S)
+ return \"xor.w %T2,%T0\";
+ return \"xor %s2,%s0\;xor %t2,%t0\";
+}"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "clobber,clobber")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "nonmemory_operand" "r,i")))]
- "TARGET_H8300H"
- "@
- xor %S2,%S0
- xor %S2,%S0"
- [(set_attr "type" "arith")
- (set_attr "length" "4,6")
- (set_attr "cc" "clobber")])
+ (match_operand:SI 2 "nonmemory_operand" "J,rn")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ int i = INTVAL (operands[2]);
+ /* The h8300h can't do byte-wise operations on the
+ upper 16bits of 32bit registers. However, if
+ those bits aren't going to change, then we can
+ work on the low-order bits. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && (i & 0xffff0000) != 0x00000000)
+ return \"xor.l %S2,%S0\";
+
+ if ((i & 0x000000ff) != 0)
+ output_asm_insn (\"xor %w2,%w0\", operands);
+ if ((i & 0x0000ff00) != 0)
+ output_asm_insn (\"xor %x2,%x0\", operands);
+ if ((i & 0x00ff0000) != 0)
+ output_asm_insn (\"xor %y2,%y0\", operands);
+ if ((i & 0xff000000) != 0)
+ output_asm_insn (\"xor %z2,%z0\", operands);
+ return \"\";
+ }
+ if (TARGET_H8300H || TARGET_H8300S)
+ return \"xor.l %S2,%S0\";
+ return \"xor %w2,%w0\;xor %x2,%x0\;xor %y2,%y0\;xor %z2,%z0\;\";
+}"
+ [(set_attr "length" "2,8")
+ (set_attr "cc" "clobber,clobber")])
+
;; ----------------------------------------------------------------------
;; NEGATION INSTRUCTIONS
;; ----------------------------------------------------------------------
@@ -999,9 +1255,8 @@
(neg:QI (match_operand:QI 1 "general_operand" "0")))]
""
"neg %X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "clobber")])
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
(define_expand "neghi2"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1028,11 +1283,10 @@
(define_insn "neghi2_h8300h"
[(set (match_operand:HI 0 "register_operand" "=r")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
- "TARGET_H8300H"
+ "TARGET_H8300H || TARGET_H8300S"
"neg %T0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "clobber")])
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
(define_expand "negsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1059,11 +1313,10 @@
(define_insn "negsi2_h8300h"
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
- "TARGET_H8300H"
+ "TARGET_H8300H || TARGET_H8300S"
"neg %S0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "clobber")])
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_zn")])
;; ----------------------------------------------------------------------
;; NOT INSTRUCTIONS
@@ -1074,9 +1327,8 @@
(not:QI (match_operand:QI 1 "general_operand" "0")))]
""
"not %X0"
- [(set_attr "type" "arith")
- (set_attr "length" "2")
- (set_attr "cc" "set")])
+ [(set_attr "length" "2")
+ (set_attr "cc" "set_znv")])
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "register_operand" "=r")
@@ -1089,9 +1341,12 @@
else
return \"not %T0\";
}"
- [(set_attr "type" "arith")
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 4)
+ (const_int 2)))])
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -1104,11 +1359,14 @@
else
return \"not %S0\";
}"
- [(set_attr "type" "arith")
-;; ??? length is wrong for 300h
- (set_attr "length" "8")
- (set_attr "cc" "clobber")])
-
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 8)
+ (const_int 2)))])
+
+
;; ----------------------------------------------------------------------
;; JUMP INSTRUCTIONS
;; ----------------------------------------------------------------------
@@ -1214,6 +1472,16 @@
""
"*
{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
+ && (GET_CODE (operands[1]) == GT
+ || GET_CODE (operands[1]) == GE
+ || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == LT))
+ {
+ cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+ return 0;
+ }
+
if (get_attr_length (insn) == 2)
return \"b%j1 %l0\";
else if (get_attr_length (insn) == 4)
@@ -1231,9 +1499,18 @@
(pc)
(label_ref (match_operand 0 "" ""))))]
""
-;; ??? We don't take advantage of 16 bit relative jumps in the 300h.
"*
{
+ if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
+ && (GET_CODE (operands[1]) == GT
+ || GET_CODE (operands[1]) == GE
+ || GET_CODE (operands[1]) == LE
+ || GET_CODE (operands[1]) == LT))
+ {
+ cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
+ return 0;
+ }
+
if (get_attr_length (insn) == 2)
return \"b%k1 %l0\";
else if (get_attr_length (insn) == 4)
@@ -1275,52 +1552,36 @@
(use (label_ref (match_operand 1 "" "")))]
"TARGET_H8300"
"jmp @%0"
- [(set_attr "type" "branch")
- (set_attr "cc" "none")
+ [(set_attr "cc" "none")
(set_attr "length" "2")])
(define_insn "tablejump_h8300h"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
- "TARGET_H8300H"
+ "TARGET_H8300H || TARGET_H8300S"
"jmp @%0"
- [(set_attr "type" "branch")
- (set_attr "cc" "none")
+ [(set_attr "cc" "none")
(set_attr "length" "2")])
;; This is a define expand, because pointers may be either 16 or 32 bits.
-;(define_insn "indirect_jump"
-; [(set (pc) (match_operand:HI 0 "register_operand" "r"))]
-; ""
-; "jmp @%0"
-; [(set_attr "type" "branch")
-; (set_attr "cc" "none")
-; (set_attr "length" "2")])
-
(define_expand "indirect_jump"
- [(set (pc) (match_operand 0 "jump_address_operand" "Vr"))]
+ [(set (pc) (match_operand 0 "jump_address_operand" ""))]
""
"")
(define_insn "indirect_jump_h8300"
- [(set (pc) (match_operand:HI 0 "jump_address_operand" "V,r"))]
+ [(set (pc) (match_operand:HI 0 "jump_address_operand" "Vr"))]
"TARGET_H8300"
- "@
- jmp @%0
- jmp @%0"
- [(set_attr "type" "branch")
- (set_attr "cc" "none")
+ "jmp @%0"
+ [(set_attr "cc" "none")
(set_attr "length" "2")])
(define_insn "indirect_jump_h8300h"
- [(set (pc) (match_operand:SI 0 "jump_address_operand" "V,r"))]
- "TARGET_H8300H"
- "@
- jmp @%0
- jmp @%0"
- [(set_attr "type" "branch")
- (set_attr "cc" "none")
+ [(set (pc) (match_operand:SI 0 "jump_address_operand" "Vr"))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "jmp @%0"
+ [(set_attr "cc" "none")
(set_attr "length" "2")])
;; Call subroutine with no return value.
@@ -1331,10 +1592,19 @@
[(call (match_operand:QI 0 "call_insn_operand" "or")
(match_operand:HI 1 "general_operand" "g"))]
""
- "jsr %0"
- [(set_attr "type" "call")
- (set_attr "cc" "clobber")
- (set_attr "length" "4")])
+ "*
+{
+ if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF
+ && SYMBOL_REF_FLAG (XEXP (operands[0], 0)))
+ return \"jsr\\t\@%0:8\";
+ else
+ return \"jsr\\t%0\";
+}"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (match_operand:QI 0 "small_call_insn_operand" "")
+ (const_int 4)
+ (const_int 8)))])
;; Call subroutine, returning value in operand 0
;; (which must be a hard register).
@@ -1346,92 +1616,134 @@
(call (match_operand:QI 1 "call_insn_operand" "or")
(match_operand:HI 2 "general_operand" "g")))]
""
- "jsr %1"
- [(set_attr "type" "call")
- (set_attr "cc" "clobber")
- (set_attr "length" "4")])
+ "*
+{
+ if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
+ && SYMBOL_REF_FLAG (XEXP (operands[1], 0)))
+ return \"jsr\\t\@%1:8\";
+ else
+ return \"jsr\\t%1\";
+}"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (match_operand:QI 0 "small_call_insn_operand" "")
+ (const_int 4)
+ (const_int 8)))])
(define_insn "nop"
[(const_int 0)]
""
"nop"
- [(set_attr "type" "multi")
- (set_attr "cc" "none")
+ [(set_attr "cc" "none")
(set_attr "length" "2")])
-
+
;; ----------------------------------------------------------------------
;; EXTEND INSTRUCTIONS
;; ----------------------------------------------------------------------
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r,r")
- (zero_extend:HI (match_operand:QI 1 "general_operand" "0,g")))]
+ (zero_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))]
""
- "*
-{
- if (which_alternative==0)
- return \"mov.b #0,%t0\";
-
- if (TARGET_H8300)
- return \"mov.b %X1,%s0\;mov.b #0,%t0\";
- else
- {
- /* ??? See how often this gets optimized. */
- if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
- return \"extu.w %T0\";
- else
- return \"mov.b %X1,%s0\;extu.w %T0\";
- }
-}"
- [(set_attr "type" "multi")
-;; ??? This length is wrong for one case.
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
+ "@
+ mov.b #0,%t0
+ mov.b %R1,%s0\;mov.b #0,%t0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "clobber,clobber")])
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (zero_extend:SI (match_operand:HI 1 "general_operand" "g")))]
- "TARGET_H8300H"
- "*
-{
- /* ??? See how often this gets optimized. */
- if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
- return \"extu.l %S0\";
- else
- return \"mov.w %T1,%T0\;extu.l %S0\";
-}"
- [(set_attr "type" "multi")
-;; ??? This length is wrong for one case.
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
+;; The compiler can synthesize a 300H variant of this which is
+;; just as efficient as one that we'd create
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:QI 1 "general_operand_src" "0,g>")))]
+ "TARGET_H8300"
+ "@
+ mov.b #0,%x0\;sub.w %e0,%e0
+ mov.b %R1,%w0\;mov.b #0,%x0\;sub.w %e0,%e0"
+ [(set_attr "length" "4,6")
+ (set_attr "cc" "clobber,clobber")])
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))]
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:HI 1 "general_operand" "")))]
""
- "*
+ "
{
- if (TARGET_H8300)
+ if (TARGET_H8300
+ && GET_CODE (operands[1]) != CONST_INT
+ && !optimize)
{
- /* ??? See how often this gets optimized. */
- if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
- return \"bld #7,%s0\;subx %t0,%t0\";
- else
- return \"mov.b %X1,%s0\;bld #7,%s0\;subx %t0,%t0\";
- }
- else
- {
- /* ??? See how often this gets optimized. */
- if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
- return \"exts.w %T0\";
- else
- return \"mov.b %X1,%s0\;exts.w %T0\";
+ emit_insn (gen_zero_extendhisi2_h8300 (operands[0], operands[1]));
+ DONE;
}
-}"
- [(set_attr "type" "multi")
-;; ??? Length is wrong in some cases.
- (set_attr "length" "6")
- (set_attr "cc" "clobber")])
+}")
+
+;; This is used when not optimizing. It avoids severe code explosion
+;; due to poor register allocation.
+(define_expand "zero_extendhisi2_h8300"
+ [(set (reg:HI 1) (match_operand:HI 1 "general_operand" ""))
+ (set (reg:SI 0) (zero_extend:SI (reg:HI 1)))
+ (set (match_operand:SI 0 "general_operand" "" ) (reg:SI 0))]
+ "TARGET_H8300"
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "general_operand_src" "0,g>")))]
+ "TARGET_H8300"
+ "@
+ sub.w %e0,%e0
+ mov.w %e1,%f0\;sub.w %e0,%e0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "clobber,clobber")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "general_operand_src" "0,g>")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "@
+ extu.l %S0
+ mov.w %T1,%T0\;extu.l %S0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_znv,set_znv")])
+
+(define_expand "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (sign_extend:HI (match_operand:QI 1 "general_operand" "")))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (sign_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))]
+ "TARGET_H8300"
+ "@
+ bld #7,%s0\;subx %t0,%t0
+ mov.b %R1,%s0\;bld #7,%s0\;subx %t0,%t0"
+ [(set_attr "length" "4,6")
+ (set_attr "cc" "clobber,clobber")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (sign_extend:HI (match_operand:QI 1 "general_operand_src" "0,g>")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "@
+ exts.w %T0
+ mov.b %R1,%s0\;exts.w %T0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_znv,set_znv")])
+
+;; The compiler can synthesize a 300H variant of this which is
+;; just as efficient as one that we'd create
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:QI 1 "general_operand_src" "0,g>")))]
+ "TARGET_H8300"
+ "@
+ bld #7,%w0\;subx %x0,%x0\;subx %y0,%y0\;subx %z0,%z0
+ mov.b %R1,%w0\;bld #7,%w0\;subx %x0,%x0\;subx %y0,%y0\;subx %z0,%z0"
+ [(set_attr "length" "8,10")
+ (set_attr "cc" "clobber,clobber")])
(define_expand "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -1439,13 +1751,17 @@
""
"
{
- if (TARGET_H8300)
- emit_insn (gen_extendhisi2_h8300 (operands[0], operands[1]));
- else
- emit_insn (gen_extendhisi2_h8300h (operands[0], operands[1]));
- DONE;
+ if (TARGET_H8300
+ && GET_CODE (operands[1]) != CONST_INT
+ && !optimize)
+ {
+ emit_insn (gen_extendhisi2_h8300 (operands[0], operands[1]));
+ DONE;
+ }
}")
+;; This is used when not optimizing. It avoids severe code explosion
+;; due to poor register allocation.
(define_expand "extendhisi2_h8300"
[(set (reg:HI 1) (match_operand:HI 1 "general_operand" ""))
(set (reg:SI 0) (sign_extend:SI (reg:HI 1)))
@@ -1453,35 +1769,26 @@
"TARGET_H8300"
"")
-(define_expand "extendhisi2_h8300h"
- [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "general_operand" "")))]
- "TARGET_H8300H"
- "")
-
-(define_insn "extendhisi2_h8300_internal"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_operand:HI 1 "register_operand" "0")))]
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "general_operand_src" "0,g>")))]
"TARGET_H8300"
- "mov.w %T1,%f0\;bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0"
- [(set_attr "length" "10")
- (set_attr "cc" "clobber")])
-
-(define_insn "extendhisi2_h8300h_internal"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))]
- "TARGET_H8300H"
- "*
-{
- /* ??? See how often this gets optimized. */
- if (REG_P (operands[1]) && (REGNO (operands[1]) == REGNO (operands[0])))
- return \"exts.l %S0\";
- else
- return \"mov.w %T1,%T0\;exts.l %S0\";
-}"
- [(set_attr "length" "10")
- (set_attr "cc" "clobber")])
+ "@
+ bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0
+ mov.w %T1,%f0\;bld #7,%x0\;subx %y0,%y0\;subx %z0,%z0"
+ [(set_attr "length" "6,8")
+ (set_attr "cc" "clobber,clobber")])
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "general_operand_src" "0,g>")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "@
+ exts.l %S0
+ mov.w %T1,%T0\;exts.l %S0"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_znv,set_znv")])
+
;; ----------------------------------------------------------------------
;; SHIFTS
;; ----------------------------------------------------------------------
@@ -1524,22 +1831,15 @@
""
"if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_QI"
+(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r")
(match_operator:QI 3 "nshift_operator"
[ (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "KM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
- [(set_attr "type" "arith")
- (set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
+ [(set_attr "length" "20")
(set_attr "cc" "clobber")])
;; HI BIT SHIFTS
@@ -1553,7 +1853,7 @@
(define_expand "lshrhi3"
[(set (match_operand:HI 0 "register_operand" "")
- (lshiftrt:HI (match_operand:HI 1 "general_operand_src" "")
+ (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
"if (expand_a_shift (HImode, LSHIFTRT, operands)) DONE;else FAIL;")
@@ -1565,22 +1865,15 @@
""
"if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_HI"
+(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
(match_operator:HI 3 "nshift_operator"
[ (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "KM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
- [(set_attr "type" "arith")
- (set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
+ [(set_attr "length" "20")
(set_attr "cc" "clobber")])
;; SI BIT SHIFTS
@@ -1588,7 +1881,7 @@
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashift:SI
- (match_operand:SI 1 "general_operand_src" "")
+ (match_operand:SI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
"if (expand_a_shift (SImode, ASHIFT, operands)) DONE;else FAIL;")
@@ -1596,7 +1889,7 @@
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI
- (match_operand:SI 1 "general_operand_src" "")
+ (match_operand:SI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
"if (expand_a_shift (SImode, LSHIFTRT, operands)) DONE;else FAIL;")
@@ -1604,384 +1897,350 @@
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashiftrt:SI
- (match_operand:SI 1 "general_operand_src" "")
+ (match_operand:SI 1 "general_operand" "")
(match_operand:QI 2 "nonmemory_operand" "")))]
""
"if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_SI"
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI 3 "nshift_operator"
[ (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IK,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "K,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
- [(set_attr "type" "arith")
- (set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
+ [(set_attr "length" "20")
(set_attr "cc" "clobber")])
-
+
;; -----------------------------------------------------------------
;; BIT FIELDS
;; -----------------------------------------------------------------
;; The H8/300 has given 1/8th of its opcode space to bitfield
-;; instructions so let's use them as well as we can
-
-;; BCC and BCS patterns.
-
-(define_insn "bcs_qiqi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "eq_operator"
- [(zero_extract:QI (match_operand:QI 2 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 3 "immediate_operand" "i"))
- (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- output_asm_insn(\"bld %Z3,%Y2\", operands);
- if (get_attr_length (insn) == 2)
- return \"b%d1 %l0\";
- else if (get_attr_length (insn) == 4)
- return \"b%d1 %l0:16\";
- else
- return \"b%g1 %L0\;jmp @%l0\;%L0:\";
-}"
- [(set_attr "type" "branch")
- (set_attr "cc" "clobber")])
-
-(define_insn "bcs_hihi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "eq_operator"
- [(zero_extract:HI (match_operand:HI 2 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 3 "immediate_operand" "i"))
- (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- output_asm_insn(\"bld %Z3,%Y2\", operands);
- if (get_attr_length (insn) == 2)
- return \"%d1 %l0\";
- else if (get_attr_length (insn) == 4)
- return \"%d1 %l0:16\";
- else
- return \"%g1 %L0\;jmp @%l0\;%L0:\";
-}"
- [(set_attr "type" "branch")
- (set_attr "cc" "clobber")])
-
-(define_insn "bcs_hiqi"
- [(set (pc)
- (if_then_else
- (match_operator 1 "eq_operator"
- [(zero_extract:HI (match_operand:QI 2 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 3 "immediate_operand" "i"))
- (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- output_asm_insn(\"bld %Z3,%Y2\", operands);
- if (get_attr_length (insn) == 2)
- return \"%d1 %l0\";
- else if (get_attr_length (insn) == 4)
- return \"%d1 %l0:16\";
- else
- return \"%g1 %L0\;jmp @%l0\;%L0:\";
-}"
- [(set_attr "type" "branch")
- (set_attr "cc" "clobber")])
+;; instructions so let's use them as well as we can.
-;; BLD and BST patterns
+;; You'll never believe all these patterns perform one basic action --
+;; load a bit from the source, optionally invert the bit, then store it
+;; in the destination (which is known to be zero)..
+;;
+;; Combine obviously need some work to better identify this situation and
+;; canonicalize the form better.
-(define_insn "extract_1"
+;;
+;; Normal loads with a 16bit destination.
+;;
+;; Yes, both cases are needed.
+;;
+(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=&r")
- (zero_extract:HI (match_operand:QI 1 "bit_operand" "Ur")
+ (zero_extract:HI (match_operand:HI 1 "register_operand" "r")
(const_int 1)
- (match_operand:HI 2 "immediate_operand" "i")))]
+ (match_operand:HI 2 "immediate_operand" "n")))]
""
- "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
+ "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "6")])
-(define_insn "extract_1_hi"
+(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=&r")
- (zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 2 "immediate_operand" "i")))]
- ""
- "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0")
-
-(define_insn "insert_1"
- [(set (zero_extract:HI (match_operand:QI 0 "bit_operand" "+Ur")
- (const_int 1)
- (match_operand:HI 1 "immediate_operand" "i"))
- (zero_extract:HI (match_operand:QI 2 "bit_operand" "Ur")
- (const_int 1)
- (const_int 0)))]
- ""
- "bld #0,%X2\;bst %Z1,%Y0 ; i1")
+ (subreg:HI (zero_extract:SI
+ (match_operand:HI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 2 "immediate_operand" "n")) 1))]
+ ""
+ "sub.w %0,%0\;bld %Z2,%Y1\;bst #0,%X0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "6")])
+
+;;
+;; Inverted loads with a 16bit destination.
+;;
+;; Yes, all four cases are needed.
+;;
-;; This is how combine canonicalizes this pattern. This is perhaps a bug
-;; in combine.c, but there is no problem with writing it this way so we do.
-(define_insn "extract_insert_1"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "+Ur")
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (zero_extract:HI (xor:HI (match_operand:HI 1 "register_operand" "r")
+ (match_operand:HI 3 "p_operand" "P"))
(const_int 1)
- (match_operand:HI 1 "immediate_operand" "i"))
- (lshiftrt:QI (match_operand:QI 2 "bit_operand" "Ur")
- (match_operand:HI 3 "immediate_operand" "i")))]
- ""
- "bld %Z3,%Y2\;bst %Z1,%Y0; ei1")
+ (match_operand:HI 2 "const_int_operand" "n")))]
+ "(1 << INTVAL (operands[2])) == INTVAL (operands[3])"
+ "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "8")])
-;; BAND, BOR, and BXOR patterns
-
-(define_insn "bitlogical_1"
- [(set (match_operand:HI 0 "bit_operand" "=Ur")
- (match_operator:HI 4 "bit_operator"
- [(zero_extract:HI (match_operand:QI 1 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 2 "immediate_operand" "i"))
- (match_operand:HI 3 "bit_operand" "0")]))]
- ""
- "bld %Z2,%Y1\;%b4 #0,%X0\;bst #0,%X0; bl1")
-
-(define_insn "bitlogical_1_hi"
- [(set (match_operand:HI 0 "bit_operand" "=Ur")
- (match_operator:HI 4 "bit_operator"
- [(zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 2 "immediate_operand" "i"))
- (match_operand:HI 3 "bit_operand" "0")]))]
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (and:HI (not:HI
+ (lshiftrt:HI
+ (match_operand:HI 1 "bit_operand" "Ur")
+ (match_operand:HI 2 "const_int_operand" "n")))
+ (const_int 1)))]
""
- "bld %Z2,%Y1\;%b4 #0,%X0\;bst #0,%X0; bl2")
+ "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "8")])
-(define_insn "bitlogical_2"
- [(set (match_operand:HI 0 "bit_operand" "=Ur")
- (match_operator:HI 5 "bit_operator"
- [(zero_extract:HI (match_operand:QI 1 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 2 "immediate_operand" "i"))
- (zero_extract:HI (match_operand:QI 3 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 4 "immediate_operand" "i"))]))]
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (and:HI (not:HI
+ (subreg:HI
+ (lshiftrt:SI
+ (match_operand:SI 1 "register_operand" "Ur")
+ (match_operand:SI 2 "const_int_operand" "n")) 1))
+ (const_int 1)))]
+ "INTVAL (operands[2]) < 16"
+ "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "8")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (and:HI (not:HI
+ (subreg:HI
+ (lshiftrt:SI
+ (match_operand:SI 1 "bit_operand" "Ur")
+ (match_operand:SI 2 "const_int_operand" "n")) 0))
+ (const_int 1)))]
+ "(TARGET_H8300H || TARGET_H8300S)
+ && INTVAL (operands[2]) < 16"
+ "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "8")])
+
+;;
+;; Normal loads with a 32bit destination.
+;;
+;; Yes, all three cases are needed.
+;;
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (zero_extract:SI (match_operand:HI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 2 "const_int_operand" "n")))]
""
- "bld %Z2,%Y1\;%b5 %Z4,%Y3\;bst #0,%X0; bl3")
+ "* return output_simode_bld (0, 0, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (zero_extend:SI
+ (lshiftrt:QI
+ (match_operand:QI 1 "bit_operand" "Ur")
+ (match_operand:QI 2 "const_int_operand" "n")))
+ (const_int 1)))]
+ ""
+ "* return output_simode_bld (0, 0, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (zero_extend:SI
+ (lshiftrt:HI
+ (match_operand:HI 1 "bit_operand" "Ur")
+ (match_operand:HI 2 "const_int_operand" "n")))
+ (const_int 1)))]
+ ""
+ "* return output_simode_bld (0, 0, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
-(define_insn "bitlogical_2_hi"
- [(set (match_operand:HI 0 "bit_operand" "=Ur")
- (match_operator:HI 5 "bit_operator"
- [(zero_extract:HI (match_operand:HI 1 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 2 "immediate_operand" "i"))
- (zero_extract:HI (match_operand:HI 3 "bit_operand" "Ur")
- (const_int 1)
- (match_operand:HI 4 "immediate_operand" "i"))]))]
- ""
- "bld %Z2,%Y1\;%b5 %Z4,%Y3\;bst #0,%X0; bl3")
+;;
+;; Inverted loads with a 32bit destination.
+;;
+;; Yes, all seven cases are needed.
+;;
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (not:SI
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))
+ (match_operand:SI 2 "p_operand" "P")))]
+ ""
+ "* return output_simode_bld (1, 1, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (not:SI
+ (zero_extend:SI
+ (lshiftrt:HI (match_operand:HI 1 "bit_operand" "Ur")
+ (match_operand:HI 2 "const_int_operand" "n"))))
+ (const_int 1)))]
+ ""
+ "* return output_simode_bld (1, 0, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (not:SI
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))
+ (match_operand:SI 2 "p_operand" "P")))]
+ ""
+ "* return output_simode_bld (1, 1, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (not:SI
+ (zero_extend:SI
+ (lshiftrt:QI (match_operand:QI 1 "bit_operand" "Ur")
+ (match_operand:QI 2 "const_int_operand" "n"))))
+ (const_int 1)))]
+ ""
+ "* return output_simode_bld (1, 0, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (not:SI
+ (subreg:SI
+ (lshiftrt:HI
+ (match_operand:HI 1 "bit_operand" "Ur")
+ (match_operand:HI 2 "const_int_operand" "n")) 0))
+ (const_int 1)))]
+ "1"
+ "* return output_simode_bld (1, 0, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (and:SI (not:SI
+ (subreg:SI
+ (lshiftrt:QI
+ (match_operand:QI 1 "bit_operand" "Ur")
+ (match_operand:QI 2 "const_int_operand" "n")) 0))
+ (const_int 1)))]
+ "1"
+ "* return output_simode_bld (1, 0, operands);"
+ [(set_attr "cc" "clobber")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_H8300H || TARGET_H8300S")
+ (const_int 0))
+ (const_int 10)
+ (const_int 8)))])
-;; This is how combine canonicalizes this pattern. This is perhaps a bug
-;; in combine.c, but there is no problem with writing it this way so we do.
-(define_insn "bitlogical_3"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "+Ur")
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (zero_extract:SI (xor:HI (match_operand:HI 1 "register_operand" "r")
+ (match_operand:HI 3 "p_operand" "P"))
(const_int 1)
- (match_operand:HI 1 "immediate_operand" "i"))
- (match_operator:QI 6 "bit_operator"
- [(lshiftrt:QI (match_operand:QI 2 "bit_operand" "Ur")
- (match_operand:HI 3 "immediate_operand" "i"))
- (lshiftrt:QI (match_operand:QI 4 "bit_operand" "Ur")
- (match_operand:HI 5 "immediate_operand" "i"))]))]
- ""
- "bld %Z3,%Y2\;%b6 %Z5,%Y4\;bst %Z1,%Y0; bl5")
-
-;; This is how combine canonicalizes this pattern. This is perhaps a bug
-;; in combine.c, but there is no problem with writing it this way so we do.
-(define_insn "bitnot_1"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "=Ur")
- (const_int 1)
- (match_operand:HI 1 "immediate_operand" "i"))
- (lshiftrt:QI (xor:QI (match_operand:QI 2 "bit_operand" "0")
- (match_operand:HI 3 "immediate_operand" "i"))
- (match_operand:HI 4 "immediate_operand" "1")))]
- "GET_CODE (operands[3]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT
- && exact_log2 (INTVAL (operands[3])) == INTVAL (operands[1])"
- "bnot %Z1,%Y0")
-
-;; ??? Implement BIAND, BIOR, BIXOR
-
-;; ??? Implement BILD, BIST
-
-;; ??? Apparently general_operand for the 1st and 2nd operands is useful,
-;; but I don't know why. --Jim
+ (match_operand:HI 2 "const_int_operand" "n")))]
+ "(1 << INTVAL (operands[2])) == INTVAL (operands[3])"
+ "sub.w %0,%0\;bild %Z2,%Y1\;bst #0,%X0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "8")])
(define_expand "insv"
- [(set (zero_extract:HI (match_operand:QI 0 "bit_operand" "Ur")
- (match_operand:HI 1 "general_operand" "g")
- (match_operand:HI 2 "general_operand" "g"))
- (zero_extract:HI (match_operand:QI 3 "bit_operand" "Ur")
- (const_int 1)
- (const_int 0)))]
-;; ??? This should have word mode which is SImode for the h8/300h.
+ [(set (zero_extract:HI (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" "")
+ (match_operand:HI 2 "general_operand" ""))
+ (match_operand:HI 3 "general_operand" ""))]
"TARGET_H8300"
"
{
+ /* We only have single bit bitfield instructions. */
if (INTVAL (operands[1]) != 1)
FAIL;
- /* ??? HACK ???
- This INSV pattern is wrong. It should use HImode for operand 3.
- Also, the zero_extract around operand 3 is superfluous and should be
- deleted. Fixing this is more work than we care to do for the moment,
- because it means most of the above patterns would need to be rewritten,
- and we also need more combine.c patches to make this work.
-
- So, for now, we work around this bug by simply not accepting any bitfield
- inserts that have a position greater than fits in QImode. */
-
- if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 8)
+ /* For now, we don't allow memory operands. */
+ if (GET_CODE (operands[0]) == MEM
+ || GET_CODE (operands[3]) == MEM)
FAIL;
-
- /* The bit_operand predicate accepts any memory during RTL generation, but
- only 'U' memory afterwards, so if this is a MEM operand, we must force
- it to be valid for 'U' by reloading the address. */
-
- if (GET_CODE (operands[0]) == MEM && ! EXTRA_CONSTRAINT (operands[0], 'U'))
- {
- rtx mem;
- mem = gen_rtx (MEM, GET_MODE (operands[0]),
- copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
- RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[0]);
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[0]);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[0]);
- operands[0] = mem;
- }
-
- /* Likewise for operands[3]. */
-
- if (GET_CODE (operands[3]) == MEM && ! EXTRA_CONSTRAINT (operands[3], 'U'))
- {
- rtx mem;
- mem = gen_rtx (MEM, GET_MODE (operands[3]),
- copy_to_mode_reg (Pmode, XEXP (operands[3], 0)));
- RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[3]);
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[3]);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[3]);
- operands[3] = mem;
- }
}")
-;; ??? Apparently general_operand for the 2nd and 3rd operands is useful,
-;; but I don't know why. --Jim
+(define_insn ""
+ [(set (zero_extract:HI (match_operand:HI 0 "register_operand" "+r")
+ (const_int 1)
+ (match_operand:HI 1 "immediate_operand" "n"))
+ (match_operand:HI 2 "register_operand" "r"))]
+ ""
+ "bld #0,%R2\;bst %Z1,%Y0 ; i1"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "4")])
(define_expand "extzv"
[(set (match_operand:HI 0 "register_operand" "")
- (zero_extract:HI (match_operand:QI 1 "bit_operand" "")
- (match_operand:HI 2 "general_operand" "g")
- (match_operand:HI 3 "general_operand" "g")))]
-;; ??? This should have word mode which is SImode for the h8/300h.
+ (zero_extract:HI (match_operand:HI 1 "bit_operand" "")
+ (match_operand:HI 2 "general_operand" "")
+ (match_operand:HI 3 "general_operand" "")))]
"TARGET_H8300"
"
{
+ /* We only have single bit bitfield instructions. */
if (INTVAL (operands[2]) != 1)
FAIL;
- /* The bit_operand predicate accepts any memory during RTL generation, but
- only 'U' memory afterwards, so if this is a MEM operand, we must force
- it to be valid for 'U' by reloading the address. */
-
- if (GET_CODE (operands[1]) == MEM && ! EXTRA_CONSTRAINT (operands[1], 'U'))
- {
- rtx mem;
- mem = gen_rtx (MEM, GET_MODE (operands[1]),
- copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
- RTX_UNCHANGING_P (mem) = RTX_UNCHANGING_P (operands[1]);
- MEM_IN_STRUCT_P (mem) = MEM_IN_STRUCT_P (operands[1]);
- MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (operands[1]);
- operands[1] = mem;
- }
+ /* For now, we don't allow memory operands. */
+ if (GET_CODE (operands[1]) == MEM)
+ FAIL;
}")
-;; -----------------------------------------------------------------
-;; STACK POINTER MANIPULATIONS
-;; -----------------------------------------------------------------
-
-;; This pattern is needed because there is no way on the H8/300
-;; to add a 16 bit immediate value to the stack pointer in one
-;; instruction, which could leave an invalid instruction if interrupted
-;; half way through. Here we add to the stack pointer from a
-;; register.
-
-(define_insn "stack_pointer_manip"
- [(set (match_operand:HI 0 "register_operand" "=&ra")
- (plus:HI (match_operand:HI 1 "general_operand_src" "g")
- (match_operand:HI 2 "register_operand" "ra")))]
- "TARGET_H8300"
- "mov.w %T1,%T0\;add.w %T2,%T0"
- [(set_attr "type" "arith")
- (set_attr "length" "6")
- (set_attr "cc" "set")])
-
+;; BAND, BOR, and BXOR patterns
-;; -------------------------------------------
-;; BLK moves
-;; -------------------------------------------
+(define_insn ""
+ [(set (match_operand:HI 0 "bit_operand" "=Ur")
+ (match_operator:HI 4 "bit_operator"
+ [(zero_extract:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 2 "immediate_operand" "n"))
+ (match_operand:HI 3 "bit_operand" "0")]))]
+ ""
+ "bld %Z2,%Y1\;%b4 #0,%R0\;bst #0,%R0; bl1"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "6")])
-(define_expand "movstrhi"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
- (mem:BLK (match_operand:BLK 1 "general_operand" "")))
- (use (match_operand:HI 2 "general_operand" ""))
- (use (match_operand:HI 3 "immediate_operand" ""))
- (clobber (match_dup 3))
- ])]
+(define_insn ""
+ [(set (match_operand:HI 0 "bit_operand" "=Ur")
+ (match_operator:HI 5 "bit_operator"
+ [(zero_extract:HI (match_operand:HI 1 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 2 "immediate_operand" "n"))
+ (zero_extract:HI (match_operand:HI 3 "register_operand" "r")
+ (const_int 1)
+ (match_operand:HI 4 "immediate_operand" "n"))]))]
""
- "
-{
- rtx src_ptr = copy_to_mode_reg (Pmode, XEXP(operands[1], 0));
- rtx dst_ptr = copy_to_mode_reg (Pmode, XEXP(operands[0], 0));
-
- int max = GET_CODE (operands[2]) == CONST_INT
- ? MIN (INTVAL (operands[2]), INTVAL (operands[3])) : 1;
- enum machine_mode mode = max >= 2 ? HImode : QImode;
- rtx tmpreg = gen_reg_rtx (mode);
- rtx increment = mode == QImode ? const1_rtx : const2_rtx;
- rtx length = operands[2];
- rtx label = gen_label_rtx ();
- rtx end_src_ptr = gen_reg_rtx (Pmode);
-
-/* emit_move_insn (length, gen_rtx(MINUS, HImode, length, increment));*/
- FAIL;
- if (Pmode == HImode)
- emit_insn (gen_addhi3 (end_src_ptr, src_ptr, length));
- else
- emit_insn (gen_addsi3 (end_src_ptr, src_ptr, length));
-
- emit_label (label);
- emit_move_insn (tmpreg, gen_rtx (MEM, mode, src_ptr));
- emit_move_insn (gen_rtx (MEM, mode, dst_ptr), tmpreg);
- emit_insn (gen_rtx (SET, VOIDmode, src_ptr,
- gen_rtx (PLUS, Pmode, src_ptr, increment)));
- emit_insn (gen_rtx (SET, VOIDmode, dst_ptr,
- gen_rtx (PLUS, Pmode, dst_ptr, increment)));
-
- emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
- gen_rtx (COMPARE, Pmode, src_ptr, end_src_ptr)));
- emit_jump_insn (gen_bne (label));
-
- DONE;
-}")
+ "bld %Z2,%Y1\;%b5 %Z4,%Y3\;bst #0,%R0; bl3"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "6")])
+
;; ----------------------------------------------
;; Peepholes go at the end.
;; ----------------------------------------------
@@ -1990,7 +2249,7 @@
(define_peephole
[(set (match_operand:QI 0 "register_operand" "=r")
- (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra")
+ (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "r")
(match_operand:HI 2 "immediate_operand" "n"))))
(set (match_operand:QI 3 "register_operand" "=r")
(mem:QI (plus:HI (match_dup 1)
@@ -1998,10 +2257,10 @@
"(INTVAL(operands[2]) == INTVAL(operands[4])+1) && REGNO(operands[0]) +1 == REGNO(operands[3])"
"mov.w @(%u4,%T1),%T0"
[(set_attr "length" "6")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_znv")])
(define_peephole
- [(set (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "ra")
+ [(set (mem:QI (plus:HI (match_operand:HI 1 "register_operand" "r")
(match_operand:HI 2 "immediate_operand" "n")))
(match_operand:QI 0 "register_operand" "r"))
(set (mem:QI (plus:HI (match_dup 1)
@@ -2010,7 +2269,7 @@
"(INTVAL(operands[2]) == INTVAL(operands[4])+1) && REGNO(operands[0]) +1 == REGNO(operands[3])"
"mov.w %T0,@(%u4,%T1)"
[(set_attr "length" "6")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_znv")])
;; Notice a move which could be post incremented.
@@ -2021,7 +2280,7 @@
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.b @%T1+,%X0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_znv")])
(define_peephole
[(set (match_operand:HI 0 "register_operand" "")
@@ -2030,7 +2289,7 @@
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.w @%T1+,%T0"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_znv")])
;; Notice a move which could be predecremented.
@@ -2042,7 +2301,7 @@
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.b %X0,@-%T1"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
+ (set_attr "cc" "set_znv")])
(define_peephole
[(set (match_operand:HI 1 "register_operand" "")
@@ -2052,169 +2311,5 @@
"REGNO(operands[1]) != REGNO(operands[0])"
"mov.w %T0,@-%T1"
[(set_attr "length" "2")
- (set_attr "cc" "set")])
-
-;(define_insn ""
-; [(set (match_operand:HI 0 "register_operand" "=r")
-; (MEM:HI (match_operand:HI 1 "register_operand" "r")))
-; (set (match_operand:HI 3 "register_operand" "=r")
-; (zero_extract:HI (match_dup 0)
-; (const_int 1)
-; (match_operand:HI 2 "general_operand" "g")))
-; (set (MEM:HI (match_dup 1) (match_dup 3)))]
-; ""
-; "bld #0,%3l\;bst %Z2,%0%Y1"
-; [(set_attr "type" "multi")
-; (set_attr "length" "4")
-; (set_attr "cc" "clobber")])
-
-(define_insn "fancybset1"
- [(set (match_operand:QI 0 "bit_operand" "=Ur")
- (ior:QI (subreg:QI
- (ashift:HI (const_int 1)
- (subreg:QI (match_operand:HI 1 "register_operand" "ri") 0)) 0)
- (match_dup 0)))]
- ""
- "bset %X1,%X0")
-
-(define_insn "fancybset"
- [(set (match_operand:QI 0 "bit_operand" "=Ur")
- (ior:QI (subreg:QI
- (ashift:HI (const_int 1)
- (match_operand:HI 1 "nonmemory_operand" "ri") ) 0)
- (match_operand:QI 2 "general_operand" "Ur")))]
- ""
- "mov.b %X2,%X0\;bset %X1,%X0")
-
-
-(define_insn "fancybclr4"
- [(set (match_operand:QI 0 "general_operand" "=Ur,Ur")
- (and:QI
- (subreg:QI
- (rotate:HI (const_int -2)
- (match_operand:HI 2 "nonmemory_operand" "ri,ri") ) 0)
- (match_operand:QI 1 "general_operand" "0,Ur")))
- (clobber (match_scratch:HI 3 "=X,&r"))]
- ""
- "@
- bclr %X2,%X0; l1
- mov.b %X1,%X3\;mov.b %3,%0\;bclr %X2,%X0; l3")
-
-(define_insn "fancybclr5"
- [(set (match_operand:QI 0 "general_operand" "=Ur,Ur")
- (and:QI
- (subreg:QI
- (rotate:HI (const_int -2)
- (match_operand:QI 2 "nonmemory_operand" "ri,ri")) 0)
- (match_operand:QI 1 "general_operand" "0,Ur")))
- (clobber (match_scratch:HI 3 "=X,&r"))]
- ""
- "@
- bclr %X2,%X0; l1
- mov.b %X1,%X3\;mov.b %3,%0\;bclr %X2,%X0;l2")
-
-(define_insn "fancybclr2"
- [(set (match_operand:QI 0 "general_operand" "=U,r")
- (and:QI
- (subreg:QI
- (rotate:HI (const_int -2)
- (match_operand:HI 2 "nonmemory_operand" "ri,ri") ) 0)
- (match_operand:QI 1 "general_operand" "0,0")))]
- ""
- "bclr %X2,%X0")
-
-(define_insn "fancybclr3"
- [(set (match_operand:QI 0 "general_operand" "=U,r")
- (and:QI
- (subreg:QI
- (rotate:HI (const_int -2)
- (match_operand:QI 2 "nonmemory_operand" "ri,ri")) 0)
- (match_operand:QI 1 "general_operand" "0,0")))]
- ""
- "bclr %X2,%X0")
-
-(define_insn "fancybclr"
- [(set (match_operand:QI 0 "general_operand" "=r")
- (and:QI (not:QI (match_operand:QI 1 "general_operand" "0"))
- (match_operand:QI 2 "general_operand" "r")))]
- ""
- "not %X0\;and %X2,%X0")
-
-(define_insn "fancybsetp3"
- [(set (match_operand:QI 0 "bit_operand" "=Ur")
- (ior:QI (subreg:QI (ashift:HI (const_int 1)
- (match_operand:QI 1 "register_operand" "r")) 0)
- (match_operand:QI 2 "bit_operand" "0")))]
- ""
- "bset %X1,%X0")
-
-(define_insn "fancybsetp2"
- [(set (match_operand:QI 0 "general_operand" "=r,U")
- (ior:QI (subreg:QI (ashift:HI (const_int 1)
- (match_operand:QI 1 "register_operand" "r,r")) 0)
- (match_operand:QI 2 "general_operand" "U,r")))]
- ""
- "mov.b %X2,%X0\;bset %X1,%X0")
-
-(define_insn "fancybnot"
- [(set (match_operand:QI 0 "bit_operand" "=Ur")
- (xor:QI (subreg:QI (ashift:HI (const_int 1)
- (match_operand:QI 1 "register_operand" "r")) 0)
- (match_operand:QI 2 "bit_operand" "0")))]
+ (set_attr "cc" "set_znv")])
- ""
- "bnot %X1,%X0")
-
-(define_insn "fancy_btst"
- [(set (pc)
- (if_then_else (eq (zero_extract:HI (zero_extend:HI (match_operand:QI 1 "general_operand" "Ur"))
- (const_int 1)
- (match_operand:HI 2 "nonmemory_operand" "rn"))
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (get_attr_length (insn) == 2)
- return \"btst %X2,%X1\;beq %l0\";
- else if (get_attr_length (insn) == 4)
- return \"btst %X2,%X1\;beq %l0:16\";
- else
- return \"btst %X2,%X1\;bne %L1\;jmp @%l0\;%L1:\";
-}"
- [(set_attr "type" "branch")
- (set_attr "cc" "clobber")])
-
-(define_insn "fancy_btst1"
- [(set (pc)
- (if_then_else (ne (zero_extract:HI (zero_extend:HI (match_operand:QI 1 "general_operand" "Ur"))
- (const_int 1)
- (match_operand:HI 2 "nonmemory_operand" "rn"))
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if (get_attr_length (insn) == 2)
- return \"btst %X2,%X1\;bne %l0\";
- else if (get_attr_length (insn) == 4)
- return \"btst %X2,%X1\;bne %l0:16\";
- else
- return \"btst %X2,%X1\;beq %L1\;jmp @%l0\;%L1:\";
-}"
- [(set_attr "type" "branch")
- (set_attr "cc" "clobber")])
-
-(define_insn "pxor"
- [(set (zero_extract:QI (match_operand:QI 0 "bit_operand" "=r,U")
- (const_int 1)
- (match_operand 1 "immediate_operand" "n,n"))
- (and:QI (not:QI (match_operand:QI 2 "bit_operand" "r,U"))
- (const_int 1)))]
- ""
- "bld #0,%X2\;bist %1,%0"
- [(set_attr "type" "arith")
- (set_attr "length" "4")
- (set_attr "cc" "clobber")])
diff --git a/gnu/usr.bin/gcc/config/h8300/lib1funcs.asm b/gnu/usr.bin/gcc/config/h8300/lib1funcs.asm
index 8746e00219d..8b6066ec386 100644
--- a/gnu/usr.bin/gcc/config/h8300/lib1funcs.asm
+++ b/gnu/usr.bin/gcc/config/h8300/lib1funcs.asm
@@ -80,7 +80,7 @@ Boston, MA 02111-1307, USA. */
#define S2P r6
#endif
-#ifdef __H8300H__
+#if defined (__H8300H__) || defined (__H8300S__)
#define MOVP mov.l /* pointers are 32 bits */
#define ADDP add.l
#define CMPP cmp.l
@@ -190,6 +190,22 @@ _lab1: or A1H,A1H ; look at dividend
adds #1,A1
xor #0x1,A2L; and toggle sign of result
_lab2: rts
+;; Basically the same, except that the sign of the divisor determines
+;; the sign.
+modnorm:
+ mov.b #0x0,A2L
+ or A0H,A0H ; is divisor > 0
+ bge _lab7
+ not A0H ; no - then make it +ve
+ not A0L
+ adds #1,A0
+ xor #0x1,A2L ; and remember that in A2L
+_lab7: or A1H,A1H ; look at dividend
+ bge _lab8
+ not A1H ; it is -ve, make it positive
+ not A1L
+ adds #1,A1
+_lab8: rts
; A0=A0/A1 signed
@@ -208,7 +224,7 @@ _lab4: rts
.global ___modhi3
___modhi3:
- bsr divnorm
+ bsr modnorm
bsr ___udivhi3
mov A3,A0
bra negans
@@ -298,6 +314,10 @@ setbit: inc A0L ; do insert bit
.h8300h
#endif
+#ifdef __H8300S__
+ .h8300s
+#endif
+
.section .text
.align 2
@@ -319,8 +339,8 @@ divnorm:
add #1,A1L
addx #0,A1H
- addx #0,A0H
addx #0,A0L
+ addx #0,A0H
mov.b #1,S2L ; the sign will be -ve
postive:
@@ -338,6 +358,39 @@ postive:
postive2:
rts
+;; Basically the same, except that the sign of the divisor determines
+;; the sign.
+modnorm:
+ mov.b #0,S2L ; keep the sign in S2
+ mov.b A0H,A0H ; is the numerator -ve
+ bge mpostive
+
+ ; negate arg
+ not A0H
+ not A1H
+ not A0L
+ not A1L
+
+ add #1,A1L
+ addx #0,A1H
+ addx #0,A0L
+ addx #0,A0H
+
+ mov.b #1,S2L ; the sign will be -ve
+mpostive:
+ mov.b A2H,A2H ; is the denominator -ve
+ bge mpostive2
+ not A2L
+ not A2H
+ not A3L
+ not A3H
+ add.b #1,A3L
+ addx #0,A3H
+ addx #0,A2L
+ addx #0,A2H
+mpostive2:
+ rts
+
#else /* __H8300H__ */
divnorm:
@@ -358,6 +411,25 @@ postive:
postive2:
rts
+;; Basically the same, except that the sign of the divisor determines
+;; the sign.
+modnorm:
+ mov.b #0,S2L ; keep the sign in S2
+ mov.l A0P,A0P ; is the numerator -ve
+ bge mpostive
+
+ neg.l A0P ; negate arg
+ mov.b #1,S2L ; the sign will be -ve
+
+mpostive:
+ mov.l A1P,A1P ; is the denominator -ve
+ bge mpostive2
+
+ neg.l A1P ; negate arg
+
+mpostive2:
+ rts
+
#endif
; numerator in A0/A1
@@ -368,7 +440,7 @@ ___modsi3:
PUSHP S0P
PUSHP S1P
- bsr divnorm
+ bsr modnorm
bsr divmodsi4
#ifdef __H8300__
mov S0,A0
@@ -427,8 +499,8 @@ exitdiv:
add #1,A1L
addx #0,A1H
- addx #0,A0H
addx #0,A0L
+ addx #0,A0H
#else /* __H8300H__ */
neg.l A0P
#endif
@@ -670,7 +742,13 @@ _done:
#else /* __H8300H__ */
+#ifdef __H8300H__
.h8300h
+#endif
+
+#ifdef __H8300S__
+ .h8300s
+#endif
.global ___mulsi3
___mulsi3:
diff --git a/gnu/usr.bin/gcc/config/h8300/t-h8300 b/gnu/usr.bin/gcc/config/h8300/t-h8300
index f072d99090f..f7536b5383f 100644
--- a/gnu/usr.bin/gcc/config/h8300/t-h8300
+++ b/gnu/usr.bin/gcc/config/h8300/t-h8300
@@ -3,7 +3,7 @@ LIB1ASMSRC = h8300/lib1funcs.asm
LIB1ASMFUNCS = _cmpsi2 _ucmpsi2 _divhi3 _divsi3 _mulhi3 _mulsi3
# We do not have DF or DI types, so fake out the libgcc2 compilation.
-LIBGCC2_CFLAGS = -g -O2 -DDF=SF -DDI=SI $(GCC_CFLAGS) $(LIBGCC2_INCLUDES)
+TARGET_LIBGCC2_CFLAGS = -DDF=SF -DDI=SI
LIB2FUNCS_EXTRA = fp-bit.c
@@ -18,8 +18,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-MULTILIB_OPTIONS = mh
-MULTILIB_DIRNAMES = h8300h
+MULTILIB_OPTIONS = mh/ms mint32
+MULTILIB_DIRNAMES = h8300h h8300s int32
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/i370/i370.md b/gnu/usr.bin/gcc/config/i370/i370.md
index c64f86d3ee7..c39007d2d8a 100644
--- a/gnu/usr.bin/gcc/config/i370/i370.md
+++ b/gnu/usr.bin/gcc/config/i370/i370.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU compiler -- System/370 version.
-;; Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 93, 94, 95, 1997 Free Software Foundation, Inc.
;; Contributed by Jan Stein (jan@cd.chalmers.se).
;; Modified for MVS C/370 by Dave Pitts (dpitts@nyx.cs.du.edu)
@@ -295,7 +295,7 @@
if (GET_CODE (operands[1]) == CONST_INT)
{
mvs_check_page (0, 4, 1);
- return \"CLM %0,1,=X'%X1'\";
+ return \"CLM %0,1,=FL1'%B1'\";
}
mvs_check_page (0, 4, 0);
return \"CLM %0,1,%1\";
@@ -306,7 +306,7 @@
if (REG_P (operands[1]))
{
mvs_check_page (0, 4, 1);
- return \"CLM %1,1,=X'%X0'\";
+ return \"CLM %1,1,=FL1'%B0'\";
}
mvs_check_page (0, 4, 0);
return \"CLI %1,%B0\";
@@ -344,7 +344,7 @@
if (GET_CODE (operands[1]) == CONST_INT)
{
mvs_check_page (0, 4, 1);
- return \"CLM %0,1,=X'%X1'\";
+ return \"CLM %0,1,=FL1'%B1'\";
}
mvs_check_page (0, 8, 0);
return \"STC %1,140(,13)\;CLM %0,1,140(13)\";
@@ -1210,36 +1210,30 @@ check_label_emit ();
op0 = XEXP (operands[0], 0);
if (GET_CODE (op0) == REG
- || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG
- && GET_CODE (XEXP (op0, 1)) == CONST_INT
- && (unsigned) INTVAL (XEXP (op0, 1)) < 4096))
- {
- op0 = operands[0];
- }
+ || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG
+ && GET_CODE (XEXP (op0, 1)) == CONST_INT
+ && (unsigned) INTVAL (XEXP (op0, 1)) < 4096))
+ op0 = operands[0];
else
- {
- op0 = gen_rtx (MEM, BLKmode, copy_to_mode_reg (SImode, op0));
- }
+ op0 = change_address (operands[0], VOIDmode,
+ copy_to_mode_reg (SImode, op0));
op1 = XEXP (operands[1], 0);
if (GET_CODE (op1) == REG
|| (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG
&& GET_CODE (XEXP (op1, 1)) == CONST_INT
&& (unsigned) INTVAL (XEXP (op1, 1)) < 4096))
- {
- op1 = operands[1];
- }
+ op1 = operands[1];
else
- {
- op1 = gen_rtx (MEM, BLKmode, copy_to_mode_reg (SImode, op1));
- }
+ op1 = change_address (operands[1], VOIDmode,
+ copy_to_mode_reg (SImode, op1));
if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 256)
- {
- emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
- gen_rtx (SET, VOIDmode, op0, op1),
- gen_rtx (USE, VOIDmode, operands[2]))));
- }
+ emit_insn (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2,
+ gen_rtx (SET, VOIDmode, op0, op1),
+ gen_rtx (USE, VOIDmode, operands[2]))));
+
else
{
rtx reg1 = gen_reg_rtx (DImode);
@@ -1248,13 +1242,14 @@ check_label_emit ();
emit_insn (gen_rtx (SET, VOIDmode, subreg, operands[2]));
emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (SUBREG, SImode, reg2, 1),
- subreg));
- emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (5,
- gen_rtx (SET, VOIDmode, op0, op1),
- gen_rtx (USE, VOIDmode, reg1),
- gen_rtx (USE, VOIDmode, reg2),
- gen_rtx (CLOBBER, VOIDmode, reg1),
- gen_rtx (CLOBBER, VOIDmode, reg2))));
+ subreg));
+ emit_insn (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (5,
+ gen_rtx (SET, VOIDmode, op0, op1),
+ gen_rtx (USE, VOIDmode, reg1),
+ gen_rtx (USE, VOIDmode, reg2),
+ gen_rtx (CLOBBER, VOIDmode, reg1),
+ gen_rtx (CLOBBER, VOIDmode, reg2))));
}
DONE;
}")
diff --git a/gnu/usr.bin/gcc/config/i386/386bsd.h b/gnu/usr.bin/gcc/config/i386/386bsd.h
index cdab5f57c88..c93279ffb00 100644
--- a/gnu/usr.bin/gcc/config/i386/386bsd.h
+++ b/gnu/usr.bin/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"
diff --git a/gnu/usr.bin/gcc/config/i386/aix386ng.h b/gnu/usr.bin/gcc/config/i386/aix386ng.h
index 5d09fc30509..ec283a4fa4e 100644
--- a/gnu/usr.bin/gcc/config/i386/aix386ng.h
+++ b/gnu/usr.bin/gcc/config/i386/aix386ng.h
@@ -1,6 +1,6 @@
/* Definitions for IBM PS2 running AIX/386.
- From: Minh Tran-Le <TRANLE@intellicorp.com>
- Copyright (C) 1988 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1996 Free Software Foundation, Inc.
+ Contributed by Minh Tran-Le <TRANLE@intellicorp.com>.
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,9 +44,9 @@ 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 \
+#define CPP_SPEC "%(cpp_cpu) %[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
@@ -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/gnu/usr.bin/gcc/config/i386/att.h b/gnu/usr.bin/gcc/config/i386/att.h
index f8bbb764306..e5c2d9c7e99 100644
--- a/gnu/usr.bin/gcc/config/i386/att.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/bsd.h b/gnu/usr.bin/gcc/config/i386/bsd.h
index 6bf7399dc31..d50be3664c1 100644
--- a/gnu/usr.bin/gcc/config/i386/bsd.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/bsd386.h b/gnu/usr.bin/gcc/config/i386/bsd386.h
index 935a2e06404..d64fe59e2ac 100644
--- a/gnu/usr.bin/gcc/config/i386/bsd386.h
+++ b/gnu/usr.bin/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,7 @@
#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 " #"
diff --git a/gnu/usr.bin/gcc/config/i386/gas.h b/gnu/usr.bin/gcc/config/i386/gas.h
index d02015723ba..fbfba7456be 100644
--- a/gnu/usr.bin/gcc/config/i386/gas.h
+++ b/gnu/usr.bin/gcc/config/i386/gas.h
@@ -1,5 +1,5 @@
-/* Definitions for Intel 386 running system V with gnu tools
- Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc.
+/* Definitions for Intel 386 using GAS.
+ Copyright (C) 1988, 1993, 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -56,8 +56,8 @@ Boston, MA 02111-1307, USA. */
/* Specify predefined symbols in preprocessor. */
-#define CPP_PREDEFINES "-Dunix -Di386 -Asystem(unix) -Acpu(i386) -Amachine(i386)"
-#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
+#define CPP_PREDEFINES "-Dunix"
+#define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{posix:-D_POSIX_SOURCE}"
/* Allow #sccs in preprocessor. */
@@ -71,12 +71,19 @@ Boston, MA 02111-1307, USA. */
#define TARGET_MEM_FUNCTIONS
-#if 0 /* People say gas uses the log as the arg to .align. */
-/* When using gas, .align N aligns to an N-byte boundary. */
+/* In the past there was confusion as to what the argument to .align was
+ in GAS. For the last several years the rule has been this: for a.out
+ file formats that argument is LOG, and for all other file formats the
+ argument is 1<<LOG.
+ However, GAS now has .p2align and .balign pseudo-ops so to remove any
+ doubt or guess work, and since this file is used for both a.out and other
+ file formats, we use one of them. */
+
+#if 0 /* ??? However, not every port uses binutils 2.6 yet. */
#undef ASM_OUTPUT_ALIGN
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG))
#endif
/* Align labels, etc. at 4-byte boundaries.
@@ -126,8 +133,8 @@ Boston, MA 02111-1307, USA. */
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/gnu/usr.bin/gcc/config/i386/gnu.h b/gnu/usr.bin/gcc/config/i386/gnu.h
index 1ad5df991e4..bdce3ed000b 100644
--- a/gnu/usr.bin/gcc/config/i386/gnu.h
+++ b/gnu/usr.bin/gcc/config/i386/gnu.h
@@ -6,14 +6,16 @@
#undef CPP_PREDEFINES
#define CPP_PREDEFINES GNU_CPP_PREDEFINES("i386")
+#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/gnu/usr.bin/gcc/config/i386/go32.h b/gnu/usr.bin/gcc/config/i386/go32.h
index 5618a0dd0fb..80a0e875c43 100644
--- a/gnu/usr.bin/gcc/config/i386/go32.h
+++ b/gnu/usr.bin/gcc/config/i386/go32.h
@@ -1,5 +1,9 @@
/* Configuration for an i386 running MS-DOS with djgpp/go32. */
+#include "dbxcoff.h"
+
+#define NO_STAB_H /* DJGPP has no stab.h */
+
/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
@@ -53,7 +57,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 +71,29 @@ 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 it's own version of __main, so don't define one
+ in libgcc, nor call one in main(). */
+#define HAS_INIT_SECTION
diff --git a/gnu/usr.bin/gcc/config/i386/i386.c b/gnu/usr.bin/gcc/config/i386/i386.c
index 48c58a09d8e..a4ec3b6a3f2 100644
--- a/gnu/usr.bin/gcc/config/i386/i386.c
+++ b/gnu/usr.bin/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, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -16,7 +16,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. */
#include <stdio.h>
#include <setjmp.h>
@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-attr.h"
#include "tree.h"
#include "flags.h"
+#include "except.h"
#include "function.h"
#ifdef EXTRA_CONSTRAINT
@@ -44,11 +45,69 @@ Boston, MA 02111-1307, USA. */
even if the conditional was untrue. */
#endif
+#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 ();
@@ -80,24 +139,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=<xxx> */
+char *ix86_arch_string; /* for -march=<xxx> */
+
/* 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,15 +193,34 @@ int i386_align_funcs; /* power of two alignment for functions */
void
override_options ()
{
- int ch, i, regno;
+ int ch, i, j, regno;
char *p;
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++)
@@ -137,23 +239,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);
@@ -164,7 +318,7 @@ override_options ()
else
i386_align_loops = 2;
- /* 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);
@@ -175,7 +329,7 @@ override_options ()
else
i386_align_jumps = def_align;
- /* 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 +339,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
@@ -205,7 +374,8 @@ order_regs_for_local_alloc ()
{
int i, ch, order, regno;
- /* 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++)
@@ -226,59 +396,112 @@ 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)
+ int level;
+{
+ /* 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));
}
+
+ 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
@@ -315,17 +538,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;
@@ -380,31 +603,28 @@ i386_return_pops_args (fundecl, funtype, size)
tree fundecl;
tree funtype;
int size;
-{
- int rtd = TARGET_RTD;
-
- if (TREE_CODE (funtype) == IDENTIFIER_NODE)
+{
+ int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
+
+ /* 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;
+
+ if (rtd
+ && (TYPE_ARG_TYPES (funtype) == NULL_TREE
+ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype)))
+ == void_type_node)))
+ return size;
+ }
+
+ /* Lose any fake structure return argument. */
+ if (aggregate_value_p (TREE_TYPE (funtype)))
+ return GET_MODE_SIZE (Pmode);
+
return 0;
-
- /* Cdecl functions override -mrtd, and never pop the stack */
- if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
- return 0;
-
- /* 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 (aggregate_value_p (TREE_TYPE (funtype)))
- return GET_MODE_SIZE (Pmode);
- }
-
- return 0;
}
@@ -416,7 +636,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 +647,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 +664,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 +677,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 +702,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 +745,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:
@@ -548,7 +768,7 @@ function_arg (cum, mode, type, named)
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)
@@ -575,7 +795,6 @@ function_arg_partial_nregs (cum, mode, type, named)
{
return 0;
}
-
/* Output an insn whose source is a 386 integer register. SRC is the
rtx for the register, and TEMPLATE is the op-code template. SRC may
@@ -609,18 +828,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);
output_asm_insn (AS1 (push%L0,%0), &high);
}
+
high = gen_rtx (REG, SImode, REGNO (src) + 1);
output_asm_insn (AS1 (push%L0,%0), &high);
}
- output_asm_insn (AS1 (push%L0,%0), &src);
+ output_asm_insn (AS1 (push%L0,%0), &src);
output_asm_insn (template, xops);
-
output_asm_insn (AS2 (add%L3,%2,%3), xops);
}
@@ -630,19 +850,25 @@ 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)
{
@@ -651,6 +877,7 @@ output_to_reg (dest, dies)
else
output_asm_insn (AS1 (fist%z3,%y0), xops);
}
+
else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT)
{
if (dies)
@@ -666,19 +893,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);
+ 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);
+ 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 +942,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 +974,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 +994,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 +1005,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. */
@@ -918,8 +1161,11 @@ 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);
else if (optype0 == OFFSOP)
@@ -960,13 +1206,12 @@ 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]);
middlehalf[1] = adj_offsettable_operand (operands[1], size-8);
latehalf[1] = adj_offsettable_operand (operands[1], size-4);
@@ -977,17 +1222,18 @@ compadr:
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 +1241,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 +1256,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 +1280,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 +1329,6 @@ compadr:
return "";
}
-
#define MAX_TMPS 2 /* max temporary registers used */
@@ -1095,13 +1342,13 @@ 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;
int offset = 0;
@@ -1110,7 +1357,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 +1393,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 +1410,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 +1421,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 +1441,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 +1452,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 +1461,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 +1486,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 +1529,6 @@ output_move_memory (operands, insn, length, tmp_start, n_operands)
return "";
}
-
int
standard_80387_constant_p (x)
@@ -1289,7 +1544,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 +1576,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 +1588,7 @@ output_move_const_single (operands)
REAL_VALUE_TO_TARGET_SINGLE (r, l);
operands[1] = GEN_INT (l);
}
+
return singlemove_string (operands);
}
@@ -1348,11 +1605,13 @@ symbolic_operand (op, mode)
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;
}
@@ -1374,9 +1633,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;
}
@@ -1392,9 +1652,10 @@ expander_call_insn_operand (op, mode)
&& (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,6 +1671,7 @@ 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;
@@ -1440,6 +1702,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,7 +1710,197 @@ symbolic_reference_mentioned_p (op)
return 0;
}
-/* This function generates the assembly code for function entry.
+/* 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. */
+
+int
+ix86_expand_binary_operator (code, mode, operands)
+ enum rtx_code code;
+ enum machine_mode mode;
+ rtx operands[];
+{
+ rtx insn;
+ int i;
+ int modified;
+
+ /* Recognize <var1> = <value> <op> <var1> for commutative operators */
+ if (GET_RTX_CLASS (code) == 'c'
+ && (rtx_equal_p (operands[0], operands[2])
+ || immediate_operand (operands[1], mode)))
+ {
+ rtx temp = operands[1];
+ operands[1] = operands[2];
+ operands[2] = temp;
+ }
+
+ /* 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]);
+
+ if (GET_CODE (operands[2]) == MEM)
+ operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
+
+ if (GET_CODE (operands[1]) == CONST_INT && code == MINUS)
+ {
+ rtx temp = gen_reg_rtx (GET_MODE (operands[0]));
+
+ emit_move_insn (temp, operands[1]);
+ operands[1] = temp;
+ return TRUE;
+ }
+ }
+
+ 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 ((! 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;
+ }
+
+ if (GET_CODE (operands[2]) == MEM)
+ {
+ operands[2] = force_reg (GET_MODE (operands[2]), operands[2]);
+ modified = TRUE;
+ }
+
+ if (GET_CODE (operands[1]) == CONST_INT && code == MINUS)
+ {
+ rtx temp = gen_reg_rtx (GET_MODE (operands[0]));
+
+ 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;
+ 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[];
+{
+ rtx insn;
+
+ /* 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;
+ enum machine_mode mode;
+ rtx operands[2];
+{
+ 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
+ with the return address of the caller and then returns. */
+
+void
+asm_output_function_prefix (file, name)
+ FILE *file;
+ char *name;
+{
+ 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 ();
+ sprintf (pic_label_name, "LPR%d", pic_label_no++);
+ LABEL_NAME (pic_label_rtx) = pic_label_name;
+ }
+
+ prologue_node = make_node (FUNCTION_DECL);
+ DECL_RESULT (prologue_node) = 0;
+#ifdef ASM_DECLARE_FUNCTION_NAME
+ ASM_DECLARE_FUNCTION_NAME (file, pic_label_name, prologue_node);
+#endif
+ 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. */
@@ -1456,23 +1909,188 @@ function_prologue (file, size)
FILE *file;
int size;
{
+ 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 ();
+ sprintf (pic_label_name, "LPR%d", 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,%P1), 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 (size);
+ xops[2] = GEN_INT (tsize);
+
if (frame_pointer_needed)
{
- output_asm_insn ("push%L1 %1", xops);
- output_asm_insn (AS2 (mov%L0,%0,%1), xops);
+ 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 (size)
- output_asm_insn (AS2 (sub%L0,%2,%0), xops);
+ 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!!
@@ -1483,39 +2101,69 @@ function_prologue (file, size)
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 (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)
- {
- xops[0] = pic_offset_table_rtx;
- xops[1] = (rtx) gen_label_rtx ();
-
- 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);
- }
+ 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.
+ 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. */
+ 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
-simple_386_epilogue ()
+ix86_can_use_return_insn_p ()
{
int regno;
int nregs = 0;
@@ -1540,7 +2188,6 @@ 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. */
@@ -1550,18 +2197,32 @@ function_epilogue (file, size)
FILE *file;
int size;
{
+ 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;
int offset;
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,25 +2231,37 @@ 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++)
@@ -1596,9 +2269,14 @@ function_epilogue (file, size)
|| (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used))
{
xops[0] = gen_rtx (REG, SImode, regno);
- output_asm_insn ("pop%L0 %0", xops);
+
+ 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])
@@ -1606,30 +2284,62 @@ function_epilogue (file, size)
{
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. */
+ xops[0] = GEN_INT (tsize);
- xops[0] = GEN_INT (size);
- output_asm_insn (AS2 (add%L2,%0,%2), xops);
+ 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);
+ }
+
+#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)
{
@@ -1643,17 +2353,37 @@ function_epilogue (file, size)
{
/* ??? 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);
+
+ 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
+ {
+ if (do_rtl)
+ emit_jump_insn (gen_return_pop_internal (xops[1]));
+ else
+ output_asm_insn ("ret %1", xops);
}
- 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 +2433,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 +2453,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 +2470,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 +2486,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 +2500,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 +2516,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 +2530,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 +2551,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 +2580,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 +2628,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.
@@ -1934,14 +2678,14 @@ legitimize_pic_address (orig, reg)
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));
+ 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,12 +2715,12 @@ 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
@@ -1987,11 +2731,10 @@ emit_pic_move (operands, mode)
rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
- operands[1] = (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.
@@ -2025,7 +2768,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 +2782,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 +2810,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,11 +2827,13 @@ 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
@@ -2173,7 +2919,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
@@ -2253,20 +2998,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 +3026,132 @@ 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:
+ fputs ("ge", file);
+ return;
+
+ case GT:
+ fputs ("g", file);
+ return;
+
+ case LE:
+ fputs ("le", file);
+ return;
+
+ case LT:
+ 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)
@@ -2406,6 +3267,33 @@ print_operand (file, x, code)
}
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:
{
char str[50];
@@ -2415,10 +3303,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,25 +3322,34 @@ 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);
}
+
/* 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);
@@ -2507,38 +3406,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 +3455,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 +3487,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 +3498,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;
@@ -2645,6 +3541,7 @@ 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.
@@ -2656,29 +3553,37 @@ notice_update_cc (exp)
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 +3591,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 +3606,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. */
@@ -2725,14 +3631,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 (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
@@ -2761,9 +3674,7 @@ split_di (operands, num, lo_half, hi_half)
hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1);
}
else if (CONSTANT_P (operands[num]))
- {
- split_double (operands[num], &lo_half[num], &hi_half[num]);
- }
+ split_double (operands[num], &lo_half[num], &hi_half[num]);
else if (offsettable_memref_p (operands[num]))
{
lo_half[num] = operands[num];
@@ -2797,7 +3708,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. */
@@ -2908,12 +3818,13 @@ 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])))
@@ -2935,12 +3846,13 @@ 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]))
@@ -2983,8 +3895,8 @@ 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])
+ || (GET_MODE (operands[0]) == DImode && ! stack_top_dies))
abort ();
xops[0] = GEN_INT (12);
@@ -2997,7 +3909,8 @@ 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)
@@ -3024,7 +3937,22 @@ 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 (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 +3968,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 +3998,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 +4011,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);
}
@@ -3092,7 +4043,32 @@ output_fp_cc0_set (insn)
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,12 +4078,22 @@ 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 ();
@@ -3168,7 +4154,8 @@ output_fp_cc0_set (insn)
default:
abort ();
}
- RET;
+
+ return "";
}
#define MAX_386_STACK_LOCALS 2
@@ -3243,3 +4230,810 @@ 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;
+{
+ return (GET_CODE (op) == MULT);
+}
+
+int is_div(op,mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ 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;
+{
+ 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 (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;
+ }
+
+ 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 "";
+}
diff --git a/gnu/usr.bin/gcc/config/i386/i386.h b/gnu/usr.bin/gcc/config/i386/i386.h
index b00b0e509c5..6fb08a120d2 100644
--- a/gnu/usr.bin/gcc/config/i386/i386.h
+++ b/gnu/usr.bin/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, 1997 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,77 @@ extern int target_flags;
#define SUBTARGET_SWITCHES
#define SUBTARGET_OPTIONS
+/* Define this to change the optimizations performed by default. */
+#define OPTIMIZATION_OPTIONS(LEVEL) optimization_options(LEVEL)
+
+/* 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
+
+#ifndef CPP_CPU_SPEC
+#ifdef __STDC__
+#if TARGET_CPU_DEFAULT == 1
+#define CPP_CPU_DEFAULT "-Di486"
+#else
+#if TARGET_CPU_DEFAULT == 2
+#define CPP_CPU_DEFAULT "-Di586"
+#else
+#if TARGET_CPU_DEFAULT == 3
+#define CPP_CPU_DEFAULT "-Di686"
+#else
+#define CPP_CPU_DEFAULT ""
+#endif
+#endif
+#endif /* TARGET_CPU_DEFAULT */
+
+#define CPP_CPU_SPEC "\
+-Di386 " CPP_CPU_DEFAULT " -Asystem(unix) -Acpu(i386) -Amachine(i386) \
+%{mcpu=i486:-Di486} %{m486:-Di486} \
+%{mpentium:-Dpentium -Di586} %{mcpu=pentium:-Dpentium -Di586} \
+%{mpentiumpro:-Dpentiumpro -Di686} %{mcpu=pentiumpro:-Dpentiumpro -Di686}"
+
+#else
+#define CPP_CPU_SPEC "\
+-Di386 -Asystem(unix) -Acpu(i386) -Amachine(i386) \
+%{mcpu=i486:-Di486} %{m486:-Di486} \
+%{mpentium:-Dpentium -Di586} %{mcpu=pentium:-Dpentium -Di586} \
+%{mpentiumpro:-Dpentiumpro -Di686} %{mcpu=pentiumpro:-Dpentiumpro -Di686}"
+#endif /* __STDC__ */
+#endif /* CPP_CPU_SPEC */
+
+#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_cpu", CPP_CPU_SPEC }, \
+ { "cc1_cpu", CC1_CPU_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
/* target machine storage layout */
@@ -265,6 +424,9 @@ extern int target_flags;
aligned on 64 bit boundaries. */
#define BIGGEST_ALIGNMENT (TARGET_ALIGN_DOUBLE ? 64 : 32)
+/* align DFmode constants and nonaggregates */
+#define ALIGN_DFmode (!TARGET_386)
+
/* Set this non-zero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 0
@@ -274,6 +436,12 @@ extern int target_flags;
/* Required on the 386 since it doesn't have bitfield insns. */
#define PCC_BITFIELD_TYPE_MATTERS 1
+/* An integer expression for the size in bits of the largest integer
+ machine mode that should actually be used. All integer machine modes of
+ this size or smaller can be used for structures and unions with the
+ appropriate sizes. */
+#define MAX_FIXED_MODE_SIZE 32
+
/* Maximum power of 2 that code can be aligned to. */
#define MAX_CODE_ALIGN 6 /* 64 byte alignment */
@@ -292,6 +460,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
@@ -414,8 +583,9 @@ extern int target_flags;
: 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.
@@ -424,17 +594,6 @@ extern int target_flags;
#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)
-
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
@@ -459,7 +618,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
@@ -567,7 +726,7 @@ enum reg_class
0x3, /* AD_REGS */ \
0xf, /* Q_REGS */ \
0x10, 0x20, /* SIREG, DIREG */ \
- 0x07f, /* INDEX_REGS */ \
+ 0x7f, /* INDEX_REGS */ \
0x100ff, /* GENERAL_REGS */ \
0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \
0xff00, /* FLOAT_REGS */ \
@@ -584,7 +743,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,6 +817,7 @@ 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.
@@ -825,7 +985,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 +1018,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 +1055,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 +1150,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[5] = stack_pointer_rtx; \
- xops[6] = GEN_INT (4); \
xops[7] = gen_rtx (REG, Pmode, 0); /* eax */ \
\
CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \
- CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \
- \
- output_asm_insn (AS2(cmp%L4,%0,%4), xops); \
- output_asm_insn (AS1(jne,%2), xops); \
\
- if (!flag_pic) \
- output_asm_insn (AS1(push%L1,%1), xops); \
- else \
+ 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 +1433,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. */
@@ -1094,8 +1524,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 (); \
@@ -1245,6 +1676,8 @@ do { \
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 +1712,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 = %s\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)); \
@@ -1369,22 +1811,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 +1854,192 @@ 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: \
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); \
+ else \
+ 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 +2052,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) 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 +2271,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 +2283,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.
@@ -1609,6 +2369,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. */
@@ -1698,13 +2474,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.
*/
@@ -1853,13 +2629,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))
+/* 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 +2661,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 +2674,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 +2700,37 @@ 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 ();
+
+#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=<xxx> */
+extern char *ix86_arch_string; /* for -march=<xxx> */
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 +2739,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/gnu/usr.bin/gcc/config/i386/i386.md b/gnu/usr.bin/gcc/config/i386/i386.md
index ff0119631cb..ea72a98a65e 100644
--- a/gnu/usr.bin/gcc/config/i386/i386.md
+++ b/gnu/usr.bin/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, 1994, 1995, 1996, 1997 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,71 @@
;; 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.
+
+;; 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 +136,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"))]
@@ -228,7 +298,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"
@@ -346,11 +416,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 +455,16 @@
(define_insn ""
[(set (cc0)
(match_operator 2 "VOIDmode_compare_op"
+ [(float_extend:XF
+ (match_operand:DF 1 "nonimmediate_operand" "fm"))
+ (match_operand:XF 0 "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"))]))
@@ -453,6 +532,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 +609,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 +623,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 +664,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 +711,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 +769,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 +802,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 +816,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")))]
""
"*
{
@@ -742,22 +835,22 @@
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "general_operand" "g"))]
- "TARGET_386"
+ "TARGET_PUSH_MEMORY"
"push%L0 %1")
-;; On a 486, it is faster to move MEM to a REG and then push, rather than
+;; If not a 386, it is faster to move MEM to a REG and then push, rather than
;; push MEM directly.
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "nonmemory_operand" "ri"))]
- "!TARGET_386 && TARGET_MOVE"
+ "!TARGET_PUSH_MEMORY && TARGET_MOVE"
"push%L0 %1")
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "ri"))]
- "!TARGET_386 && !TARGET_MOVE"
+ (match_operand:SI 1 "nonmemory_operand" "ri"))]
+ "!TARGET_PUSH_MEMORY && !TARGET_MOVE"
"push%L0 %1")
;; General case of fullword move.
@@ -819,19 +912,19 @@
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "general_operand" "g"))]
- "TARGET_386"
+ "TARGET_PUSH_MEMORY"
"push%W0 %1")
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "nonmemory_operand" "ri"))]
- "!TARGET_386 && TARGET_MOVE"
+ "!TARGET_PUSH_MEMORY && TARGET_MOVE"
"push%W0 %1")
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
- (match_operand:HI 1 "general_operand" "ri"))]
- "!TARGET_386 && !TARGET_MOVE"
+ (match_operand:HI 1 "nonmemory_operand" "ri"))]
+ "!TARGET_PUSH_MEMORY && !TARGET_MOVE"
"push%W0 %1")
;; On i486, an incl and movl are both faster than incw and movw.
@@ -876,10 +969,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,13 +1036,13 @@
;; 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"))]
+ (match_operand:QI 1 "register_operand" "q"))]
"!TARGET_MOVE"
"*
{
@@ -978,14 +1082,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,r,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))
@@ -1032,7 +1136,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)"
"*
@@ -1083,16 +1187,28 @@
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
+ /* 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 ((reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) != MEM
&& GET_CODE (operands[1]) == CONST_DOUBLE
&& !standard_80387_constant_p (operands[1]))
{
- current_function_uses_pic_offset_table = 1;
+ rtx insn, note, fp_const;
+
+ fp_const = force_const_mem (SFmode, operands[1]);
+ if (flag_pic)
+ current_function_uses_pic_offset_table = 1;
+
+ insn = emit_insn (gen_rtx (SET, SFmode, operands[0], fp_const));
+ note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+
+ if (note)
+ XEXP (note, 0) = operands[1];
+ else
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn));
}
}")
@@ -1176,7 +1292,7 @@
;; For the purposes of regclass, prefer FLOAT_REGS.
(define_insn "movsf_normal"
- [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm")
+ [(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 +1319,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 +1344,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")
@@ -1264,16 +1382,28 @@
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
+ /* 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 ((reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) != MEM
&& GET_CODE (operands[1]) == CONST_DOUBLE
&& !standard_80387_constant_p (operands[1]))
{
- current_function_uses_pic_offset_table = 1;
+ rtx insn, note, fp_const;
+
+ fp_const = force_const_mem (DFmode, operands[1]);
+ if (flag_pic)
+ current_function_uses_pic_offset_table = 1;
+
+ insn = emit_insn (gen_rtx (SET, DFmode, operands[0], fp_const));
+ note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+
+ if (note)
+ XEXP (note, 0) = operands[1];
+ else
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn));
}
}")
@@ -1346,10 +1476,11 @@
"* 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 +1505,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 +1530,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")
@@ -1435,16 +1569,28 @@
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
+ /* 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 ((reload_in_progress | reload_completed) == 0
&& GET_CODE (operands[0]) != MEM
&& GET_CODE (operands[1]) == CONST_DOUBLE
&& !standard_80387_constant_p (operands[1]))
{
- current_function_uses_pic_offset_table = 1;
+ rtx insn, note, fp_const;
+
+ fp_const = force_const_mem (XFmode, operands[1]);
+ if (flag_pic)
+ current_function_uses_pic_offset_table = 1;
+
+ insn = emit_insn (gen_rtx (SET, XFmode, operands[0], fp_const));
+ note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+
+ if (note)
+ XEXP (note, 0) = operands[1];
+ else
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn));
}
}")
@@ -1514,10 +1660,11 @@
""
"* 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 +1689,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 +1717,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)
@@ -1623,21 +1770,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_rtx (CONST_INT, VOIDmode, 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 +1811,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_rtx (CONST_INT, VOIDmode, 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,22 +1874,89 @@
#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]))
{
- 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,%0,%0),operands);
+ output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
+ }
+ else
+ {
+ xops[0] = operands[0];
+ xops[1] = gen_rtx (CONST_INT, VOIDmode, 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)
+ {
+ xops[0] = operands[0];
+ xops[1] = gen_rtx (CONST_INT, VOIDmode, 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;
+ }
#ifdef INTEL_SYNTAX
return AS2 (movzx,%1,%0);
@@ -1694,23 +1965,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")))]
""
"*
{
@@ -1736,9 +2061,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 +2082,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 +2099,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 +2110,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 +2189,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 +2208,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 +2224,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 +2243,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 +2259,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 +2320,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 +2335,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 +2353,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 +2368,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 +2410,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 +2431,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 +2452,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 +2472,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 +2490,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 +2508,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")
+ [(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")
+ [(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")
+ [(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 +2556,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 +2570,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 +2584,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 +2652,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 +2727,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 +2761,137 @@
;;- add instructions
+(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"))]
+ ""
+ "*
+{
+ rtx low[3], high[3], xops[7], temp;
+
+ 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 (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 "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"))]
+ ""
+ "*
+{
+ rtx low[3], high[3], xops[7], temp;
+
+ 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)
+ {
+ 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,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"))]
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,!&r,!o,!o")
+ (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0iF,or,riF,o")
+ (match_operand:DI 2 "general_operand" "o,riF,or,or,oriF,o")))
+ (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r"))]
""
"*
{
@@ -2456,14 +2963,23 @@
;; 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_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]) && REGNO (operands[0]) != REGNO (operands[1]))
+ 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);
@@ -2483,34 +2999,85 @@
operands[1] = SET_SRC (PATTERN (insn));
return AS2 (lea%L0,%a1,%0);
}
-
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
}
+ 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 +3091,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 +3124,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 +3159,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")))]
; ""
; "*
;{
@@ -2578,40 +3174,12 @@
; 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 +3199,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 +3314,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 +3393,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 +3412,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 +3428,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 +3470,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 +3480,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 +3509,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 +3551,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 +3563,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 +3588,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 +3603,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 +3612,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 +3637,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]))
+ {
+ rtx tmp;
+ tmp = operands[1];
+ operands[1] = operands[2];
+ operands[2] = tmp;
+ }
+ switch (GET_CODE (operands[2]))
{
- if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
+ 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 +3675,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 +3692,107 @@
#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;
+ }
}
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 +3831,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 +3889,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,37 +3901,87 @@
;;- 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;
+
+ 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);
- return AS2 (or%B0,%2,%b0);
+ 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);
+ }
- return AS2 (or%B0,%2,%h0);
+ operands[0] = adj_offsettable_operand (operands[0], 1);
+ goto byte_or_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_or_operation;
+ }
+
+ /* fourth byte? */
+ if ((intval & ~0xff000000) == 0)
+ {
+ intval = (intval >> 24) & 0xff;
+ operands[0] = adj_offsettable_operand (operands[0], 3);
+ goto byte_or_operation;
}
}
@@ -3186,87 +3989,172 @@
}")
(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;
+
+ if (intval == 0xff)
+ return AS2 (mov%B0,%2,%b0);
- return AS2 (or%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);
+ }
+
+ operands[0] = adj_offsettable_operand (operands[0], 1);
- return AS2 (or%B0,%2,%h0);
+ goto byte_or_operation;
}
}
+ 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;
}
}
@@ -3274,8 +4162,8 @@
}")
(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")))]
""
"*
@@ -3312,12 +4200,31 @@
}
}
+ 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 "general_operand" "=qm,q")
- (xor:QI (match_operand:QI 1 "general_operand" "%0,0")
+ [(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);")
@@ -3345,50 +4252,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 +4303,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 +4352,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 +4366,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 +4465,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 +4495,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,34 +4530,28 @@
(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];
+ static HOST_WIDE_INT ashldi_label_number;
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);
-
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);
+ asm_fprintf (asm_out_file, \"\\tje %LLASHLDI%d\\n\", ashldi_label_number);
+ output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */
+ output_asm_insn (AS2 (xor%L2,%2,%2), xops);
+ asm_fprintf (asm_out_file, \"%LLASHLDI%d:\\n\", ashldi_label_number++);
RET;
}")
@@ -3668,15 +4561,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);
@@ -3706,8 +4599,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 +4615,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 +4652,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 +4718,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];
+ static HOST_WIDE_INT ashrdi_label_number;
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);
-
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);
+ asm_fprintf (asm_out_file, \"\\tje %LLASHRDI%d\\n\", ashrdi_label_number);
+ 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_fprintf (asm_out_file, \"%LLASHRDI%d:\\n\", ashrdi_label_number++);
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 +4759,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 +4772,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 +4808,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 +4873,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];
+ static HOST_WIDE_INT lshrdi_label_number;
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);
-
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);
+ asm_fprintf (asm_out_file, \"\\tje %LLLSHRDI%d\\n\", lshrdi_label_number);
+ output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */
+ output_asm_insn (AS2 (xor%L3,%3,%3), xops);
+ asm_fprintf (asm_out_file, \"%LLLSHRDI%d:\\n\", lshrdi_label_number++);
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 +4913,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 +4926,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 +4941,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 +4954,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 +4967,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 +4980,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 +4993,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 +5006,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 +5022,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"))]
""
"*
{
@@ -4130,7 +5064,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 +5077,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 +5091,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 +5109,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 +5122,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 +5147,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 +5190,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 +5321,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 +5354,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 +5387,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 +5420,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 +5475,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 +5515,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 +5545,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 +5597,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 +5649,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 +5700,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 +5747,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 +5769,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 +5788,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 +5819,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 +5851,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 +5882,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 +5914,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 +5942,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 +5957,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 +5969,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 +5993,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 +6104,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 +6119,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;
}")
@@ -5066,7 +6186,7 @@
}")
(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,6 +6432,7 @@
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)
@@ -5344,19 +6465,148 @@
;; This is only done if the function's epilogue is known to be simple.
;; See comments for simple_386_epilogue in i386.c.
-(define_insn "return"
+(define_expand "return"
[(return)]
- "simple_386_epilogue ()"
+ "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))]
+ ""
"*
{
- function_epilogue (asm_out_file, get_frame_size ());
+ rtx xops [2];
+
+ xops[0] = operands[0];
+ xops[1] = stack_pointer_rtx;
+ output_asm_insn (AS2 (sub%L1,%0,%1), xops);
RET;
}")
-(define_insn "nop"
- [(const_int 0)]
+(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))]
""
- "nop")
+ "*
+{
+ 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+[.-%%P2],%%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,%P1), operands);
+ if (! TARGET_DEEP_BRANCH_PREDICTION)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1]));
+ }
+ RET;
+}")
+
+(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,%P1), 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_+[.-%P1],%0\", operands);
+ RET;
+}")
+
+(define_expand "epilogue"
+ [(const_int 1)]
+ ""
+ "
+{
+ ix86_expand_epilogue ();
+ DONE;
+}")
+
+(define_insn "epilogue_set_stack_ptr"
+ [(set (reg:SI 7) (reg:SI 6))
+ (clobber (reg:SI 6))]
+ ""
+ "*
+{
+ 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 "leave"
+ [(const_int 2)
+ (clobber (reg:SI 6))
+ (clobber (reg:SI 7))]
+ ""
+ "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 +6630,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 +6676,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" "")
@@ -5464,7 +6781,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 +6792,7 @@
""
"*
{
- rtx xops[4], label;
+ rtx xops[2], label;
label = gen_label_rtx ();
@@ -5485,16 +6802,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;
}")
@@ -5523,6 +6837,7 @@
return \"repz\;cmps%B2\";
}")
+
(define_expand "ffssi2"
[(set (match_dup 2)
(plus:SI (ffs:SI (match_operand:SI 1 "general_operand" ""))
@@ -5537,8 +6852,8 @@
;; 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"))
+ [(set (match_operand:SI 0 "register_operand" "=&r")
+ (plus:SI (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm"))
(const_int -1)))]
""
"*
@@ -5570,6 +6885,7 @@
output_asm_insn (buffer, xops);
ffssi_label_number++;
+ CC_STATUS_INIT;
return \"\";
}")
@@ -5583,8 +6899,8 @@
"operands[2] = gen_reg_rtx (HImode);")
(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=&r")
- (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm"))
+ [(set (match_operand:HI 0 "register_operand" "=&r")
+ (plus:HI (ffs:HI (match_operand:SI 1 "nonimmediate_operand" "rm"))
(const_int -1)))]
""
"*
@@ -5616,6 +6932,7 @@
output_asm_insn (buffer, xops);
ffshi_label_number++;
+ CC_STATUS_INIT;
return \"\";
}")
@@ -5633,81 +6950,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 +7122,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 +7234,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 +7248,454 @@
output_asm_insn (AS2 (mov%L0,%1,%0), xops);
return \"repnz\;scas%B2\";
}")
+
+/* Conditional move define_insns. */
+
+(define_expand "movsicc"
+ [(match_dup 4)
+ (parallel [(set (match_operand 0 "register_operand" "")
+ (if_then_else:SI (match_operand 1 "comparison_operator" "")
+ (match_operand:SI 2 "general_operand" "")
+ (match_operand:SI 3 "general_operand" "")))
+ (clobber (match_scratch:SI 4 "=&r"))])]
+ "TARGET_CMOVE"
+ "
+{
+ operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+}")
+
+(define_expand "movhicc"
+ [(match_dup 4)
+ (parallel [(set (match_operand 0 "register_operand" "")
+ (if_then_else:HI (match_operand 1 "comparison_operator" "")
+ (match_operand:HI 2 "general_operand" "")
+ (match_operand:HI 3 "general_operand" "")))
+ (clobber (match_scratch:SI 4 "=&r"))])]
+ "TARGET_CMOVE"
+ "
+{
+ operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+}")
+
+(define_insn "movsicc_1"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,&r,rm")
+ (if_then_else:SI (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:SI 2 "general_operand" "rm,0,rm,g")
+ (match_operand:SI 3 "general_operand" "0,rm,rm,g")))
+ (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
+ "TARGET_CMOVE"
+ "*
+{
+ if (which_alternative == 0)
+ {
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ }
+ else if (which_alternative == 1)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ }
+ else if (which_alternative == 2)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ }
+ else if (which_alternative == 3)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ rtx xops[3];
+
+ xops[0] = gen_label_rtx ();
+ xops[1] = gen_label_rtx ();
+ xops[2] = operands[1];
+
+ output_asm_insn (\"j%c2 %l0\", xops);
+ if (! rtx_equal_p (operands[0], operands[2]))
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
+ {
+ output_asm_insn (AS2 (mov%z2,%2,%4), operands);
+ output_asm_insn (AS2 (mov%z2,%4,%0), operands);
+ }
+ else
+ output_asm_insn (AS2 (mov%z0,%2,%0), operands);
+ output_asm_insn (\"jmp %l1\", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
+ if (! rtx_equal_p (operands[0], operands[3]))
+ {
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
+ {
+ output_asm_insn (AS2 (mov%z2,%3,%4), operands);
+ output_asm_insn (AS2 (mov%z2,%4,%0), operands);
+ }
+ else
+ output_asm_insn (AS2 (mov%z0,%3,%0), operands);
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
+ }
+ RET;
+}")
+
+(define_insn "movhicc_1"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,&r,rm")
+ (if_then_else:HI (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:HI 2 "general_operand" "rm,0,rm,g")
+ (match_operand:HI 3 "general_operand" "0,rm,rm,g")))
+ (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
+ "TARGET_CMOVE"
+ "*
+{
+ if (which_alternative == 0)
+ {
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ }
+ else if (which_alternative == 1)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ }
+ else if (which_alternative == 2)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+ output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+ }
+ else if (which_alternative == 3)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ rtx xops[3];
+
+ xops[0] = gen_label_rtx ();
+ xops[1] = gen_label_rtx ();
+ xops[2] = operands[1];
+
+ output_asm_insn (\"j%c2 %l0\", xops);
+ if (! rtx_equal_p (operands[0], operands[2]))
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
+ {
+ output_asm_insn (AS2 (mov%z2,%2,%4), operands);
+ output_asm_insn (AS2 (mov%z2,%4,%0), operands);
+ }
+ else
+ output_asm_insn (AS2 (mov%z0,%2,%0), operands);
+ output_asm_insn (\"jmp %l1\", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
+ if (! rtx_equal_p (operands[0], operands[3]))
+ {
+ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
+ {
+ output_asm_insn (AS2 (mov%z2,%3,%4), operands);
+ output_asm_insn (AS2 (mov%z2,%4,%0), operands);
+ }
+ else
+ output_asm_insn (AS2 (mov%z0,%3,%0), operands);
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
+ }
+ RET;
+}")
+
+(define_expand "movsfcc"
+ [(match_dup 4)
+ (set (match_operand 0 "general_operand" "")
+ (if_then_else:SF (match_operand 1 "comparison_operator" "")
+ (match_operand:SF 2 "general_operand" "")
+ (match_operand:SF 3 "general_operand" "")))]
+ "TARGET_CMOVE"
+ "
+{
+ int i;
+
+ for (i = 2; i <= 3; i++)
+ {
+ if ((reload_in_progress | reload_completed) == 0
+ && CONSTANT_P (operands[i]))
+ {
+ operands[i] = force_const_mem (SFmode, operands[i]);
+ }
+ }
+ operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+}")
+
+(define_expand "movdfcc"
+ [(match_dup 4)
+ (set (match_operand 0 "register_operand" "t")
+ (if_then_else:DF (match_operand 1 "comparison_operator" "")
+ (match_operand:DF 2 "general_operand" "")
+ (match_operand:DF 3 "general_operand" "")))]
+ "TARGET_CMOVE"
+ "
+{
+ int i;
+
+ for (i = 2; i <= 3; i++)
+ {
+ if ((reload_in_progress | reload_completed) == 0
+ && CONSTANT_P (operands[i]))
+ {
+ operands[i] = force_const_mem (DFmode, operands[i]);
+ }
+ }
+ operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+}")
+
+(define_expand "movxfcc"
+ [(match_dup 4)
+ (set (match_operand 0 "register_operand" "t")
+ (if_then_else:XF (match_operand 1 "comparison_operator" "")
+ (match_operand:XF 2 "general_operand" "")
+ (match_operand:XF 3 "general_operand" "")))]
+ "TARGET_CMOVE"
+ "
+{
+ int i;
+
+ for (i = 2; i <= 3; i++)
+ {
+ if ((reload_in_progress | reload_completed) == 0
+ && CONSTANT_P (operands[i]))
+ {
+ operands[i] = force_const_mem (XFmode, operands[i]);
+ }
+ }
+ operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+}")
+
+(define_insn "movsfcc_1"
+ [(set (match_operand:SF 0 "general_operand" "=f,=f,=f,=f")
+ (if_then_else:SF (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:SF 2 "general_operand" "0,f,f,fFm")
+ (match_operand:SF 3 "general_operand" "f,0,f,fFm")))]
+ "TARGET_CMOVE"
+ "*
+{
+ if (which_alternative == 0)
+ {
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 1)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ }
+ else if (which_alternative == 2)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 3)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ rtx xops[3];
+
+ xops[0] = gen_label_rtx ();
+ xops[1] = gen_label_rtx ();
+ xops[2] = operands[1];
+
+ output_asm_insn (\"j%f2 %l0\", xops);
+ if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM)
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ else
+ {
+ operands[2] = XEXP (operands[2], 0);
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ }
+ output_asm_insn (\"jmp %l1\", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
+ if (STACK_REG_P (operands[3]) || GET_CODE (operands[0]) == MEM)
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ else
+ {
+ operands[3] = XEXP (operands[3], 0);
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
+}
+ RET;
+}")
+
+(define_insn "movdfcc_1"
+ [(set (match_operand:DF 0 "general_operand" "=f,=f,=f,=f")
+ (if_then_else:DF (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:DF 2 "general_operand" "0,f,f,fFm")
+ (match_operand:DF 3 "general_operand" "f,0,f,fFm")))]
+ "TARGET_CMOVE"
+ "*
+{
+ if (which_alternative == 0)
+ {
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 1)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ }
+ else if (which_alternative == 2)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 3)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ rtx xops[3];
+
+ xops[0] = gen_label_rtx ();
+ xops[1] = gen_label_rtx ();
+ xops[2] = operands[1];
+
+ output_asm_insn (\"j%f2 %l0\", xops);
+ if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM)
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ else
+ {
+ operands[2] = XEXP (operands[2], 0);
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ }
+ output_asm_insn (\"jmp %l1\", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
+ if (STACK_REG_P (operands[3]) || GET_CODE (operands[0]) == MEM)
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ else
+ {
+ operands[3] = XEXP (operands[3], 0);
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
+}
+ RET;
+}")
+
+(define_insn "movxfcc_1"
+ [(set (match_operand:XF 0 "register_operand" "=f,=f,=f,=f")
+ (if_then_else:XF (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:XF 2 "register_operand" "0,f,f,fFm")
+ (match_operand:XF 3 "register_operand" "f,0,f,fFm")))]
+ "TARGET_CMOVE"
+ "*
+{
+ if (which_alternative == 0)
+ {
+ /* r <- cond ? arg : r */
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 1)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ }
+ else if (which_alternative == 2)
+ {
+ /* r <- cond ? r : arg */
+ output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+ output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+ }
+ else if (which_alternative == 3)
+ {
+ /* r <- cond ? arg1 : arg2 */
+ rtx xops[3];
+
+ xops[0] = gen_label_rtx ();
+ xops[1] = gen_label_rtx ();
+ xops[2] = operands[1];
+
+ output_asm_insn (\"j%f2 %l0\", xops);
+ if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM)
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ else
+ {
+ operands[2] = XEXP (operands[2], 0);
+ output_asm_insn (AS1 (fld%z2,%y2), operands);
+ }
+ output_asm_insn (\"jmp %l1\", xops);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
+ if (STACK_REG_P (operands[3]) || GET_CODE (operands[0]) == MEM)
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ else
+ {
+ operands[3] = XEXP (operands[3], 0);
+ output_asm_insn (AS1 (fld%z3,%y3), operands);
+ }
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
+}
+ RET;
+}")
+
+(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 "nonlocal_goto_receiver"
+ [(const_int 0)]
+ "flag_pic"
+ "
+{
+ load_pic_register (1);
+ DONE;
+}")
diff --git a/gnu/usr.bin/gcc/config/i386/isc.h b/gnu/usr.bin/gcc/config/i386/isc.h
index cf8c5f69277..d0b2dcc7a55 100644
--- a/gnu/usr.bin/gcc/config/i386/isc.h
+++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/linux-aout.h b/gnu/usr.bin/gcc/config/i386/linux-aout.h
index 7e46c68b8ec..8bf3daa5613 100644
--- a/gnu/usr.bin/gcc/config/i386/linux-aout.h
+++ b/gnu/usr.bin/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 Free Software Foundation, Inc.
Contributed by H.J. Lu (hjl@nynexst.com)
This file is part of GNU CC.
@@ -28,14 +28,10 @@ Boston, MA 02111-1307, USA. */
/* 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) %[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 +53,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/gnu/usr.bin/gcc/config/i386/linux-oldld.h b/gnu/usr.bin/gcc/config/i386/linux-oldld.h
index c3066ba1333..9c6c21f79d4 100644
--- a/gnu/usr.bin/gcc/config/i386/linux-oldld.h
+++ b/gnu/usr.bin/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 Free Software Foundation, Inc.
Contributed by Michael Meissner (meissner@cygnus.com)
This file is part of GNU CC.
@@ -28,14 +29,10 @@ Boston, MA 02111-1307, USA. */
/* 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) %[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 +54,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/gnu/usr.bin/gcc/config/i386/linux.h b/gnu/usr.bin/gcc/config/i386/linux.h
index f077de57efb..df27c603603 100644
--- a/gnu/usr.bin/gcc/config/i386/linux.h
+++ b/gnu/usr.bin/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 Free Software Foundation, Inc.
Contributed by Eric Youngdale.
Modified for stabs-in-ELF by H.J. Lu.
@@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */
#include <linux.h> /* some common stuff */
#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (i386 Linux/ELF)");
+#define TARGET_VERSION fprintf (stderr, " (i386 GNU/Linux with ELF)");
/* The svr4 ABI for the i386 says that records and unions are returned
in memory. */
@@ -148,32 +148,19 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE_SIZE BITS_PER_WORD
#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 -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}"
+#ifdef USE_GNULIBC_1
+#define CPP_SPEC "%(cpp_cpu) %[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) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#endif
-#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 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
+#undef CC1_SPEC
+#define CC1_SPEC "%(cc1_cpu) %{profile:-p}"
-/* Provide a LINK_SPEC appropriate for Linux. Here we provide support
+/* 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
@@ -190,6 +177,7 @@ Boston, MA 02111-1307, USA. */
/* 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 elf_i386 %{shared:-shared} \
%{!shared: \
@@ -207,6 +195,23 @@ Boston, MA 02111-1307, USA. */
%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
%{static:-static}}}"
#endif
+#else
+#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{static:-static}}}"
+#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)
diff --git a/gnu/usr.bin/gcc/config/i386/lynx.h b/gnu/usr.bin/gcc/config/i386/lynx.h
index 4ac00a052ba..73111f916a5 100644
--- a/gnu/usr.bin/gcc/config/i386/lynx.h
+++ b/gnu/usr.bin/gcc/config/i386/lynx.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running LynxOS.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,12 +24,12 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dunix -Di386 -DI386 -DLynx -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(i386) -Amachine(i386)"
-/* This is how to output a reference to a user-level label named NAME. */
+/* The prefix to add to user-visible assembler symbols. */
/* Override the svr3 convention of adding a leading underscore. */
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME)
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
/* Apparently LynxOS clobbers ebx when you call into the OS. */
diff --git a/gnu/usr.bin/gcc/config/i386/next.h b/gnu/usr.bin/gcc/config/i386/next.h
index c0d6d7296f1..8dd46f5cd41 100644
--- a/gnu/usr.bin/gcc/config/i386/next.h
+++ b/gnu/usr.bin/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 \
diff --git a/gnu/usr.bin/gcc/config/i386/osfelf.h b/gnu/usr.bin/gcc/config/i386/osfelf.h
index 7e71fe98f6b..4604a341175 100644
--- a/gnu/usr.bin/gcc/config/i386/osfelf.h
+++ b/gnu/usr.bin/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) %[cpp_cpu] \
%{mrose: -D__ROSE__ %{!pic-none: -D__SHARED__}} \
%{!mrose: -D__ELF__ %{fpic: -D__SHARED__}} \
%{mno-underscores: -D__NO_UNDERSCORES__} \
diff --git a/gnu/usr.bin/gcc/config/i386/osfrose.h b/gnu/usr.bin/gcc/config/i386/osfrose.h
index 3aae1e1b681..fd4c3a8eb28 100644
--- a/gnu/usr.bin/gcc/config/i386/osfrose.h
+++ b/gnu/usr.bin/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) %[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
diff --git a/gnu/usr.bin/gcc/config/i386/sco.h b/gnu/usr.bin/gcc/config/i386/sco.h
index 37dc0326698..9c94a766a83 100644
--- a/gnu/usr.bin/gcc/config/i386/sco.h
+++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/sco4.h b/gnu/usr.bin/gcc/config/i386/sco4.h
index fc389b4d1bc..1b17d674cd5 100644
--- a/gnu/usr.bin/gcc/config/i386/sco4.h
+++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/sco4dbx.h b/gnu/usr.bin/gcc/config/i386/sco4dbx.h
index 0387c2436c3..6ff5714c56b 100644
--- a/gnu/usr.bin/gcc/config/i386/sco4dbx.h
+++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/scodbx.h b/gnu/usr.bin/gcc/config/i386/scodbx.h
index 1309735cf1e..a2581d4257f 100644
--- a/gnu/usr.bin/gcc/config/i386/scodbx.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/seq-gas.h b/gnu/usr.bin/gcc/config/i386/seq-gas.h
index 2ee071925bc..796eaa24d62 100644
--- a/gnu/usr.bin/gcc/config/i386/seq-gas.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/seq-sysv3.h b/gnu/usr.bin/gcc/config/i386/seq-sysv3.h
index e3182ee1a77..9e8388d47d7 100644
--- a/gnu/usr.bin/gcc/config/i386/seq-sysv3.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/sol2.h b/gnu/usr.bin/gcc/config/i386/sol2.h
index cc5ebca7d7e..64172359c4e 100644
--- a/gnu/usr.bin/gcc/config/i386/sol2.h
+++ b/gnu/usr.bin/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 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) %[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}%{!pg: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} \
@@ -76,16 +85,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/gnu/usr.bin/gcc/config/i386/sun386.h b/gnu/usr.bin/gcc/config/i386/sun386.h
index 6e2680789bd..4d4d66c181a 100644
--- a/gnu/usr.bin/gcc/config/i386/sun386.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/svr3.ifile b/gnu/usr.bin/gcc/config/i386/svr3.ifile
index f0bb3a0f8dc..32b3ddc2bf3 100644
--- a/gnu/usr.bin/gcc/config/i386/svr3.ifile
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/svr3dbx.h b/gnu/usr.bin/gcc/config/i386/svr3dbx.h
index d3348d55292..c394747ab9a 100644
--- a/gnu/usr.bin/gcc/config/i386/svr3dbx.h
+++ b/gnu/usr.bin/gcc/config/i386/svr3dbx.h
@@ -66,17 +66,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/gnu/usr.bin/gcc/config/i386/svr3gas.h b/gnu/usr.bin/gcc/config/i386/svr3gas.h
index 401c7661e27..a288b84e524 100644
--- a/gnu/usr.bin/gcc/config/i386/svr3gas.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/svr3z.ifile b/gnu/usr.bin/gcc/config/i386/svr3z.ifile
index 4fdbb937c57..4946051235e 100644
--- a/gnu/usr.bin/gcc/config/i386/svr3z.ifile
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/sysv3.h b/gnu/usr.bin/gcc/config/i386/sysv3.h
index 8c5cfc41587..b6a1fcc8e2a 100644
--- a/gnu/usr.bin/gcc/config/i386/sysv3.h
+++ b/gnu/usr.bin/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) %[cpp_cpu] %{posix:-D_POSIX_SOURCE}"
/* Writing `int' for a bitfield forces int alignment for the structure. */
diff --git a/gnu/usr.bin/gcc/config/i386/sysv4.h b/gnu/usr.bin/gcc/config/i386/sysv4.h
index 92fcada03d5..3f69827fd54 100644
--- a/gnu/usr.bin/gcc/config/i386/sysv4.h
+++ b/gnu/usr.bin/gcc/config/i386/sysv4.h
@@ -243,3 +243,11 @@ do { long value[3]; \
necessary when compiling PIC code. */
#define JUMP_TABLES_IN_TEXT_SECTION
+
+/* 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/gnu/usr.bin/gcc/config/i386/t-crtpic b/gnu/usr.bin/gcc/config/i386/t-crtpic
index f5dd073a664..ff81a9bef9c 100644
--- a/gnu/usr.bin/gcc/config/i386/t-crtpic
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/t-next b/gnu/usr.bin/gcc/config/i386/t-next
index ec6373f9cea..effa6953b9a 100644
--- a/gnu/usr.bin/gcc/config/i386/t-next
+++ b/gnu/usr.bin/gcc/config/i386/t-next
@@ -7,3 +7,6 @@ OTHER_FIXINCLUDES_DIRS= /LocalDeveloper/Headers
# <limits.h> 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/gnu/usr.bin/gcc/config/i386/t-sol2 b/gnu/usr.bin/gcc/config/i386/t-sol2
index f79f6ca05fb..f47905ae65d 100644
--- a/gnu/usr.bin/gcc/config/i386/t-sol2
+++ b/gnu/usr.bin/gcc/config/i386/t-sol2
@@ -13,15 +13,18 @@ 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++
@@ -30,3 +33,4 @@ crtn.o: $(srcdir)/config/i386/sol2-cn.asm
# routines in crtstuff.c.
CRTSTUFF_T_CFLAGS = -fPIC
+TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gnu/usr.bin/gcc/config/i386/t-winnt b/gnu/usr.bin/gcc/config/i386/t-winnt
index e8e1a0af050..1e3557c1822 100644
--- a/gnu/usr.bin/gcc/config/i386/t-winnt
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/unix.h b/gnu/usr.bin/gcc/config/i386/unix.h
index f38fe270d89..c74911c7107 100644
--- a/gnu/usr.bin/gcc/config/i386/unix.h
+++ b/gnu/usr.bin/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,47 @@ 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, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \
+ fprintf (FILE, "@GOT(%%ebx),%%ecx\n\tpopl %%ebx\n\tjmp *%%ecx\n"); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tjmp "); \
+ assemble_name \
+ (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \
+ fprintf (FILE, "\n"); \
+ } \
+} while (0)
diff --git a/gnu/usr.bin/gcc/config/i386/winnt.c b/gnu/usr.bin/gcc/config/i386/winnt.c
index 3a7ebf1ba5d..ac26a1a7190 100644
--- a/gnu/usr.bin/gcc/config/i386/winnt.c
+++ b/gnu/usr.bin/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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -44,13 +44,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 +64,30 @@ gen_stdcall_suffix (decl)
return IDENTIFIER_POINTER (get_identifier (newsym));
}
+/* 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));
+
+ /* 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). */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ prefix = ".text$";
+ else if (DECL_READONLY_SECTION (decl, reloc))
+ prefix = ".rdata$";
+ 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);
+}
diff --git a/gnu/usr.bin/gcc/config/i386/x-osfrose b/gnu/usr.bin/gcc/config/i386/x-osfrose
index a419bdb7822..27c36fe4fe7 100644
--- a/gnu/usr.bin/gcc/config/i386/x-osfrose
+++ b/gnu/usr.bin/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)
@@ -25,7 +26,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/gnu/usr.bin/gcc/config/i386/xm-aix.h b/gnu/usr.bin/gcc/config/i386/xm-aix.h
index 5e5d40281a1..ea9202112a1 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-aix.h
+++ b/gnu/usr.bin/gcc/config/i386/xm-aix.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for IBM PS/2 running AIX/386.
- Copyright (C) 1988, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1993, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -25,13 +25,7 @@ Boston, MA 02111-1307, USA. */
#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/gnu/usr.bin/gcc/config/i386/xm-bsd386.h b/gnu/usr.bin/gcc/config/i386/xm-bsd386.h
index 9deb7ef6c65..6b8eee7db03 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-bsd386.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-dos.h b/gnu/usr.bin/gcc/config/i386/xm-dos.h
index 1dd0c013b1d..a734a81b94e 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-dos.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-linux.h b/gnu/usr.bin/gcc/config/i386/xm-linux.h
index 42f097ddc6c..713bf3b2817 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-linux.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-os2.h b/gnu/usr.bin/gcc/config/i386/xm-os2.h
index 5ff2899cfd5..f74bee5ebb2 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-os2.h
+++ b/gnu/usr.bin/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 Free Software Foundation, Inc.
+ Contributed by Samuel Figueroa (figueroa@apple.com)
This file is part of GNU CC.
@@ -28,13 +28,7 @@ Boston, MA 02111-1307, USA. */
#include <stdlib.h> /* 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
diff --git a/gnu/usr.bin/gcc/config/i386/xm-osf.h b/gnu/usr.bin/gcc/config/i386/xm-osf.h
index fda50d98f55..cd06b56b6ad 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-osf.h
+++ b/gnu/usr.bin/gcc/config/i386/xm-osf.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for 386 running OSF/1
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,11 +22,3 @@ Boston, MA 02111-1307, USA. */
#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/gnu/usr.bin/gcc/config/i386/xm-sco.h b/gnu/usr.bin/gcc/config/i386/xm-sco.h
index 01a63d90e00..472ce047cf8 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-sco.h
+++ b/gnu/usr.bin/gcc/config/i386/xm-sco.h
@@ -20,3 +20,6 @@
#define ONLY_INT_FIELDS 1
#define CODE_FIELD_BUG 1
#endif
+
+/* SCO lacks sys_siglist. */
+#define NO_SYS_SIGLIST
diff --git a/gnu/usr.bin/gcc/config/i386/xm-sun.h b/gnu/usr.bin/gcc/config/i386/xm-sun.h
index d2e714ecf5c..de7c2013b3e 100644
--- a/gnu/usr.bin/gcc/config/i386/xm-sun.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i860/bsd-gas.h b/gnu/usr.bin/gcc/config/i860/bsd-gas.h
index 11b400bb745..f76fec76827 100644
--- a/gnu/usr.bin/gcc/config/i860/bsd-gas.h
+++ b/gnu/usr.bin/gcc/config/i860/bsd-gas.h
@@ -1,4 +1,2 @@
-#include "i860/bsd.h"
-
#undef ASCII_DATA_ASM_OP
#define ASCII_DATA_ASM_OP ".ascii"
diff --git a/gnu/usr.bin/gcc/config/i860/bsd.h b/gnu/usr.bin/gcc/config/i860/bsd.h
index 4f745c50a1b..17b053343e8 100644
--- a/gnu/usr.bin/gcc/config/i860/bsd.h
+++ b/gnu/usr.bin/gcc/config/i860/bsd.h
@@ -1,5 +1,3 @@
-#include "i860/i860.h"
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i860, BSD)")
diff --git a/gnu/usr.bin/gcc/config/i860/fx2800.h b/gnu/usr.bin/gcc/config/i860/fx2800.h
index e295c686454..41c5bae3d06 100644
--- a/gnu/usr.bin/gcc/config/i860/fx2800.h
+++ b/gnu/usr.bin/gcc/config/i860/fx2800.h
@@ -1,9 +1,7 @@
/* Target definitions for GNU compiler for Alliant FX/2800
running Concentrix 2.2
-
- Copyright (C) 1991 Free Software Foundation, Inc.
-
- Written by Howard Chu (hyc@hanauma.jpl.nasa.gov).
+ Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+ Contributed by Howard Chu (hyc@hanauma.jpl.nasa.gov).
This file is part of GNU CC.
@@ -22,10 +20,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. */
-#define OUTPUT_TDESC
-
-#include "i860/sysv4.h"
-
/* The Alliant fx2800 running Concentrix 2.x is weird. This is basically
a BSD 4.3 based operating system, but it uses svr4 ELF format object
files and it somehow puts BSD stabs records into the ELF files for
@@ -336,9 +330,27 @@ Boston, MA 02111-1307, USA. */
#undef DWARF_DEBUGGING_INFO
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "_%s", NAME)
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
#undef ASM_OUTPUT_EXTERNAL_LIBCALL
+/* ??? Is this used anywhere? */
#undef BSS_ASM_OP
#define BSS_ASM_OP "\t.lcomm"
+
+#undef ASM_FILE_END
+#define ASM_FILE_END(FILE) \
+do { \
+ if (current_function_original_name != NULL) { \
+ tdesc_section(); \
+ fprintf ((FILE), "%s __ETEXT\n", ASM_LONG); \
+ fprintf ((FILE), "%s 0\n", ASM_LONG); \
+ text_section(); \
+ fputs("__ETEXT:\n", (FILE)); \
+ } \
+ fprintf ((FILE), "\t.ident\t\"GCC: (GNU) %s\"\n", \
+ version_string); \
+ } while (0)
diff --git a/gnu/usr.bin/gcc/config/i860/i860.c b/gnu/usr.bin/gcc/config/i860/i860.c
index dce13404783..23a3522a7a7 100644
--- a/gnu/usr.bin/gcc/config/i860/i860.c
+++ b/gnu/usr.bin/gcc/config/i860/i860.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Intel 860
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1991, 1997 Free Software Foundation, Inc.
Derived from sparc.c.
Written by Richard Stallman (rms@ai.mit.edu).
@@ -26,6 +26,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "flags.h"
#include "rtl.h"
#include "regs.h"
@@ -38,8 +39,6 @@ Boston, MA 02111-1307, USA. */
#include "recog.h"
#include "insn-attr.h"
-#include <stdio.h>
-
static rtx find_addr_reg ();
#ifndef I860_REG_PREFIX
diff --git a/gnu/usr.bin/gcc/config/i860/i860.h b/gnu/usr.bin/gcc/config/i860/i860.h
index d182b860da1..47eb7dcfd1d 100644
--- a/gnu/usr.bin/gcc/config/i860/i860.h
+++ b/gnu/usr.bin/gcc/config/i860/i860.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for Intel 860.
- Copyright (C) 1989, 1991, 1993, 1995 Free Software Foundation, Inc.
- Hacked substantially by Ron Guilmette (rfg@segfault.us.com) to cater to
+ Copyright (C) 1989, 91, 93, 95, 96, 1997 Free Software Foundation, Inc.
+ Hacked substantially by Ron Guilmette (rfg@monkeys.com) to cater to
the whims of the System V Release 4 assembler.
This file is part of GNU CC.
@@ -472,7 +472,7 @@ struct cumulative_args { int ints, floats; };
when the function gets a structure-value-address as an
invisible first argument. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM).ints = ((FNTYPE) != 0 && aggregate_value_p (TREE_TYPE ((FNTYPE))) \
? 4 : 0), \
(CUM).floats = 0)
@@ -1046,15 +1046,13 @@ struct cumulative_args { int ints, floats; };
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.
This definition is overridden in i860v4.h because under System V
Release 4, user-level symbols are *not* prefixed with underscores in
the generated assembly code. */
-#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. */
@@ -1371,7 +1369,7 @@ extern unsigned long sfmode_constant_to_ulong ();
stack (where the i860 calling conventions require structs &
unions to be passed). */
-#define FLOAT_TYPE_VALUE float
+#define FLOAT_VALUE_TYPE float
#define INTIFY(FLOATVAL) (FLOATVAL)
#define FLOATIFY(INTVAL) (INTVAL)
#define FLOAT_ARG_TYPE float
diff --git a/gnu/usr.bin/gcc/config/i860/i860.md b/gnu/usr.bin/gcc/config/i860/i860.md
index a3df7bc4584..b5649f59e49 100644
--- a/gnu/usr.bin/gcc/config/i860/i860.md
+++ b/gnu/usr.bin/gcc/config/i860/i860.md
@@ -1,5 +1,5 @@
;;- Machine description for Intel 860 chip for GNU C compiler
-;; Copyright (C) 1989, 1990 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1990, 1997 Free Software Foundation, Inc.
;; This file is part of GNU CC.
@@ -1004,23 +1004,26 @@
;; that anything generated as this insn will be recognized as one
;; and that it won't successfully combine with anything.
(define_expand "movstrsi"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
- (mem:BLK (match_operand:BLK 1 "general_operand" "")))
+ [(parallel [(set (match_operand:BLK 0 "general_operand" "")
+ (match_operand:BLK 1 "general_operand" ""))
(use (match_operand:SI 2 "nonmemory_operand" ""))
(use (match_operand:SI 3 "immediate_operand" ""))
(clobber (match_dup 4))
(clobber (match_dup 5))
(clobber (match_dup 6))
- (clobber (match_dup 0))
- (clobber (match_dup 1))])]
+ (clobber (match_dup 7))
+ (clobber (match_dup 8))])]
""
"
{
- operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
- operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
operands[4] = gen_reg_rtx (SImode);
operands[5] = gen_reg_rtx (SImode);
operands[6] = gen_reg_rtx (SImode);
+ operands[7] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
+ operands[8] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
+
+ operands[0] = change_address (operands[0], VOIDmode, operands[7]);
+ operands[1] = change_address (operands[1], VOIDmode, operands[8]);
}")
(define_insn ""
diff --git a/gnu/usr.bin/gcc/config/i860/mach.h b/gnu/usr.bin/gcc/config/i860/mach.h
index 7a4f5230974..a59cc58e0ff 100644
--- a/gnu/usr.bin/gcc/config/i860/mach.h
+++ b/gnu/usr.bin/gcc/config/i860/mach.h
@@ -1,7 +1,5 @@
/* Configuration for an i860 running Mach as the target machine. */
-#include "i860/i860.h"
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i860 Mach3.x)");
diff --git a/gnu/usr.bin/gcc/config/i860/paragon.h b/gnu/usr.bin/gcc/config/i860/paragon.h
index 802d4fdcb76..c6bfbba09e9 100644
--- a/gnu/usr.bin/gcc/config/i860/paragon.h
+++ b/gnu/usr.bin/gcc/config/i860/paragon.h
@@ -1,10 +1,9 @@
/* Target definitions for GNU compiler for Intel 80860 running OSF/1AD
- Copyright (C) 1991 Free Software Foundation, Inc.
-
- Based upon original work of Ron Guilmette (rfg@netcom.com).
- Whacked into submission by Andy Pfiffer (andyp@ssd.intel.com).
+ Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+ Based upon original work of Ron Guilmette (rfg@monkeys.com).
+ Contributed by Andy Pfiffer (andyp@ssd.intel.com).
Partially inspired by
- Pete Beckman @ Indiana University (beckman@cs.indiana.edu)
+ Pete Beckman of Indiana University (beckman@cs.indiana.edu)
Harry Dolan of Intel Corporation (dolan@ssd.intel.com)
This file is part of GNU CC.
@@ -24,9 +23,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 "i860/i860.h"
-#include "svr3.h"
-
/* For the sake of libgcc2.c, indicate target supports atexit. */
#define HAVE_ATEXIT
@@ -54,17 +50,17 @@ Boston, MA 02111-1307, USA. */
#define CPP_SPEC "%{mnx:-D__NODE}"
/* autoinit.o autolaunches NX applications */
-#define STARTFILE_SPEC "-ycrt0.o%s %{mnx:-yoptions/autoinit.o%s}"
+#define STARTFILE_SPEC "crt0.o%s %{mnx:-yoptions/autoinit.o%s}"
/* libic.a is the PGI intrinsic library */
/* libpm.o and guard.o are for the performance monitoring modules (ignored) */
/* /usr/lib/noieee contains non-IEEE compliant (but faster) math routines */
#if HAVE_DASH_G
-#define LIB_SPEC "%{mnoieee:-L/usr/lib/noieee} -L/usr/lib %{mnx:-lnx -lmach} %
-{g*:-lg} -lc -lic"
+#define LIB_SPEC \
+"%{mnoieee:-L/usr/lib/noieee} %{mnx:-lnx} %{g*:-lg} -lc -lmach -lc -lic"
#else /* HAVE_DASH_G */
/* can't use -g for -lg; libg.a doesn't have a symbol table and ld complains */
-#define LIB_SPEC "%{mnoieee:-L/usr/lib/noieee} -L/usr/lib %{mnx:-lnx -lmach} -lc -lic"
+#define LIB_SPEC "%{mnoieee:-L/usr/lib/noieee} %{mnx:-lnx} -lc -lmach -lc -lic"
#endif /* HAVE_DASH_G */
/* Get rid of definition from svr3.h. */
@@ -237,7 +233,4 @@ Boston, MA 02111-1307, USA. */
#define BSS_SECTION_ASM_OP ".bss" /* XXX */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_bss
#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- BSS_SECTION_FUNCTION
diff --git a/gnu/usr.bin/gcc/config/i860/sysv3.h b/gnu/usr.bin/gcc/config/i860/sysv3.h
index 6a7c6a5b66e..56f8e49a3e7 100644
--- a/gnu/usr.bin/gcc/config/i860/sysv3.h
+++ b/gnu/usr.bin/gcc/config/i860/sysv3.h
@@ -1,7 +1,6 @@
/* Target definitions for GNU compiler for Intel 80860 running System V.3
- Copyright (C) 1991 Free Software Foundation, Inc.
-
- Written by Ron Guilmette (rfg@netcom.com).
+ Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.com).
This file is part of GNU CC.
@@ -20,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 "i860/i860.h"
-#include "svr3.h"
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i860, System V Release 3)")
diff --git a/gnu/usr.bin/gcc/config/i860/sysv4.h b/gnu/usr.bin/gcc/config/i860/sysv4.h
index d8b0a8eafeb..eca6b79ce2e 100644
--- a/gnu/usr.bin/gcc/config/i860/sysv4.h
+++ b/gnu/usr.bin/gcc/config/i860/sysv4.h
@@ -1,7 +1,6 @@
/* Target definitions for GNU compiler for Intel 80860 running System V.4
- Copyright (C) 1991 Free Software Foundation, Inc.
-
- Written by Ron Guilmette (rfg@netcom.com).
+ Copyright (C) 1991, 1996 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.com).
This file is part of GNU CC.
@@ -20,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 "i860/i860.h"
-#include "svr4.h"
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i860 System V Release 4)");
@@ -195,18 +191,3 @@ tdesc_section () \
} \
}
-#ifdef OUTPUT_TDESC
-#undef ASM_FILE_END
-#define ASM_FILE_END(FILE) \
-do { \
- if (current_function_original_name != NULL) { \
- tdesc_section(); \
- fprintf ((FILE), "%s __ETEXT\n", ASM_LONG); \
- fprintf ((FILE), "%s 0\n", ASM_LONG); \
- text_section(); \
- fputs("__ETEXT:\n", (FILE)); \
- } \
- fprintf ((FILE), "\t.ident\t\"GCC: (GNU) %s\"\n", \
- version_string); \
- } while (0)
-#endif
diff --git a/gnu/usr.bin/gcc/config/i960/i960-coff.h b/gnu/usr.bin/gcc/config/i960/i960-coff.h
index 15415e37ed9..139e8d1c5c3 100644
--- a/gnu/usr.bin/gcc/config/i960/i960-coff.h
+++ b/gnu/usr.bin/gcc/config/i960/i960-coff.h
@@ -1,12 +1,10 @@
/* Definitions of target machine for GNU compiler, for "naked" Intel
80960 using coff object format and coff debugging symbols.
- Copyright (C) 1988, 1989, 1991 Intel Corp.
+ Copyright (C) 1988, 1989, 1991, 1996 Free Software Foundation.
Contributed by Steven McGeady (mcg@omepd.intel.com)
Additional work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
Converted to GCC 2.0 by Michael Tiemann, Cygnus Support.
- */
-/*
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
@@ -24,12 +22,16 @@ 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 "i960/i960.h"
+/* Support -gstabs using stabs in COFF sections. */
/* Generate SDB_DEBUGGING_INFO by default. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
+/* This is intended to be used with Cygnus's newlib library, so we want to
+ use the standard definition of LIB_SPEC. */
+#undef LIB_SPEC
+
#undef ASM_FILE_START
#define ASM_FILE_START(FILE) \
output_file_directive ((FILE), main_input_filename)
diff --git a/gnu/usr.bin/gcc/config/i960/i960.c b/gnu/usr.bin/gcc/config/i960/i960.c
index fde2e43e786..6e86645fe61 100644
--- a/gnu/usr.bin/gcc/config/i960/i960.c
+++ b/gnu/usr.bin/gcc/config/i960/i960.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on intel 80960.
- Copyright (C) 1992, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Steven McGeady, Intel Corp.
Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
@@ -21,9 +21,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 <stdio.h>
-
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -36,8 +35,8 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "tree.h"
#include "insn-codes.h"
-#include "assert.h"
#include "expr.h"
+#include "except.h"
#include "function.h"
#include "recog.h"
#include <math.h>
@@ -89,30 +88,30 @@ static int ret_label = 0;
/* ??? This is incomplete, since it does not handle all pragmas that the
intel compilers understand. */
-void
-process_pragma (finput)
+int
+process_pragma (finput, t)
FILE *finput;
+ tree t;
{
- int c;
int i;
+ register int c;
+ register char *pname;
- c = getc (finput);
- while (c == ' ' || c == '\t')
- c = getc (finput);
+ if (TREE_CODE (t) != IDENTIFIER_NODE)
+ return 0;
- if (c == 'a'
- && getc (finput) == 'l'
- && getc (finput) == 'i'
- && getc (finput) == 'g'
- && getc (finput) == 'n'
- && ((c = getc (finput)) == ' ' || c == '\t' || c == '\n'))
+ pname = IDENTIFIER_POINTER (t);
+
+ if (strcmp (pname, "align") == 0)
{
char buf[20];
char *s = buf;
int align;
- while (c == ' ' || c == '\t')
+ do {
c = getc (finput);
+ } while (c == ' ' || c == '\t');
+
if (c == '(')
c = getc (finput);
while (c >= '0' && c <= '9')
@@ -123,6 +122,11 @@ process_pragma (finput)
}
*s = '\0';
+ /* We had to read a non-numerical character to get out of the
+ while loop---often a newline. So, we have to put it back to
+ make sure we continue to parse everything properly. */
+ ungetc (c, finput);
+
align = atoi (buf);
switch (align)
{
@@ -158,11 +162,13 @@ process_pragma (finput)
- missing identifier means next struct
- alignment rules for bitfields need more investigation */
+
+ return 1;
}
/* Should be pragma 'far' or equivalent for callx/balx here. */
- ungetc (c, finput);
+ return 0;
}
/* Initialize variables before compiling any files. */
@@ -215,6 +221,19 @@ arith_operand (op, mode)
return (register_operand (op, mode) || literal (op, mode));
}
+/* Return truth value of whether OP can be used as an operands in a three
+ address logic insn, possibly complementing OP, of mode MODE. */
+
+int
+logic_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return (register_operand (op, mode)
+ || (GET_CODE (op) == CONST_INT
+ && INTVAL(op) >= -32 && INTVAL(op) < 32));
+}
+
/* Return true if OP is a register or a valid floating point literal. */
int
@@ -1638,10 +1657,13 @@ i960_print_operand (file, x, code)
}
else if (rtxcode == CONST_INT)
{
- if (INTVAL (x) > 9999 || INTVAL (x) < -999)
- fprintf (file, "0x%x", INTVAL (x));
+ HOST_WIDE_INT val = INTVAL (x);
+ if (code == 'C')
+ val = ~val;
+ if (val > 9999 || val < -999)
+ fprintf (file, "0x%x", val);
else
- fprintf (file, "%d", INTVAL (x));
+ fprintf (file, "%d", val);
return;
}
else if (rtxcode == CONST_DOUBLE)
@@ -2218,7 +2240,8 @@ i960_arg_size_and_align (mode, type, size_out, align_out)
else if (mode == VOIDmode)
{
/* End of parm list. */
- assert (type != 0 && TYPE_MODE (type) == VOIDmode);
+ if (type == 0 || TYPE_MODE (type) != VOIDmode)
+ abort ();
size = 1;
}
else
diff --git a/gnu/usr.bin/gcc/config/i960/i960.h b/gnu/usr.bin/gcc/config/i960/i960.h
index 7bde093a4c4..6ced9acadf8 100644
--- a/gnu/usr.bin/gcc/config/i960/i960.h
+++ b/gnu/usr.bin/gcc/config/i960/i960.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for Intel 80960
- Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
Contributed by Steven McGeady, Intel Corp.
Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
@@ -30,6 +30,8 @@ Boston, MA 02111-1307, USA. */
/* Name to predefine in the preprocessor for processor variations. */
#define CPP_SPEC "%{mic*:-D__i960\
%{mka:-D__i960KA}%{mkb:-D__i960KB}\
+ %{mja:-D__i960JA}%{mjd:-D__i960JD}%{mjf:-D__i960JF}\
+ %{mrp:-D__i960RP}\
%{msa:-D__i960SA}%{msb:-D__i960SB}\
%{mmc:-D__i960MC}\
%{mca:-D__i960CA}%{mcc:-D__i960CC}\
@@ -58,7 +60,7 @@ Boston, MA 02111-1307, USA. */
If the user gives an explicit -gstabs or -gcoff option, then do not
try to add an implicit one, as this will fail. */
#define CC1_SPEC \
- "%{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:-mkb}}}}}}}}\
+ "%{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-mka}}}}}}}}}}}}\
%{!gs*:%{!gc*:%{mbout:%{g*:-gstabs}}\
%{mcoff:%{g*:-gcoff}}\
%{!mbout:%{!mcoff:%{g*:-gstabs}}}}}"
@@ -69,7 +71,8 @@ Boston, MA 02111-1307, USA. */
#define ASM_SPEC \
"%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB}\
%{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF}\
- %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:-AKB}}}}}}}}\
+ %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX}\
+ %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-AKB}}}}}}}}}}}}\
%{mlink-relax:-linkrelax}"
/* Specs for the linker, to handle processor variations.
@@ -78,7 +81,7 @@ Boston, MA 02111-1307, USA. */
#define LINK_SPEC \
"%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB}\
%{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF}\
- %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:-AKB}}}}}}}}\
+ %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX}\
%{mbout:-Fbout}%{mcoff:-Fcoff}\
%{mlink-relax:-relax}"
@@ -108,18 +111,18 @@ Boston, MA 02111-1307, USA. */
/* Generate SDB style debugging information. */
#define SDB_DEBUGGING_INFO
+#define EXTENDED_SDB_BASIC_TYPES
/* Generate DBX_DEBUGGING_INFO by default. */
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-/* Redefine this to print in hex and adjust values like GNU960. The extra
- bit is used to handle the type long double. Gcc does not support long
- double in sdb output, but we do support the non-standard format. */
+/* Redefine this to print in hex. No value adjustment is necessary
+ anymore. */
#define PUT_SDB_TYPE(A) \
- fprintf (asm_out_file, "\t.type\t0x%x;", (A & 0xf) + 2 * (A & ~0xf))
+ fprintf (asm_out_file, "\t.type\t0x%x;", A)
/* Handle pragmas for compatibility with Intel's compilers. */
-#define HANDLE_PRAGMA(FILE) process_pragma (FILE)
+#define HANDLE_PRAGMA(FILE, NODE) process_pragma (FILE, NODE)
/* Run-time compilation parameters selecting different hardware subsets. */
@@ -133,7 +136,8 @@ Boston, MA 02111-1307, USA. */
#define TARGET_PROTECTED (target_flags & TARGET_FLAG_PROTECTED)
/* The following three are mainly used to provide a little sanity checking
- against the -mARCH flags given. */
+ against the -mARCH flags given. The Jx series, for the purposes of
+ gcc, is a Kx with a data cache. */
/* Nonzero if we should generate code for the KA and similar processors.
No FPU, no microcode instructions. */
@@ -226,6 +230,11 @@ extern int target_flags;
TARGET_FLAG_COMPLEX_ADDR)},\
/* {"kc", (TARGET_FLAG_NUMERICS|TARGET_FLAG_PROTECTED|\
TARGET_FLAG_MC|TARGET_FLAG_COMPLEX_ADDR)},*/ \
+ {"ja", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR)},\
+ {"jd", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR)},\
+ {"jf", (TARGET_FLAG_NUMERICS|TARGET_FLAG_K_SERIES| \
+ TARGET_FLAG_COMPLEX_ADDR)},\
+ {"rp", (TARGET_FLAG_K_SERIES|TARGET_FLAG_COMPLEX_ADDR)},\
{"mc", (TARGET_FLAG_NUMERICS|TARGET_FLAG_PROTECTED|\
TARGET_FLAG_MC|TARGET_FLAG_COMPLEX_ADDR)},\
{"ca", (TARGET_FLAG_C_SERIES|TARGET_FLAG_BRANCH_PREDICT|\
@@ -302,7 +311,7 @@ extern int target_flags;
}
/* Don't enable anything by default. The user is expected to supply a -mARCH
- option. If none is given, then -mkb is added by CC1_SPEC. */
+ option. If none is given, then -mka is added by CC1_SPEC. */
#define TARGET_DEFAULT 0
/* Target machine storage layout. */
@@ -402,13 +411,14 @@ extern int target_flags;
#define ROUND_TYPE_ALIGN(TYPE, COMPUTED, SPECIFIED) \
((TREE_CODE (TYPE) == REAL_TYPE && TYPE_MODE (TYPE) == XFmode) \
? 128 /* Put 80 bit floating point elements on 128 bit boundaries. */ \
- : ((!TARGET_OLD_ALIGN && TREE_CODE (TYPE) == RECORD_TYPE) \
+ : ((!TARGET_OLD_ALIGN && !TYPE_PACKED (TYPE) \
+ && TREE_CODE (TYPE) == RECORD_TYPE) \
? i960_round_align (MAX ((COMPUTED), (SPECIFIED)), TYPE_SIZE (TYPE)) \
: MAX ((COMPUTED), (SPECIFIED))))
#define ROUND_TYPE_SIZE(TYPE, COMPUTED, SPECIFIED) \
((TREE_CODE (TYPE) == REAL_TYPE && TYPE_MODE (TYPE) == XFmode) \
- ? build_int_2 (128, 0) : (COMPUTED))
+ ? build_int_2 (128, 0) : round_up (COMPUTED, SPECIFIED))
/* Standard register usage. */
@@ -651,8 +661,9 @@ enum reg_class { NO_REGS, GLOBAL_REGS, LOCAL_REGS, LOCAL_OR_GLOBAL_REGS,
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
((C) == 'I' ? (((unsigned) (VALUE)) <= 31) \
: (C) == 'J' ? ((VALUE) == 0) \
- : (C) == 'K' ? ((VALUE) > -32 && (VALUE) <= 0) \
- : 0)
+ : (C) == 'K' ? ((VALUE) >= -31 && (VALUE) <= 0) \
+ : (C) == 'M' ? ((VALUE) >= -32 && (VALUE) <= 0) \
+ : 0)
/* Similar, but for floating constants, and defining letters G and H.
Here VALUE is the CONST_DOUBLE rtx itself.
@@ -802,7 +813,7 @@ struct cum_args { int ca_nregparms; int ca_nstackparms; };
On 80960, the offset always starts at 0; the first parm reg is g0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM).ca_nregparms = 0, (CUM).ca_nstackparms = 0)
/* Update the data in CUM to advance over an argument
@@ -1104,7 +1115,7 @@ extern struct rtx_def *legitimize_address ();
/* Define this to be nonzero if shift instructions ignore all but the low-order
few bits. */
-#define SHIFT_COUNT_TRUNCATED 1
+#define SHIFT_COUNT_TRUNCATED 0
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
is done just by pretending it is already truncated. */
@@ -1261,10 +1272,9 @@ extern struct rtx_def *gen_compare_reg ();
assemble_name (FILE, NAME); \
fputs ("\n", FILE); }
-/* 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. */
@@ -1372,10 +1382,20 @@ extern struct rtx_def *gen_compare_reg ();
( fputs (".bss\t", (FILE)), \
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%d,%d\n", (SIZE), \
- ((ALIGN) <= 8 ? 0 \
- : ((ALIGN) <= 16 ? 1 \
- : ((ALIGN) <= 32 ? 2 \
- : ((ALIGN <= 64 ? 3 : 4)))))))
+ (floor_log2 ((ALIGN) / 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)
/* Output text for an #ident directive. */
#define ASM_OUTPUT_IDENT(FILE, STR) fprintf(FILE, "\t# %s\n", STR);
@@ -1502,6 +1522,7 @@ extern enum insn_types i960_last_insn_type;
{"fpmove_src_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
LABEL_REF, SUBREG, REG, MEM}}, \
{"arith_operand", {SUBREG, REG, CONST_INT}}, \
+ {"logic_operand", {SUBREG, REG, CONST_INT}}, \
{"fp_arith_operand", {SUBREG, REG, CONST_DOUBLE}}, \
{"signed_arith_operand", {SUBREG, REG, CONST_INT}}, \
{"literal", {CONST_INT}}, \
@@ -1521,7 +1542,29 @@ extern enum insn_types i960_last_insn_type;
extern char *i960_output_ldconst ();
extern char *i960_output_call_insn ();
extern char *i960_output_ret_insn ();
+extern char *i960_output_move_double ();
+extern char *i960_output_move_quad ();
/* Defined in reload.c, and used in insn-recog.c. */
extern int rtx_equal_function_value_matters;
+
+/* 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 d = (DELTA); \
+ if (d < 0 && d > -32) \
+ fprintf (FILE, "\tsubo %d,g0,g0\n", -d); \
+ else if (d > 0 && d < 32) \
+ fprintf (FILE, "\taddo %d,g0,g0\n", d); \
+ else \
+ { \
+ fprintf (FILE, "\tldconst %d,r5\n", d); \
+ fprintf (FILE, "\taddo r5,g0,g0\n"); \
+ } \
+ fprintf (FILE, "\tbx "); \
+ assemble_name \
+ (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \
+ fprintf (FILE, "\n"); \
+} while (0);
diff --git a/gnu/usr.bin/gcc/config/i960/i960.md b/gnu/usr.bin/gcc/config/i960/i960.md
index 01e18c5ac9c..32acd924ed1 100644
--- a/gnu/usr.bin/gcc/config/i960/i960.md
+++ b/gnu/usr.bin/gcc/config/i960/i960.md
@@ -352,6 +352,13 @@
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d")
+ (eq:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))]
+ ""
+ "shro %1,1,%0"
+ [(set_attr "type" "alu2")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
(match_operator:SI 1 "comparison_operator" [(reg:CC 36) (const_int 0)]))]
""
"test%C1 %0"
@@ -1502,6 +1509,9 @@
;; add instruction.
;; Some assemblers apparently won't accept two addresses added together.
+;; ??? The condition should be improved to reject the case of two
+;; symbolic constants.
+
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,d,d")
(plus:SI (match_operand:SI 1 "arith32_operand" "%dn,i,dn")
@@ -1524,8 +1534,16 @@
else if (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32)
return \"addo %1,%2,%0\";
}
+ /* Non-canonical results (op1 == const, op2 != const) have been seen
+ in reload output when both operands were symbols before reload, so
+ we deal with it here. This may be a fault of the constraints above. */
if (CONSTANT_P (operands[1]))
- return \"lda %1+%2,%0\";
+ {
+ if (CONSTANT_P (operands[2]))
+ return \"lda %1+%2,%0\";
+ else
+ return \"lda %1(%2),%0\";
+ }
return \"lda %2(%1),%0\";
}")
@@ -1645,11 +1663,13 @@
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
- (and:SI (match_operand:SI 1 "arith_operand" "%dI")
- (match_operand:SI 2 "arith_operand" "dI")))]
+ (and:SI (match_operand:SI 1 "register_operand" "%d")
+ (match_operand:SI 2 "logic_operand" "dIM")))]
""
"*
{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ return \"andnot %C2,%1,%0\";
if (i960_bypass (insn, operands[1], operands[2], 0))
return \"and %2,%1,%0\";
return \"and %1,%2,%0\";
@@ -1657,11 +1677,25 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (and:SI (not:SI (match_operand:SI 1 "arith_operand" "dI"))
- (match_operand:SI 2 "arith_operand" "dI")))]
+ (and:SI (match_operand:SI 1 "arith_operand" "dI")
+ (match_operand:SI 2 "cmplpower2_operand" "n")))]
""
"*
{
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ bitpos (~INTVAL (operands[2])));
+ return \"clrbit %2,%1,%0\";
+}")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "d"))
+ (match_operand:SI 2 "logic_operand" "dIM")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ return \"nor %C2,%1,%0\";
if (i960_bypass (insn, operands[1], operands[2], 0))
return \"notand %2,%1,%0\";
return \"andnot %1,%2,%0\";
@@ -1669,8 +1703,8 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (ior:SI (not:SI (match_operand:SI 1 "arith_operand" "%dI"))
- (not:SI (match_operand:SI 2 "arith_operand" "dI"))))]
+ (ior:SI (not:SI (match_operand:SI 1 "register_operand" "%d"))
+ (not:SI (match_operand:SI 2 "register_operand" "d"))))]
""
"*
{
@@ -1679,9 +1713,23 @@
return \"nand %1,%2,%0\";
}")
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ior:SI (match_operand:SI 1 "register_operand" "%d")
+ (match_operand:SI 2 "logic_operand" "dIM")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ return \"ornot %C2,%1,%0\";
+ if (i960_bypass (insn, operands[1], operands[2], 0))
+ return \"or %2,%1,%0\";
+ return \"or %1,%2,%0\";
+}")
+
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (ior:SI (match_operand:SI 1 "arith_operand" "dI")
+ (ior:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "power2_operand" "n")))]
""
"*
@@ -1693,42 +1741,43 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (ior:SI (ashift:SI (const_int 1)
- (match_operand:SI 1 "register_operand" "d"))
- (match_operand:SI 2 "arith_operand" "dI")))]
+ (ior:SI (not:SI (match_operand:SI 1 "register_operand" "d"))
+ (match_operand:SI 2 "logic_operand" "dIM")))]
""
- "setbit %1,%2,%0")
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ return \"nand %C2,%1,%0\";
+ if (i960_bypass (insn, operands[1], operands[2], 0))
+ return \"notor %2,%1,%0\";
+ return \"ornot %1,%2,%0\";
+}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (and:SI (match_operand:SI 1 "arith_operand" "dI")
- (match_operand:SI 2 "cmplpower2_operand" "n")))]
+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "%d"))
+ (not:SI (match_operand:SI 2 "register_operand" "d"))))]
""
"*
{
- operands[2] = gen_rtx (CONST_INT, VOIDmode,
- bitpos (~INTVAL (operands[2])));
- return \"clrbit %2,%1,%0\";
+ if (i960_bypass (insn, operands[1], operands[2], 0))
+ return \"nor %2,%1,%0\";
+ return \"nor %1,%2,%0\";
}")
-;; (not (ashift 1 reg)) canonicalizes to (rotate -2 reg)
-(define_insn ""
+(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
- (and:SI (rotate:SI (const_int -2)
- (match_operand:SI 1 "register_operand" "d"))
- (match_operand:SI 2 "register_operand" "d")))]
+ (xor:SI (match_operand:SI 1 "register_operand" "%d")
+ (match_operand:SI 2 "logic_operand" "dIM")))]
""
- "clrbit %1,%2,%0")
-
-;; The above pattern canonicalizes to this when both the input and output
-;; are the same pseudo-register.
-(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "=d")
- (const_int 1)
- (match_operand:SI 1 "register_operand" "d"))
- (const_int 0))]
- ""
- "clrbit %1,%0,%0")
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ return \"xnor %C2,%1,%0\";
+ if (i960_bypass (insn, operands[1], operands[2], 0))
+ return \"xor %2,%1,%0\";
+ return \"xor %1,%2,%0\";
+}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -1744,71 +1793,50 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (xor:SI (ashift:SI (const_int 1)
- (match_operand:SI 1 "register_operand" "d"))
- (match_operand:SI 2 "arith_operand" "dI")))]
- ""
- "notbit %1,%2,%0")
-
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (ior:SI (match_operand:SI 1 "arith_operand" "%dI")
- (match_operand:SI 2 "arith_operand" "dI")))]
+ (not:SI (xor:SI (match_operand:SI 1 "register_operand" "%d")
+ (match_operand:SI 2 "register_operand" "d"))))]
""
"*
{
if (i960_bypass (insn, operands[1], operands[2], 0))
- return \"or %2,%1,%0\";
- return \"or %1,%2,%0\";
+ return \"xnor %2,%1,%0\";
+ return \"xnor %2,%1,%0\";
}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (ior:SI (not:SI (match_operand:SI 1 "arith_operand" "dI"))
+ (ior:SI (ashift:SI (const_int 1)
+ (match_operand:SI 1 "register_operand" "d"))
(match_operand:SI 2 "arith_operand" "dI")))]
""
- "*
-{
- if (i960_bypass (insn, operands[1], operands[2], 0))
- return \"notor %2,%1,%0\";
- return \"ornot %1,%2,%0\";
-}")
+ "setbit %1,%2,%0")
+;; (not (ashift 1 reg)) canonicalizes to (rotate -2 reg)
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (and:SI (not:SI (match_operand:SI 1 "arith_operand" "%dI"))
- (not:SI (match_operand:SI 2 "arith_operand" "dI"))))]
+ (and:SI (rotate:SI (const_int -2)
+ (match_operand:SI 1 "register_operand" "d"))
+ (match_operand:SI 2 "register_operand" "d")))]
""
- "*
-{
- if (i960_bypass (insn, operands[1], operands[2], 0))
- return \"nor %2,%1,%0\";
- return \"nor %1,%2,%0\";
-}")
+ "clrbit %1,%2,%0")
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (xor:SI (match_operand:SI 1 "arith_operand" "%dI")
- (match_operand:SI 2 "arith_operand" "dI")))]
+;; The above pattern canonicalizes to this when both the input and output
+;; are the same pseudo-register.
+(define_insn ""
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "=d")
+ (const_int 1)
+ (match_operand:SI 1 "register_operand" "d"))
+ (const_int 0))]
""
- "*
-{
- if (i960_bypass (insn, operands[1], operands[2], 0))
- return \"xor %2,%1,%0\";
- return \"xor %1,%2,%0\";
-}")
+ "clrbit %1,%0,%0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (not:SI (xor:SI (match_operand:SI 1 "arith_operand" "%dI")
- (match_operand:SI 2 "arith_operand" "dI"))))]
+ (xor:SI (ashift:SI (const_int 1)
+ (match_operand:SI 1 "register_operand" "d"))
+ (match_operand:SI 2 "arith_operand" "dI")))]
""
- "*
-{
- if (i960_bypass (insn, operands[1], operands[2], 0))
- return \"xnor %2,%1,%0\";
- return \"xnor %2,%1,%0\";
-}")
+ "notbit %1,%2,%0")
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=d")
diff --git a/gnu/usr.bin/gcc/config/i960/t-960bare b/gnu/usr.bin/gcc/config/i960/t-960bare
index 20a4870c939..c6be2a04f3e 100644
--- a/gnu/usr.bin/gcc/config/i960/t-960bare
+++ b/gnu/usr.bin/gcc/config/i960/t-960bare
@@ -1,7 +1,7 @@
LIBGCC1 =
CROSS_LIBGCC1 =
-LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c xp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' > dp-bit.c
@@ -12,9 +12,13 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-MULTILIB_OPTIONS=mnumerics
-MULTILIB_DIRNAMES=float
-MULTILIB_MATCHES=mnumerics=msb mnumerics=msc mnumerics=mkb mnumerics=mkc mnumerics=mmc mnumerics=mcb mnumerics=mcc
+xp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define EXTENDED_FLOAT_STUBS' > xp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> xp-bit.c
+
+MULTILIB_OPTIONS=mnumerics/msoft-float
+MULTILIB_DIRNAMES=float soft-float
+MULTILIB_MATCHES=mnumerics=msb mnumerics=msc mnumerics=mkb mnumerics=mkc mnumerics=mmc mnumerics=mcb mnumerics=mcc mnumerics=mjf msoft-float=msa msoft-float=mka msoft-float=mca msoft-float=mcf
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/i960/t-vxworks960 b/gnu/usr.bin/gcc/config/i960/t-vxworks960
index 84949cf17f5..c2dd5eb2060 100644
--- a/gnu/usr.bin/gcc/config/i960/t-vxworks960
+++ b/gnu/usr.bin/gcc/config/i960/t-vxworks960
@@ -3,8 +3,8 @@ CROSS_LIBGCC1 =
# We don't want to put exit in libgcc.a for VxWorks, because VxWorks
# does not have _exit.
-LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) -g1 -Dexit=unused_exit
-LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c
+TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit
+LIB2FUNCS_EXTRA = fp-bit.c dp-bit.c xp-bit.c
dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' > dp-bit.c
@@ -15,9 +15,13 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-MULTILIB_OPTIONS=mnumerics
-MULTILIB_DIRNAMES=float
-MULTILIB_MATCHES=mnumerics=msb mnumerics=msc mnumerics=mkb mnumerics=mkc mnumerics=mmc mnumerics=mcb mnumerics=mcc
+xp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define EXTENDED_FLOAT_STUBS' > xp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> xp-bit.c
+
+MULTILIB_OPTIONS=mnumerics/msoft-float
+MULTILIB_DIRNAMES=float soft-float
+MULTILIB_MATCHES=mnumerics=msb mnumerics=msc mnumerics=mkb mnumerics=mkc mnumerics=mmc mnumerics=mcb mnumerics=mcc msoft-float=msa msoft-float=mka msoft-float=mca msoft-float=mcf
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/i960/vx960-coff.h b/gnu/usr.bin/gcc/config/i960/vx960-coff.h
index 74b1b668f0d..b2e93fb9976 100644
--- a/gnu/usr.bin/gcc/config/i960/vx960-coff.h
+++ b/gnu/usr.bin/gcc/config/i960/vx960-coff.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Vxworks i960 version.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,11 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This file just exists to give specs for the 960 running on VxWorks. */
-
-#include "i960/i960-coff.h"
-
-/* VxWorks does all the library stuff itself. */
+/* This file just exists to give specs for the 960 running on VxWorks.
+ VxWorks does all the library stuff itself. */
#undef LIB_SPEC
#define LIB_SPEC ""
@@ -38,7 +35,10 @@ Boston, MA 02111-1307, USA. */
#define CPP_PREDEFINES "-Di960 -Di80960 -DI960 -DI80960 -Dvxworks -Acpu(i960) -Amachine(i960)"
/* The VxWorks header files expect the compiler to define CPU to a
- magic number. */
+ magic number. 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 "%{mic*:-D__i960\
@@ -47,16 +47,16 @@ Boston, MA 02111-1307, USA. */
%{mmc:-D__i960MC}\
%{mca:-D__i960CA}%{mcc:-D__i960CC}\
%{mcf:-D__i960CF}}\
- %{mka:-D__i960KA__ -D__i960_KA__ %{!ansi:-DCPU=I960KA}}\
- %{mkb:-D__i960KB__ -D__i960_KB__ %{!ansi:-DCPU=I960KB}}\
+ %{mka:-D__i960KA__ -D__i960_KA__ -DCPU=I960KA}\
+ %{mkb:-D__i960KB__ -D__i960_KB__ -DCPU=I960KB}\
%{msa:-D__i960SA__ -D__i960_SA__}\
%{msb:-D__i960SB__ -D__i960_SB__}\
%{mmc:-D__i960MC__ -D__i960_MC__}\
- %{mca:-D__i960CA__ -D__i960_CA__ %{!ansi:-DCPU=I960CA}}\
+ %{mca:-D__i960CA__ -D__i960_CA__ -DCPU=I960CA}\
%{mcc:-D__i960CC__ -D__i960_CC__}\
%{mcf:-D__i960CF__ -D__i960_CF__}\
%{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:\
- %{!mcc:%{!mcf:-D__i960_CA -D__i960CA__ %{!ansi:-DCPU=I960CA}\
+ %{!mcc:%{!mcf:-D__i960_CA -D__i960CA__ -DCPU=I960CA\
%{mic*:-D__i960CA}}}}}}}}}"
/* Default to -mca. */
diff --git a/gnu/usr.bin/gcc/config/i960/vx960.h b/gnu/usr.bin/gcc/config/i960/vx960.h
index 25f4f9793e0..ebf70dc183a 100644
--- a/gnu/usr.bin/gcc/config/i960/vx960.h
+++ b/gnu/usr.bin/gcc/config/i960/vx960.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Vxworks i960 version.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,11 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This file just exists to give specs for the 960 running on VxWorks. */
-
-#include "i960/i960.h"
-
-/* VxWorks does all the library stuff itself. */
+/* This file just exists to give specs for the 960 running on VxWorks.
+ VxWorks does all the library stuff itself. */
#undef LIB_SPEC
#define LIB_SPEC ""
diff --git a/gnu/usr.bin/gcc/config/linux-aout.h b/gnu/usr.bin/gcc/config/linux-aout.h
index 29fb8e9e132..ca8a39d5070 100644
--- a/gnu/usr.bin/gcc/config/linux-aout.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/linux.h b/gnu/usr.bin/gcc/config/linux.h
index c82cfe2dd09..3d5a8f78565 100644
--- a/gnu/usr.bin/gcc/config/linux.h
+++ b/gnu/usr.bin/gcc/config/linux.h
@@ -1,5 +1,5 @@
-/* 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 Free Software Foundation, Inc.
Contributed by Eric Youngdale.
Modified for stabs-in-ELF by H.J. Lu.
@@ -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,55 @@ 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. */
+#undef CC1_SPEC
+#define CC1_SPEC "%{profile:-p}"
+
+#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: %{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/gnu/usr.bin/gcc/config/lynx.h b/gnu/usr.bin/gcc/config/lynx.h
index 04919d4cc9b..62c790b6bfb 100644
--- a/gnu/usr.bin/gcc/config/lynx.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/m68k/3b1.h b/gnu/usr.bin/gcc/config/m68k/3b1.h
index 4c177df9804..5f9ec4c7301 100644
--- a/gnu/usr.bin/gcc/config/m68k/3b1.h
+++ b/gnu/usr.bin/gcc/config/m68k/3b1.h
@@ -1,8 +1,7 @@
/* Definitions of target machine for GNU compiler.
AT&T UNIX PC version (pc7300, 3b1)
- Written by Alex Crain (alex@umbc3.umd.edu).
-
- Copyright (C) 1987, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1993, 1996 Free Software Foundation, Inc.
+ Contributed by Alex Crain (alex@umbc3.umd.edu).
This file is part of GNU CC.
@@ -119,7 +118,7 @@ output_file_directive ((FILE), main_input_filename)
#undef ASM_OUTPUT_INTERNAL_LABEL
#undef ASM_OUTPUT_OPCODE
#undef ASM_OUTPUT_LOCAL
-#undef ASM_OUTPUT_LABELREF
+#undef USER_LABEL_PREFIX
#undef ASM_OUTPUT_ASCII
#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T unixpc syntax)");
@@ -437,8 +436,7 @@ int switch_table_difference_label_flag;
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%u\n", (ROUNDED)))
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, "%s", NAME)
+#define USER_LABEL_PREFIX ""
/* Override usual definitions of SDB output macros.
These definitions differ only in the absence of the period
diff --git a/gnu/usr.bin/gcc/config/m68k/altos3068.h b/gnu/usr.bin/gcc/config/m68k/altos3068.h
index e778d4215b7..5903a12d5a6 100644
--- a/gnu/usr.bin/gcc/config/m68k/altos3068.h
+++ b/gnu/usr.bin/gcc/config/m68k/altos3068.h
@@ -1,8 +1,6 @@
/* Definitions of target machine for GNU compiler. Altos 3068 68020 version.
- Copyright (C) 1988, 1989, 1993 Free Software Foundation, Inc.
-
-Written by Jyrki Kuoppala <jkp@cs.hut.fi>
-Last modified: Mon Mar 6 22:47:58 1989
+ Copyright (C) 1988, 1989, 1993, 1996 Free Software Foundation, Inc.
+ Contributed by Jyrki Kuoppala <jkp@cs.hut.fi>
This file is part of GNU CC.
@@ -28,7 +26,7 @@ Boston, MA 02111-1307, USA. */
/* 5 is without 68881. Change to 7 if you have 68881 */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 5
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
/* Don't try using XFmode. */
#undef LONG_DOUBLE_TYPE_SIZE
@@ -40,7 +38,7 @@ Boston, MA 02111-1307, USA. */
This will control the use of inline 68881 insns in certain macros.
Also inform the program which CPU this is for. */
-#if TARGET_DEFAULT & 02
+#if TARGET_DEFAULT & MASK_68881
/* -m68881 is the default */
#define CPP_SPEC \
diff --git a/gnu/usr.bin/gcc/config/m68k/apollo68.h b/gnu/usr.bin/gcc/config/m68k/apollo68.h
index 0cf2fa08c04..8eed141dc84 100644
--- a/gnu/usr.bin/gcc/config/m68k/apollo68.h
+++ b/gnu/usr.bin/gcc/config/m68k/apollo68.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Apollo 680X0 version.
- Copyright (C) 1989,1992 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1992, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
/* Target switches for the Apollo is the same as in m68k.h, except
@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
This will control the use of inline 68881 insns in certain macros.
Also inform the program which CPU this is for. */
-#if TARGET_DEFAULT & 02
+#if TARGET_DEFAULT & MASK_68881
/* -m68881 is the default */
#define CPP_SPEC \
@@ -87,10 +87,6 @@ Boston, MA 02111-1307, USA. */
#define IDENT_DIRECTIVE
#define ASM_OUTPUT_IDENT(FILE, NAME)
-/* Allow dollarsigns in identifiers */
-
-#define DOLLARS_IN_IDENTIFIERS 2
-
/* -m68000 requires special flags to the assembler. */
#define ASM_SPEC \
@@ -100,7 +96,7 @@ Boston, MA 02111-1307, USA. */
Note that includes knowledge of the default specs for gcc, ie. no
args translates to the same effect as -m68881 */
-#if TARGET_DEFAULT & 2
+#if TARGET_DEFAULT & MASK_68881
/* -m68881 is the default */
#define STARTFILE_SPEC \
"%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}"
@@ -184,8 +180,13 @@ Boston, MA 02111-1307, USA. */
/* config/m68k.md has an explicit reference to the program counter,
prefix this by the register prefix. */
-#define ASM_RETURN_CASE_JUMP return "jmp %%pc@(2,%0:w)"
-
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)" \
+ } while (0)
/* Here are the new register names. */
diff --git a/gnu/usr.bin/gcc/config/m68k/ccur-GAS.h b/gnu/usr.bin/gcc/config/m68k/ccur-GAS.h
index f21c3eae239..685eb971a50 100644
--- a/gnu/usr.bin/gcc/config/m68k/ccur-GAS.h
+++ b/gnu/usr.bin/gcc/config/m68k/ccur-GAS.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Concurrent 68k version.
- Copyright (C) 1987, 1988, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -38,9 +38,10 @@ Boston, MA 02111-1307, USA. */
#define MOVE_RATIO 100
#define SPACE_AFTER_L_OPTION
-#define SWITCHES_NEED_SPACES " "
+#define SWITCHES_NEED_SPACES "oL"
-#define TARGET_DEFAULT 0407 /* See m68k.h. 7 means 68020 with 68881. */
+/* See m68k.h. 7 means 68020 with 68881. */
+#define TARGET_DEFAULT (MASK_68040|MASK_BITFIELD|MASK_68881|MASK_68020)
#include "m68k/m68k.h"
diff --git a/gnu/usr.bin/gcc/config/m68k/coff.h b/gnu/usr.bin/gcc/config/m68k/coff.h
index b2fc34379d6..acd45e7bb2d 100644
--- a/gnu/usr.bin/gcc/config/m68k/coff.h
+++ b/gnu/usr.bin/gcc/config/m68k/coff.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
m68k series COFF object files and debugging, version.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,15 +24,11 @@ Boston, MA 02111-1307, USA. */
/* Generate sdb debugging information. */
-#undef DBX_DEBUGGING_INFO
#define SDB_DEBUGGING_INFO
/* Output DBX (stabs) debugging information if using -gstabs. */
-#define DBX_DEBUGGING_INFO
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
+#include "dbxcoff.h"
/* COFF symbols don't start with an underscore. */
@@ -59,7 +55,13 @@ Boston, MA 02111-1307, USA. */
/* config/m68k.md has an explicit reference to the program counter,
prefix this by the register prefix. */
-#define ASM_RETURN_CASE_JUMP return "jmp %%pc@(2,%0:w)"
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
/* Here are the new register names. */
@@ -84,6 +86,28 @@ Boston, MA 02111-1307, USA. */
#define ASM_FILE_START(FILE) \
output_file_directive ((FILE), main_input_filename)
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as uninitialized global
+ data. */
+
+#define BSS_SECTION_ASM_OP ".section\t.bss"
+
+/* 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))
+
+/* Support generic sections */
+
+#undef ASM_OUTPUT_SECTION_NAME
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
+ fprintf((FILE), ".section\t%s,\"%c\"\n", (NAME), \
+ (DECL) && (TREE_CODE (DECL) == FUNCTION_DECL || \
+ DECL_READONLY_SECTION (DECL, RELOC)) ? 'x' : 'd')
+
/* Support the ctors and dtors sections for g++. */
#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\""
@@ -148,4 +172,5 @@ dtors_section () \
/* Don't assume anything about startfiles. */
+#undef STARTFILE_SPEC
#define STARTFILE_SPEC ""
diff --git a/gnu/usr.bin/gcc/config/m68k/crds.h b/gnu/usr.bin/gcc/config/m68k/crds.h
index 3d848c26fb3..441b285b4ee 100644
--- a/gnu/usr.bin/gcc/config/m68k/crds.h
+++ b/gnu/usr.bin/gcc/config/m68k/crds.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler;
Charles River Data Systems UNiverse/32.
- Copyright (C) 1987, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
Contributed by Gary E. Miller (Gary_Edmunds_Miller@cup.portal.com)
This file is part of GNU CC.
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
#define SGS /* Uses SGS assembler */
#define SGS_SWITCH_TABLES /* Different switch table handling */
+#define SGS_NO_LI /* Suppress jump table label usage */
#define CRDS /* Charles River Data Systems assembler */
#include "m68k/m68k.h"
@@ -31,7 +32,8 @@ Boston, MA 02111-1307, USA. */
aligned such that we can correctly extract bitfields from them.
Someone should check whether the usual compiler on the crds machine
provides the equivalent behavior of STRUCTURE_SIZE_BOUNDARY. */
-#error This does not define STRUCTURE_SIZE_BOUNDARY
+/* Set to 16 because all other m68k targets have it so */
+#define STRUCTURE_SIZE_BOUNDARY 16
/* See m68k.h. 0 means 680[01]0 with no 68881. */
@@ -75,8 +77,13 @@ Boston, MA 02111-1307, USA. */
/* UNOS need stack probe :-( */
+#if 0
#define HAVE_probe 1
#define gen_probe() gen_rtx(ASM_INPUT, VOIDmode, "tstb -2048(sp)\t;probe\n")
+#else
+#undef NEED_PROBE
+#define NEED_PROBE (-2048)
+#endif
/* use memcpy, memset instead of bcopy, etc. */
@@ -105,18 +112,7 @@ Boston, MA 02111-1307, USA. */
#define STRUCT_VALUE gen_rtx(MEM, Pmode, gen_rtx( , , ) )
*/
-#define EXTRA_SECTIONS in_bss
-
-#define EXTRA_SECTION_FUNCTIONS \
-void \
-bss_section () \
-{ \
- if (in_section != in_bss) \
- { \
- fprintf (asm_out_file, ".bss\n"); \
- in_section = in_bss; \
- } \
-}
+#define BSS_SECTION_ASM_OP ".bss"
/* Specify how to pad function arguments.
Value should be `upward', `downward' or `none'.
@@ -157,6 +153,11 @@ bss_section () \
#undef ASM_APP_OFF
#define ASM_APP_OFF ";#NO_APP\n"
+/* The prefix for immediate operands. */
+
+#undef IMMEDIATE_PREFIX
+#define IMMEDIATE_PREFIX "$"
+
/* This is how to output an assembler line defining a `double' constant. */
#undef ASM_OUTPUT_DOUBLE
@@ -234,6 +235,7 @@ do { int i; \
}
+#if 0
/* 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.
@@ -311,6 +313,7 @@ do { int i; \
REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
else { putc ('$', FILE); output_addr_const (FILE, X); }}
+#endif
/* Note that this contains a kludge that knows that the only reason
we have an address (plus (label_ref...) (reg...))
@@ -501,10 +504,6 @@ do { int i; \
fprintf (FILE, "\tadd.l #%d,sp\n", - (fsize + 4)); \
} \
} \
- for (regno = 24; regno < 56; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- fprintf(FILE, "\tfpmoved %s, sp@-\n", \
- reg_names[regno]); \
for (regno = 16; regno < 24; regno++) \
if (regs_ever_live[regno] && ! call_used_regs[regno]) \
mask |= 1 << (regno - 16); \
@@ -546,11 +545,6 @@ do { int i; \
int fsize = ((SIZE) + 3) & -4; \
int big = 0; \
nregs = 0; fmask = 0; fpoffset = 0; \
- for (regno = 24 ; regno < 56 ; regno++) \
- if (regs_ever_live[regno] && ! call_used_regs[regno]) \
- nregs++; \
- fpoffset = nregs*8; \
- nregs = 0; \
for (regno = 16; regno < 24; regno++) \
if (regs_ever_live[regno] && ! call_used_regs[regno]) \
{ nregs++; fmask |= 1 << (23 - regno); } \
diff --git a/gnu/usr.bin/gcc/config/m68k/dpx2.h b/gnu/usr.bin/gcc/config/m68k/dpx2.h
index 1402a256186..14f0606b8aa 100644
--- a/gnu/usr.bin/gcc/config/m68k/dpx2.h
+++ b/gnu/usr.bin/gcc/config/m68k/dpx2.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Bull DPX/2 200 and 300 systems (m68k, SysVr3).
- Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Contributed by Frederic Pierresteguy (F.Pierresteguy@frcl.bull.fr).
This file is part of GNU CC.
@@ -36,7 +36,7 @@ Boston, MA 02111-1307, USA. */
* but this will get us going.
*/
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
#define OBJECT_FORMAT_COFF
@@ -79,7 +79,7 @@ Boston, MA 02111-1307, USA. */
* bitfield instructions do not seem to work a clean way.
*/
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 3
+#define TARGET_DEFAULT (MASK_68881|MASK_68020)
/* The native assembler doesn't support fmovecr. */
#define NO_ASM_FMOVECR
diff --git a/gnu/usr.bin/gcc/config/m68k/hp320.h b/gnu/usr.bin/gcc/config/m68k/hp320.h
index f748f3fde13..1388e0262b2 100644
--- a/gnu/usr.bin/gcc/config/m68k/hp320.h
+++ b/gnu/usr.bin/gcc/config/m68k/hp320.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. HP-UX 68000/68020 version.
- Copyright (C) 1987, 1988, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -65,7 +65,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
@@ -77,7 +77,7 @@ Boston, MA 02111-1307, USA. */
#define NO_DOT_IN_LABEL
-#if TARGET_DEFAULT & 02 /* -m68881 is the default */
+#if TARGET_DEFAULT & MASK_68881 /* -m68881 is the default */
/* These definitions differ from those used for GAS by defining __HPUX_ASM__.
This is needed because some programs, particularly GDB, need to
@@ -98,7 +98,7 @@ Boston, MA 02111-1307, USA. */
#else /* not HPUX_ASM */
-#if TARGET_DEFAULT & 02 /* -m68881 is the default */
+#if TARGET_DEFAULT & MASK_68881 /* -m68881 is the default */
#define CPP_SPEC \
"%{!msoft-float:-D__HAVE_68881__ }\
@@ -178,8 +178,6 @@ Boston, MA 02111-1307, USA. */
#undef ASM_OUTPUT_COMMON
#undef ASM_OUTPUT_LOCAL
#undef ASM_FORMAT_PRIVATE_NAME
-#undef PRINT_OPERAND
-#undef PRINT_OPERAND_ADDRESS
#undef FUNCTION_PROFILER
#undef ASM_OUTPUT_INTERNAL_LABEL
#undef GLOBAL_ASM_OP
@@ -333,23 +331,54 @@ do { long l[3]; \
#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME)
#define ASM_OUTPUT_SOURCE_LINE(FILE, LINENO)
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
#ifdef AS_BUG_FLOATING_CONSTANT
-#define PRINT_OPERAND_FLOAT(CODE,FILE,VALUE,INT) \
- do { REAL_VALUE_TO_TARGET_SINGLE (VALUE, INT); \
- fprintf (FILE, "&0x%x", INT); } while (0)
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "&0x%lx", l); \
+ } while (0)
#else
-#define PRINT_OPERAND_FLOAT(CODE,FILE,VALUE,INT) \
- do { if (CODE == 'f') \
- { char dstr[30]; \
- REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
- fprintf (FILE, "&0f%s", dstr); \
- } \
- else \
- { \
- REAL_VALUE_TO_TARGET_SINGLE (VALUE, INT); \
- fprintf (FILE, "&0x%x", INT); } } while (0)
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ if (CODE == 'f') \
+ { \
+ char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.9g", dstr); \
+ fprintf ((FILE), "&0f%s", dstr); \
+ } \
+ else \
+ { \
+ long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf ((FILE), "&0x%lx", l); \
+ } \
+ } while (0)
#endif /* AS_BUG_FLOATING_CONSTANT */
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ fprintf (FILE, "&0f%s", dstr); \
+ } while (0)
+
+/* Note, long double immediate operands are not actually
+ generated by m68k.md. */
+#undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
+#define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ fprintf (FILE, "&0f%s", dstr); \
+ } while (0)
+
+#if 0
+#undef PRINT_OPERAND
#define PRINT_OPERAND(FILE, X, CODE) \
{ if (CODE == '.') fprintf (FILE, "."); \
else if (CODE == '#') fprintf (FILE, "&"); \
@@ -380,7 +409,9 @@ do { long l[3]; \
REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr); \
fprintf (FILE, "&0f%s", dstr); } \
else { putc ('&', FILE); output_addr_const (FILE, X); }}
+#endif
+#undef PRINT_OPERAND_ADDRESS
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
{ register rtx reg1, reg2, breg, ireg; \
register rtx addr = ADDR; \
diff --git a/gnu/usr.bin/gcc/config/m68k/hp3bsd.h b/gnu/usr.bin/gcc/config/m68k/hp3bsd.h
index d800f7a137b..34405f88350 100644
--- a/gnu/usr.bin/gcc/config/m68k/hp3bsd.h
+++ b/gnu/usr.bin/gcc/config/m68k/hp3bsd.h
@@ -2,7 +2,7 @@
/* See m68k.h. 7 means 68020 with 68881. */
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
This will control the use of inline 68881 insns in certain macros. */
diff --git a/gnu/usr.bin/gcc/config/m68k/hp3bsd44.h b/gnu/usr.bin/gcc/config/m68k/hp3bsd44.h
index b94b598d0ea..a3b652ffe35 100644
--- a/gnu/usr.bin/gcc/config/m68k/hp3bsd44.h
+++ b/gnu/usr.bin/gcc/config/m68k/hp3bsd44.h
@@ -2,7 +2,7 @@
/* See m68k.h. 7 means 68020 with 68881. */
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
This will control the use of inline 68881 insns in certain macros. */
diff --git a/gnu/usr.bin/gcc/config/m68k/isi-nfp.h b/gnu/usr.bin/gcc/config/m68k/isi-nfp.h
index f3544485feb..fbded9e8bdb 100644
--- a/gnu/usr.bin/gcc/config/m68k/isi-nfp.h
+++ b/gnu/usr.bin/gcc/config/m68k/isi-nfp.h
@@ -1,6 +1,6 @@
/* Define target machine as an ISI 68000/68020 with no 68881. */
-#define TARGET_DEFAULT 5
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
#include "m68k/isi.h"
diff --git a/gnu/usr.bin/gcc/config/m68k/isi.h b/gnu/usr.bin/gcc/config/m68k/isi.h
index bc1b969d980..a458cf9e080 100644
--- a/gnu/usr.bin/gcc/config/m68k/isi.h
+++ b/gnu/usr.bin/gcc/config/m68k/isi.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. ISI 68000/68020 version.
Intended only for use with GAS, and not ISI's assembler, which is buggy
- Copyright (C) 1988 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -23,10 +23,10 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
-#if TARGET_DEFAULT & 2
+#if TARGET_DEFAULT & MASK_68881
/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
This will control the use of inline 68881 insns in certain macros. */
diff --git a/gnu/usr.bin/gcc/config/m68k/lb1sf68.asm b/gnu/usr.bin/gcc/config/m68k/lb1sf68.asm
index 2cdeb7088b5..a8a7a6ced5e 100644
--- a/gnu/usr.bin/gcc/config/m68k/lb1sf68.asm
+++ b/gnu/usr.bin/gcc/config/m68k/lb1sf68.asm
@@ -1,7 +1,9 @@
-/* libgcc1 routines for 68000 w/o floating-point hardware. */
-/* Copyright (C) 1994 Free Software Foundation, Inc.
+/* libgcc1 routines for 68000 w/o floating-point hardware.
+ Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
-This file is free software; you can redistribute it and/or modify it
+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.
@@ -212,7 +214,11 @@ TRUNCDFSF = 7
| void __clear_sticky_bits(void);
SYM (__clear_sticky_bit):
lea SYM (_fpCCR),a0
+#ifndef __mcf5200__
movew IMM (0),a0@(STICK)
+#else
+ clr.w a0@(STICK)
+#endif
rts
|=============================================================================
@@ -242,12 +248,22 @@ FPTRAP = 15
$_exception_handler:
lea SYM (_fpCCR),a0
movew d7,a0@(EBITS) | set __exception_bits
+#ifndef __mcf5200__
orw d7,a0@(STICK) | and __sticky_bits
+#else
+ movew a0@(STICK),d4
+ orl d7,d4
+ movew d4,a0@(STICK)
+#endif
movew d6,a0@(FORMT) | and __format
movew d5,a0@(LASTO) | and __last_operation
| Now put the operands in place:
+#ifndef __mcf5200__
cmpw IMM (SINGLE_FLOAT),d6
+#else
+ cmpl IMM (SINGLE_FLOAT),d6
+#endif
beq 1f
movel a6@(8),a0@(OPER1)
movel a6@(12),a0@(OPER1+4)
@@ -258,11 +274,23 @@ $_exception_handler:
movel a6@(12),a0@(OPER2)
2:
| And check whether the exception is trap-enabled:
+#ifndef __mcf5200__
andw a0@(TRAPE),d7 | is exception trap-enabled?
+#else
+ clrl d6
+ movew a0@(TRAPE),d6
+ andl d6,d7
+#endif
beq 1f | no, exit
pea SYM (_fpCCR) | yes, push address of _fpCCR
trap IMM (FPTRAP) | and trap
+#ifndef __mcf5200__
1: moveml sp@+,d2-d7 | restore data registers
+#else
+1: moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 | and return
rts
#endif /* L_floatex */
@@ -276,7 +304,11 @@ SYM (__mulsi3):
muluw sp@(10), d0 /* x0*y1 */
movew sp@(6), d1 /* x1 -> d1 */
muluw sp@(8), d1 /* x1*y0 */
+#ifndef __mcf5200__
addw d1, d0
+#else
+ addl d1, d0
+#endif
swap d0
clrw d0
movew sp@(6), d1 /* x1 -> d1 */
@@ -291,6 +323,7 @@ SYM (__mulsi3):
.proc
.globl SYM (__udivsi3)
SYM (__udivsi3):
+#ifndef __mcf5200__
movel d2, sp@-
movel sp@(12), d1 /* d1 = divisor */
movel sp@(8), d0 /* d0 = dividend */
@@ -324,7 +357,7 @@ L4: lsrl IMM (1), d1 /* shift divisor */
swap d2
mulu d0, d2 /* high part, at most 17 bits */
swap d2 /* align high part with low part */
- btst IMM (0), d2 /* high part 17 bits? */
+ tstw d2 /* high part 17 bits? */
jne L5 /* if 17 bits, quotient was too large */
addl d2, d1 /* add parts */
jcs L5 /* if sum is 33 bits, quotient was too large */
@@ -334,6 +367,31 @@ L5: subql IMM (1), d0 /* adjust quotient */
L6: movel sp@+, d2
rts
+
+#else /* __mcf5200__ */
+
+/* Coldfire implementation of non-restoring division algorithm from
+ Hennessy & Patterson, Appendix A. */
+ link a6,IMM (-12)
+ moveml d2-d4,sp@
+ movel a6@(8),d0
+ movel a6@(12),d1
+ clrl d2 | clear p
+ moveq IMM (31),d4
+L1: addl d0,d0 | shift reg pair (p,a) one bit left
+ addxl d2,d2
+ movl d2,d3 | subtract b from p, store in tmp.
+ subl d1,d3
+ jmi L2 | if the result is not is negative, set the
+ bset IMM (0),d0 | low order bit of a to 1 and store tmp in p.
+ movl d3,d2
+L2: subql IMM (1),d4
+ jcc L1
+ moveml sp@,d2-d4 | restore data registers
+ unlk a6 | and return
+ rts
+#endif /* __mcf5200__ */
+
#endif /* L_udivsi3 */
#ifdef L_divsi3
@@ -343,15 +401,23 @@ L6: movel sp@+, d2
SYM (__divsi3):
movel d2, sp@-
- moveb IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */
+ moveq IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */
movel sp@(12), d1 /* d1 = divisor */
jpl L1
negl d1
+#ifndef __mcf5200__
negb d2 /* change sign because divisor <0 */
+#else
+ negl d2 /* change sign because divisor <0 */
+#endif
L1: movel sp@(8), d0 /* d0 = dividend */
jpl L2
negl d0
+#ifndef __mcf5200__
negb d2
+#else
+ negl d2
+#endif
L2: movel d1, sp@-
movel d0, sp@-
@@ -378,10 +444,14 @@ SYM (__umodsi3):
jbsr SYM (__udivsi3)
addql IMM (8), sp
movel sp@(8), d1 /* d1 = divisor */
+#ifndef __mcf5200__
movel d1, sp@-
movel d0, sp@-
jbsr SYM (__mulsi3) /* d0 = (a/b)*b */
addql IMM (8), sp
+#else
+ mulsl d1,d0
+#endif
movel sp@(4), d1 /* d1 = dividend */
subl d0, d1 /* d1 = a - (a/b)*b */
movel d1, d0
@@ -400,10 +470,14 @@ SYM (__modsi3):
jbsr SYM (__divsi3)
addql IMM (8), sp
movel sp@(8), d1 /* d1 = divisor */
+#ifndef __mcf5200__
movel d1, sp@-
movel d0, sp@-
jbsr SYM (__mulsi3) /* d0 = (a/b)*b */
addql IMM (8), sp
+#else
+ mulsl d1,d0
+#endif
movel sp@(4), d1 /* d1 = dividend */
subl d0, d1 /* d1 = a - (a/b)*b */
movel d1, d0
@@ -464,9 +538,8 @@ ROUND_TO_MINUS = 3 | round result towards minus infinity
Ld$den:
| Return and signal a denormalized number
orl d7,d0
- movew IMM (UNDERFLOW),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (DOUBLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (DOUBLE_FLOAT),d6
jmp $_exception_handler
Ld$infty:
@@ -475,27 +548,24 @@ Ld$overflow:
movel IMM (0x7ff00000),d0
movel IMM (0),d1
orl d7,d0
- movew IMM (OVERFLOW),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (DOUBLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+OVERFLOW),d7
+ moveq IMM (DOUBLE_FLOAT),d6
jmp $_exception_handler
Ld$underflow:
| Return 0 and set the exception flags
movel IMM (0),d0
movel d0,d1
- movew IMM (UNDERFLOW),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (DOUBLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (DOUBLE_FLOAT),d6
jmp $_exception_handler
Ld$inop:
| Return a quiet NaN and set the exception flags
movel IMM (QUIET_NaN),d0
movel d0,d1
- movew IMM (INVALID_OPERATION),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (DOUBLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7
+ moveq IMM (DOUBLE_FLOAT),d6
jmp $_exception_handler
Ld$div$0:
@@ -503,9 +573,8 @@ Ld$div$0:
movel IMM (0x7ff00000),d0
movel IMM (0),d1
orl d7,d0
- movew IMM (DIVIDE_BY_ZERO),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (DOUBLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
+ moveq IMM (DOUBLE_FLOAT),d6
jmp $_exception_handler
|=============================================================================
@@ -542,8 +611,13 @@ SYM (__subdf3):
| double __adddf3(double, double);
SYM (__adddf3):
+#ifndef __mcf5200__
link a6,IMM (0) | everything will be done in registers
moveml d2-d7,sp@- | save all data registers and a2 (but d0-d1)
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movel a6@(8),d0 | get first operand
movel a6@(12),d1 |
movel a6@(16),d2 | get second operand
@@ -561,10 +635,15 @@ SYM (__adddf3):
andl IMM (0x80000000),d7 | isolate a's sign bit '
swap d6 | and also b's sign bit '
+#ifndef __mcf5200__
andw IMM (0x8000),d6 |
orw d6,d7 | and combine them into d7, so that a's sign '
| bit is in the high word and b's is in the '
| low word, so d6 is free to be used
+#else
+ andl IMM (0x8000),d6
+ orl d6,d7
+#endif
movel d7,a0 | now save d7 into a0, so d7 is free to
| be used also
@@ -583,7 +662,11 @@ SYM (__adddf3):
orl d7,d0 | and put hidden bit back
Ladddf$1:
swap d4 | shift right exponent so that it starts
+#ifndef __mcf5200__
lsrw IMM (5),d4 | in bit 0 and not bit 20
+#else
+ lsrl IMM (5),d4 | in bit 0 and not bit 20
+#endif
| Now we have a's exponent in d4 and fraction in d0-d1 '
movel d2,d5 | save b to get exponent
andl d6,d5 | get exponent in d5
@@ -595,7 +678,11 @@ Ladddf$1:
orl d7,d2 | and put hidden bit back
Ladddf$2:
swap d5 | shift right exponent so that it starts
+#ifndef __mcf5200__
lsrw IMM (5),d5 | in bit 0 and not bit 20
+#else
+ lsrl IMM (5),d5 | in bit 0 and not bit 20
+#endif
| Now we have b's exponent in d5 and fraction in d2-d3. '
@@ -606,7 +693,13 @@ Ladddf$2:
| and d4-d5-d6-d7 for the second. To do this we store (temporarily) the
| exponents in a2-a3.
+#ifndef __mcf5200__
moveml a2-a3,sp@- | save the address registers
+#else
+ movel a2,sp@-
+ movel a3,sp@-
+ movel a4,sp@-
+#endif
movel d4,a2 | save the exponents
movel d5,a3 |
@@ -620,32 +713,88 @@ Ladddf$2:
| Here we shift the numbers until the exponents are the same, and put
| the largest exponent in a2.
+#ifndef __mcf5200__
exg d4,a2 | get exponents back
exg d5,a3 |
cmpw d4,d5 | compare the exponents
+#else
+ movel d4,a4 | get exponents back
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+ cmpl d4,d5 | compare the exponents
+#endif
beq Ladddf$3 | if equal don't shift '
bhi 9f | branch if second exponent is higher
| Here we have a's exponent larger than b's, so we have to shift b. We do
| this by using as counter d2:
1: movew d4,d2 | move largest exponent to d2
+#ifndef __mcf5200__
subw d5,d2 | and subtract second exponent
exg d4,a2 | get back the longs we saved
exg d5,a3 |
+#else
+ subl d5,d2 | and subtract second exponent
+ movel d4,a4 | get back the longs we saved
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+#endif
| if difference is too large we don't shift (actually, we can just exit) '
+#ifndef __mcf5200__
cmpw IMM (DBL_MANT_DIG+2),d2
+#else
+ cmpl IMM (DBL_MANT_DIG+2),d2
+#endif
bge Ladddf$b$small
+#ifndef __mcf5200__
cmpw IMM (32),d2 | if difference >= 32, shift by longs
+#else
+ cmpl IMM (32),d2 | if difference >= 32, shift by longs
+#endif
bge 5f
-2: cmpw IMM (16),d2 | if difference >= 16, shift by words
+2:
+#ifndef __mcf5200__
+ cmpw IMM (16),d2 | if difference >= 16, shift by words
+#else
+ cmpl IMM (16),d2 | if difference >= 16, shift by words
+#endif
bge 6f
bra 3f | enter dbra loop
-4: lsrl IMM (1),d4
+4:
+#ifndef __mcf5200__
+ lsrl IMM (1),d4
roxrl IMM (1),d5
roxrl IMM (1),d6
roxrl IMM (1),d7
-3: dbra d2,4b
+#else
+ lsrl IMM (1),d7
+ btst IMM (0),d6
+ beq 10f
+ bset IMM (31),d7
+10: lsrl IMM (1),d6
+ btst IMM (0),d5
+ beq 11f
+ bset IMM (31),d6
+11: lsrl IMM (1),d5
+ btst IMM (0),d4
+ beq 12f
+ bset IMM (31),d5
+12: lsrl IMM (1),d4
+#endif
+3:
+#ifndef __mcf5200__
+ dbra d2,4b
+#else
+ subql IMM (1),d2
+ bpl 4b
+#endif
movel IMM (0),d2
movel d2,d3
bra Ladddf$4
@@ -654,7 +803,11 @@ Ladddf$2:
movel d5,d6
movel d4,d5
movel IMM (0),d4
+#ifndef __mcf5200__
subw IMM (32),d2
+#else
+ subl IMM (32),d2
+#endif
bra 2b
6:
movew d6,d7
@@ -665,28 +818,82 @@ Ladddf$2:
swap d5
movew IMM (0),d4
swap d4
+#ifndef __mcf5200__
subw IMM (16),d2
+#else
+ subl IMM (16),d2
+#endif
bra 3b
-9: exg d4,d5
+9:
+#ifndef __mcf5200__
+ exg d4,d5
movew d4,d6
subw d5,d6 | keep d5 (largest exponent) in d4
exg d4,a2
exg d5,a3
+#else
+ movel d5,d6
+ movel d4,d5
+ movel d6,d4
+ subl d5,d6
+ movel d4,a4
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+#endif
| if difference is too large we don't shift (actually, we can just exit) '
+#ifndef __mcf5200__
cmpw IMM (DBL_MANT_DIG+2),d6
+#else
+ cmpl IMM (DBL_MANT_DIG+2),d6
+#endif
bge Ladddf$a$small
+#ifndef __mcf5200__
cmpw IMM (32),d6 | if difference >= 32, shift by longs
+#else
+ cmpl IMM (32),d6 | if difference >= 32, shift by longs
+#endif
bge 5f
-2: cmpw IMM (16),d6 | if difference >= 16, shift by words
+2:
+#ifndef __mcf5200__
+ cmpw IMM (16),d6 | if difference >= 16, shift by words
+#else
+ cmpl IMM (16),d6 | if difference >= 16, shift by words
+#endif
bge 6f
bra 3f | enter dbra loop
-4: lsrl IMM (1),d0
+4:
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
roxrl IMM (1),d1
roxrl IMM (1),d2
roxrl IMM (1),d3
-3: dbra d6,4b
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+#endif
+3:
+#ifndef __mcf5200__
+ dbra d6,4b
+#else
+ subql IMM (1),d6
+ bpl 4b
+#endif
movel IMM (0),d7
movel d7,d6
bra Ladddf$4
@@ -695,7 +902,11 @@ Ladddf$2:
movel d1,d2
movel d0,d1
movel IMM (0),d0
+#ifndef __mcf5200__
subw IMM (32),d6
+#else
+ subl IMM (32),d6
+#endif
bra 2b
6:
movew d2,d3
@@ -706,18 +917,40 @@ Ladddf$2:
swap d1
movew IMM (0),d0
swap d0
+#ifndef __mcf5200__
subw IMM (16),d6
+#else
+ subl IMM (16),d6
+#endif
bra 3b
Ladddf$3:
+#ifndef __mcf5200__
exg d4,a2
exg d5,a3
+#else
+ movel d4,a4
+ movel a2,d4
+ movel a4,a2
+ movel d5,a4
+ movel a3,d5
+ movel a4,a3
+#endif
Ladddf$4:
| Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and
| the signs in a4.
| Here we have to decide whether to add or subtract the numbers:
+#ifndef __mcf5200__
exg d7,a0 | get the signs
exg d6,a3 | a3 is free to be used
+#else
+ movel d7,a4
+ movel a0,d7
+ movel a4,a0
+ movel d6,a4
+ movel a3,d6
+ movel a4,a3
+#endif
movel d7,d6 |
movew IMM (0),d7 | get a's sign in d7 '
swap d6 |
@@ -725,8 +958,17 @@ Ladddf$4:
eorl d7,d6 | compare the signs
bmi Lsubdf$0 | if the signs are different we have
| to subtract
+#ifndef __mcf5200__
exg d7,a0 | else we add the numbers
exg d6,a3 |
+#else
+ movel d7,a4
+ movel a0,d7
+ movel a4,a0
+ movel d6,a4
+ movel a3,d6
+ movel a4,a3
+#endif
addl d7,d3 |
addxl d6,d2 |
addxl d5,d1 |
@@ -736,7 +978,13 @@ Ladddf$4:
movel a0,d7 |
andl IMM (0x80000000),d7 | d7 now has the sign
+#ifndef __mcf5200__
moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
| the case of denormalized numbers in the rounding routine itself).
@@ -744,28 +992,64 @@ Ladddf$4:
| one more bit we check this:
btst IMM (DBL_MANT_DIG+1),d0
beq 1f
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
roxrl IMM (1),d2
roxrl IMM (1),d3
addw IMM (1),d4
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
1:
lea Ladddf$5,a0 | to return from rounding routine
lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
movew a1@(6),d6 | rounding mode in d6
beq Lround$to$nearest
+#ifndef __mcf5200__
cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
bhi Lround$to$minus
blt Lround$to$zero
bra Lround$to$plus
Ladddf$5:
| Put back the exponent and check for overflow
+#ifndef __mcf5200__
cmpw IMM (0x7ff),d4 | is the exponent big?
+#else
+ cmpl IMM (0x7ff),d4 | is the exponent big?
+#endif
bge 1f
bclr IMM (DBL_MANT_DIG-1),d0
+#ifndef __mcf5200__
lslw IMM (4),d4 | put exponent back into position
+#else
+ lsll IMM (4),d4 | put exponent back into position
+#endif
swap d0 |
+#ifndef __mcf5200__
orw d4,d0 |
+#else
+ orl d4,d0 |
+#endif
swap d0 |
bra Ladddf$ret
1:
@@ -774,17 +1058,26 @@ Ladddf$5:
Lsubdf$0:
| Here we do the subtraction.
+#ifndef __mcf5200__
exg d7,a0 | put sign back in a0
exg d6,a3 |
+#else
+ movel d7,a4
+ movel a0,d7
+ movel a4,a0
+ movel d6,a4
+ movel a3,d6
+ movel a4,a3
+#endif
subl d7,d3 |
subxl d6,d2 |
subxl d5,d1 |
subxl d4,d0 |
beq Ladddf$ret$1 | if zero just exit
bpl 1f | if positive skip the following
- exg d7,a0 |
+ movel a0,d7 |
bchg IMM (31),d7 | change sign bit in d7
- exg d7,a0 |
+ movel d7,a0 |
negl d3 |
negxl d2 |
negxl d1 | and negate result
@@ -793,7 +1086,13 @@ Lsubdf$0:
movel a2,d4 | return exponent to d4
movel a0,d7
andl IMM (0x80000000),d7 | isolate sign bit
+#ifndef __mcf5200__
moveml sp@+,a2-a3 |
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
| the case of denormalized numbers in the rounding routine itself).
@@ -801,26 +1100,58 @@ Lsubdf$0:
| one more bit we check this:
btst IMM (DBL_MANT_DIG+1),d0
beq 1f
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
roxrl IMM (1),d2
roxrl IMM (1),d3
addw IMM (1),d4
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
1:
lea Lsubdf$1,a0 | to return from rounding routine
lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
movew a1@(6),d6 | rounding mode in d6
beq Lround$to$nearest
+#ifndef __mcf5200__
cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
bhi Lround$to$minus
blt Lround$to$zero
bra Lround$to$plus
Lsubdf$1:
| Put back the exponent and sign (we don't have overflow). '
bclr IMM (DBL_MANT_DIG-1),d0
+#ifndef __mcf5200__
lslw IMM (4),d4 | put exponent back into position
+#else
+ lsll IMM (4),d4 | put exponent back into position
+#endif
swap d0 |
+#ifndef __mcf5200__
orw d4,d0 |
+#else
+ orl d4,d0 |
+#endif
swap d0 |
bra Ladddf$ret
@@ -828,22 +1159,46 @@ Lsubdf$1:
| DBL_MANT_DIG+1) we return the other (and now we don't have to '
| check for finiteness or zero).
Ladddf$a$small:
+#ifndef __mcf5200__
moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
movel a6@(16),d0
movel a6@(20),d1
lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 | and return
rts
Ladddf$b$small:
+#ifndef __mcf5200__
moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
movel a6@(8),d0
movel a6@(12),d1
lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 | and return
rts
@@ -883,21 +1238,41 @@ Ladddf$a:
bra Ld$infty |
Ladddf$ret$1:
+#ifndef __mcf5200__
moveml sp@+,a2-a3 | restore regs and exit
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
Ladddf$ret:
| Normal exit.
lea SYM (_fpCCR),a0
movew IMM (0),a0@
orl d7,d0 | put sign bit back
+#ifndef __mcf5200__
moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
Ladddf$ret$den:
| Return a denormalized number.
+#ifndef __mcf5200__
lsrl IMM (1),d0 | shift right once more
roxrl IMM (1),d1 |
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+#endif
bra Ladddf$ret
Ladddf$nf:
@@ -954,8 +1329,13 @@ Ladddf$nf:
| double __muldf3(double, double);
SYM (__muldf3):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movel a6@(8),d0 | get a into d0-d1
movel a6@(12),d1 |
movel a6@(16),d2 | and b into d2-d3
@@ -990,17 +1370,30 @@ SYM (__muldf3):
andl d6,d0 | isolate fraction
orl IMM (0x00100000),d0 | and put hidden bit back
swap d4 | I like exponents in the first byte
+#ifndef __mcf5200__
lsrw IMM (4),d4 |
+#else
+ lsrl IMM (4),d4 |
+#endif
Lmuldf$1:
andl d7,d5 |
beq Lmuldf$b$den |
andl d6,d2 |
orl IMM (0x00100000),d2 | and put hidden bit back
swap d5 |
+#ifndef __mcf5200__
lsrw IMM (4),d5 |
+#else
+ lsrl IMM (4),d5 |
+#endif
Lmuldf$2: |
+#ifndef __mcf5200__
addw d5,d4 | add exponents
subw IMM (D_BIAS+1),d4 | and subtract bias (plus one)
+#else
+ addl d5,d4 | add exponents
+ subl IMM (D_BIAS+1),d4 | and subtract bias (plus one)
+#endif
| We are now ready to do the multiplication. The situation is as follows:
| both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were
@@ -1012,11 +1405,18 @@ Lmuldf$2: |
| enough to keep everything in them. So we use the address registers to keep
| some intermediate data.
+#ifndef __mcf5200__
moveml a2-a3,sp@- | save a2 and a3 for temporary use
+#else
+ movel a2,sp@-
+ movel a3,sp@-
+ movel a4,sp@-
+#endif
movel IMM (0),a2 | a2 is a null register
movel d4,a3 | and a3 will preserve the exponent
| First, shift d2-d3 so bit 20 becomes bit 31:
+#ifndef __mcf5200__
rorl IMM (5),d2 | rotate d2 5 places right
swap d2 | and swap it
rorl IMM (5),d3 | do the same thing with d3
@@ -1025,6 +1425,16 @@ Lmuldf$2: |
andw IMM (0x07ff),d6 |
orw d6,d2 | and put them into d2
andw IMM (0xf800),d3 | clear those bits in d3
+#else
+ moveq IMM (11),d7 | left shift d2 11 bits
+ lsll d7,d2
+ movel d3,d6 | get a copy of d3
+ lsll d7,d3 | left shift d3 11 bits
+ andl IMM (0xffe00000),d6 | get the top 11 bits of d3
+ moveq IMM (21),d7 | right shift them 21 bits
+ lsrl d7,d6
+ orl d6,d2 | stick them at the end of d2
+#endif
movel d2,d6 | move b into d6-d7
movel d3,d7 | move a into d4-d5
@@ -1037,9 +1447,22 @@ Lmuldf$2: |
| We use a1 as counter:
movel IMM (DBL_MANT_DIG-1),a1
+#ifndef __mcf5200__
exg d7,a1
+#else
+ movel d7,a4
+ movel a1,d7
+ movel a4,a1
+#endif
-1: exg d7,a1 | put counter back in a1
+1:
+#ifndef __mcf5200__
+ exg d7,a1 | put counter back in a1
+#else
+ movel d7,a4
+ movel a1,d7
+ movel a4,a1
+#endif
addl d3,d3 | shift sum once left
addxl d2,d2 |
addxl d1,d1 |
@@ -1047,17 +1470,44 @@ Lmuldf$2: |
addl d7,d7 |
addxl d6,d6 |
bcc 2f | if bit clear skip the following
+#ifndef __mcf5200__
exg d7,a2 |
+#else
+ movel d7,a4
+ movel a2,d7
+ movel a4,a2
+#endif
addl d5,d3 | else add a to the sum
addxl d4,d2 |
addxl d7,d1 |
addxl d7,d0 |
+#ifndef __mcf5200__
exg d7,a2 |
-2: exg d7,a1 | put counter in d7
+#else
+ movel d7,a4
+ movel a2,d7
+ movel a4,a2
+#endif
+2:
+#ifndef __mcf5200__
+ exg d7,a1 | put counter in d7
dbf d7,1b | decrement and branch
+#else
+ movel d7,a4
+ movel a1,d7
+ movel a4,a1
+ subql IMM (1),d7
+ bpl 1b
+#endif
movel a3,d4 | restore exponent
+#ifndef __mcf5200__
moveml sp@+,a2-a3
+#else
+ movel sp@+,a4
+ movel sp@+,a3
+ movel sp@+,a2
+#endif
| Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The
| first thing to do now is to normalize it so bit 8 becomes bit
@@ -1070,6 +1520,7 @@ Lmuldf$2: |
swap d3
movew d3,d2
movew IMM (0),d3
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
roxrl IMM (1),d2
@@ -1082,6 +1533,22 @@ Lmuldf$2: |
roxrl IMM (1),d1
roxrl IMM (1),d2
roxrl IMM (1),d3
+#else
+ moveq IMM (29),d6
+ lsrl IMM (3),d3
+ movel d2,d7
+ lsll d6,d7
+ orl d7,d3
+ lsrl IMM (3),d2
+ movel d1,d7
+ lsll d6,d7
+ orl d7,d2
+ lsrl IMM (3),d1
+ movel d0,d7
+ lsll d6,d7
+ orl d7,d1
+ lsrl IMM (3),d0
+#endif
| Now round, check for over- and underflow, and exit.
movel a0,d7 | get sign bit back into d7
@@ -1089,9 +1556,18 @@ Lmuldf$2: |
btst IMM (DBL_MANT_DIG+1-32),d0
beq Lround$exit
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
addw IMM (1),d4
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
bra Lround$exit
Lmuldf$inop:
@@ -1116,8 +1592,17 @@ Lmuldf$a$nf:
| NaN, in which case we return NaN.
Lmuldf$b$0:
movew IMM (MULTIPLY),d5
+#ifndef __mcf5200__
exg d2,d0 | put b (==0) into d0-d1
exg d3,d1 | and a (with sign bit cleared) into d2-d3
+#else
+ movel d2,d7
+ movel d0,d2
+ movel d7,d0
+ movel d3,d7
+ movel d1,d3
+ movel d7,d1
+#endif
bra 1f
Lmuldf$a$0:
movel a6@(16),d2 | put b into d2-d3 again
@@ -1127,7 +1612,13 @@ Lmuldf$a$0:
bge Ld$inop | in case NaN or +/-INFINITY return NaN
lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
@@ -1140,7 +1631,11 @@ Lmuldf$a$den:
andl d6,d0
1: addl d1,d1 | shift a left until bit 20 is set
addxl d0,d0 |
+#ifndef __mcf5200__
subw IMM (1),d4 | and adjust exponent
+#else
+ subl IMM (1),d4 | and adjust exponent
+#endif
btst IMM (20),d0 |
bne Lmuldf$1 |
bra 1b
@@ -1150,7 +1645,11 @@ Lmuldf$b$den:
andl d6,d2
1: addl d3,d3 | shift b left until bit 20 is set
addxl d2,d2 |
+#ifndef __mcf5200__
subw IMM (1),d5 | and adjust exponent
+#else
+ subql IMM (1),d5 | and adjust exponent
+#endif
btst IMM (20),d2 |
bne Lmuldf$2 |
bra 1b
@@ -1162,8 +1661,13 @@ Lmuldf$b$den:
| double __divdf3(double, double);
SYM (__divdf3):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movel a6@(8),d0 | get a into d0-d1
movel a6@(12),d1 |
movel a6@(16),d2 | and b into d2-d3
@@ -1202,17 +1706,30 @@ SYM (__divdf3):
andl d6,d0 | and isolate fraction
orl IMM (0x00100000),d0 | and put hidden bit back
swap d4 | I like exponents in the first byte
+#ifndef __mcf5200__
lsrw IMM (4),d4 |
+#else
+ lsrl IMM (4),d4 |
+#endif
Ldivdf$1: |
andl d7,d5 |
beq Ldivdf$b$den |
andl d6,d2 |
orl IMM (0x00100000),d2
swap d5 |
+#ifndef __mcf5200__
lsrw IMM (4),d5 |
+#else
+ lsrl IMM (4),d5 |
+#endif
Ldivdf$2: |
+#ifndef __mcf5200__
subw d5,d4 | subtract exponents
addw IMM (D_BIAS),d4 | and add bias
+#else
+ subl d5,d4 | subtract exponents
+ addl IMM (D_BIAS),d4 | and add bias
+#endif
| We are now ready to do the division. We have prepared things in such a way
| that the ratio of the fractions will be less than 2 but greater than 1/2.
@@ -1243,7 +1760,12 @@ Ldivdf$2: |
bset d5,d6 | set the corresponding bit in d6
3: addl d1,d1 | shift a by 1
addxl d0,d0 |
+#ifndef __mcf5200__
dbra d5,1b | and branch back
+#else
+ subql IMM (1), d5
+ bpl 1b
+#endif
bra 5f
4: cmpl d1,d3 | here d0==d2, so check d1 and d3
bhi 3b | if d1 > d2 skip the subtraction
@@ -1260,7 +1782,12 @@ Ldivdf$2: |
bset d5,d7 | set the corresponding bit in d7
3: addl d1,d1 | shift a by 1
addxl d0,d0 |
+#ifndef __mcf5200__
dbra d5,1b | and branch back
+#else
+ subql IMM (1), d5
+ bpl 1b
+#endif
bra 5f
4: cmpl d1,d3 | here d0==d2, so check d1 and d3
bhi 3b | if d1 > d2 skip the subtraction
@@ -1273,7 +1800,12 @@ Ldivdf$2: |
beq 3f | if d0==d2 check d1 and d3
2: addl d1,d1 | shift a by 1
addxl d0,d0 |
+#ifndef __mcf5200__
dbra d5,1b | and branch back
+#else
+ subql IMM (1), d5
+ bpl 1b
+#endif
movel IMM (0),d2 | here no sticky bit was found
movel d2,d3
bra 5f
@@ -1284,13 +1816,23 @@ Ldivdf$2: |
| to it; if you don't do this the algorithm loses in some cases). '
movel IMM (0),d2
movel d2,d3
+#ifndef __mcf5200__
subw IMM (DBL_MANT_DIG),d5
addw IMM (63),d5
cmpw IMM (31),d5
+#else
+ subl IMM (DBL_MANT_DIG),d5
+ addl IMM (63),d5
+ cmpl IMM (31),d5
+#endif
bhi 2f
1: bset d5,d3
bra 5f
+#ifndef __mcf5200__
subw IMM (32),d5
+#else
+ subl IMM (32),d5
+#endif
2: bset d5,d2
5:
| Finally we are finished! Move the longs in the address registers to
@@ -1305,11 +1847,28 @@ Ldivdf$2: |
| not set:
btst IMM (DBL_MANT_DIG-32+1),d0
beq 1f
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
roxrl IMM (1),d2
roxrl IMM (1),d3
addw IMM (1),d4
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
1:
| Now round, check for over- and underflow, and exit.
movel a0,d7 | restore sign bit to d7
@@ -1338,7 +1897,13 @@ Ldivdf$a$0:
movel d0,d1 |
lea SYM (_fpCCR),a0 | clear exception flags
movew IMM (0),a0@ |
+#ifndef __mcf5200__
moveml sp@+,d2-d7 |
+#else
+ moveml sp@,d2-d7 |
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 |
rts |
@@ -1380,7 +1945,11 @@ Ldivdf$a$den:
andl d6,d0
1: addl d1,d1 | shift a left until bit 20 is set
addxl d0,d0
+#ifndef __mcf5200__
subw IMM (1),d4 | and adjust exponent
+#else
+ subl IMM (1),d4 | and adjust exponent
+#endif
btst IMM (DBL_MANT_DIG-32-1),d0
bne Ldivdf$1
bra 1b
@@ -1390,7 +1959,11 @@ Ldivdf$b$den:
andl d6,d2
1: addl d3,d3 | shift b left until bit 20 is set
addxl d2,d2
+#ifndef __mcf5200__
subw IMM (1),d5 | and adjust exponent
+#else
+ subql IMM (1),d5 | and adjust exponent
+#endif
btst IMM (DBL_MANT_DIG-32-1),d2
bne Ldivdf$2
bra 1b
@@ -1401,7 +1974,11 @@ Lround$exit:
| so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4.
| First check for underlow in the exponent:
+#ifndef __mcf5200__
cmpw IMM (-DBL_MANT_DIG-1),d4
+#else
+ cmpl IMM (-DBL_MANT_DIG-1),d4
+#endif
blt Ld$underflow
| It could happen that the exponent is less than 1, in which case the
| number is denormalized. In this case we shift right and adjust the
@@ -1410,9 +1987,15 @@ Lround$exit:
movel d7,a0 |
movel IMM (0),d6 | use d6-d7 to collect bits flushed right
movel d6,d7 | use d6-d7 to collect bits flushed right
+#ifndef __mcf5200__
cmpw IMM (1),d4 | if the exponent is less than 1 we
+#else
+ cmpl IMM (1),d4 | if the exponent is less than 1 we
+#endif
bge 2f | have to shift right (denormalize)
-1: addw IMM (1),d4 | adjust the exponent
+1:
+#ifndef __mcf5200__
+ addw IMM (1),d4 | adjust the exponent
lsrl IMM (1),d0 | shift right once
roxrl IMM (1),d1 |
roxrl IMM (1),d2 |
@@ -1420,6 +2003,31 @@ Lround$exit:
roxrl IMM (1),d6 |
roxrl IMM (1),d7 |
cmpw IMM (1),d4 | is the exponent 1 already?
+#else
+ addl IMM (1),d4 | adjust the exponent
+ lsrl IMM (1),d7
+ btst IMM (0),d6
+ beq 13f
+ bset IMM (31),d7
+13: lsrl IMM (1),d6
+ btst IMM (0),d3
+ beq 14f
+ bset IMM (31),d6
+14: lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d2
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 12f
+ bset IMM (31),d1
+12: lsrl IMM (1),d0
+ cmpl IMM (1),d4 | is the exponent 1 already?
+#endif
beq 2f | if not loop back
bra 1b |
bra Ld$underflow | safety check, shouldn't execute '
@@ -1429,9 +2037,16 @@ Lround$exit:
| Now call the rounding routine (which takes care of denormalized numbers):
lea Lround$0,a0 | to return from rounding routine
lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
movew a1@(6),d6 | rounding mode in d6
beq Lround$to$nearest
+#ifndef __mcf5200__
cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
bhi Lround$to$minus
blt Lround$to$zero
bra Lround$to$plus
@@ -1443,23 +2058,41 @@ Lround$0:
| check again for underflow!). We have to check for overflow or for a
| denormalized number (which also signals underflow).
| Check for overflow (i.e., exponent >= 0x7ff).
+#ifndef __mcf5200__
cmpw IMM (0x07ff),d4
+#else
+ cmpl IMM (0x07ff),d4
+#endif
bge Ld$overflow
| Now check for a denormalized number (exponent==0):
movew d4,d4
beq Ld$den
1:
| Put back the exponents and sign and return.
+#ifndef __mcf5200__
lslw IMM (4),d4 | exponent back to fourth byte
+#else
+ lsll IMM (4),d4 | exponent back to fourth byte
+#endif
bclr IMM (DBL_MANT_DIG-32-1),d0
swap d0 | and put back exponent
+#ifndef __mcf5200__
orw d4,d0 |
+#else
+ orl d4,d0 |
+#endif
swap d0 |
orl d7,d0 | and sign also
lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
@@ -1469,8 +2102,13 @@ Lround$0:
| double __negdf2(double, double);
SYM (__negdf2):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movew IMM (NEGATE),d5
movel a6@(8),d0 | get number to negate in d0-d1
movel a6@(12),d1 |
@@ -1490,7 +2128,13 @@ SYM (__negdf2):
bra Ld$infty
1: lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
2: bclr IMM (31),d0
@@ -1506,8 +2150,13 @@ EQUAL = 0
| int __cmpdf2(double, double);
SYM (__cmpdf2):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@- | save registers
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movew IMM (COMPARE),d5
movel a6@(8),d0 | get first operand
movel a6@(12),d1 |
@@ -1545,8 +2194,17 @@ Lcmpdf$1:
tstl d6
bpl 1f
| If both are negative exchange them
+#ifndef __mcf5200__
exg d0,d2
exg d1,d3
+#else
+ movel d0,d7
+ movel d2,d0
+ movel d7,d2
+ movel d1,d7
+ movel d3,d1
+ movel d7,d3
+#endif
1:
| Now that they are positive we just compare them as longs (does this also
| work for denormalized numbers?).
@@ -1559,17 +2217,35 @@ Lcmpdf$1:
bne Lcmpdf$a$gt$b | |b| < |a|
| If we got here a == b.
movel IMM (EQUAL),d0
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
Lcmpdf$a$gt$b:
movel IMM (GREATER),d0
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
Lcmpdf$b$gt$a:
movel IMM (LESS),d0
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
@@ -1611,13 +2287,22 @@ Lround$to$nearest:
| Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent
| is one (remember that a denormalized number corresponds to an
| exponent of -D_BIAS+1).
+#ifndef __mcf5200__
cmpw IMM (1),d4 | remember that the exponent is at least one
+#else
+ cmpl IMM (1),d4 | remember that the exponent is at least one
+#endif
beq 2f | an exponent of one means denormalized
addl d3,d3 | else shift and adjust the exponent
addxl d2,d2 |
addxl d1,d1 |
addxl d0,d0 |
+#ifndef __mcf5200__
dbra d4,1b |
+#else
+ subql IMM (1), d4
+ bpl 1b
+#endif
2:
| Now round: we do it as follows: after the shifting we can write the
| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
@@ -1639,16 +2324,34 @@ Lround$to$nearest:
addl d3,d1 |
addxl d2,d0
| Shift right once (because we used bit #DBL_MANT_DIG-32!).
-2: lsrl IMM (1),d0
+2:
+#ifndef __mcf5200__
+ lsrl IMM (1),d0
roxrl IMM (1),d1
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+#endif
| Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a
| 'fraction overflow' ...).
btst IMM (DBL_MANT_DIG-32),d0
beq 1f
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
addw IMM (1),d4
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ addl IMM (1),d4
+#endif
1:
| If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we
| have to put the exponent to zero and return a denormalized number.
@@ -1719,9 +2422,8 @@ ROUND_TO_MINUS = 3 | round result towards minus infinity
Lf$den:
| Return and signal a denormalized number
orl d7,d0
- movew IMM (UNDERFLOW),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (SINGLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (SINGLE_FLOAT),d6
jmp $_exception_handler
Lf$infty:
@@ -1729,34 +2431,30 @@ Lf$overflow:
| Return a properly signed INFINITY and set the exception flags
movel IMM (INFINITY),d0
orl d7,d0
- movew IMM (OVERFLOW),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (SINGLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+OVERFLOW),d7
+ moveq IMM (SINGLE_FLOAT),d6
jmp $_exception_handler
Lf$underflow:
| Return 0 and set the exception flags
movel IMM (0),d0
- movew IMM (UNDERFLOW),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (SINGLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+UNDERFLOW),d7
+ moveq IMM (SINGLE_FLOAT),d6
jmp $_exception_handler
Lf$inop:
| Return a quiet NaN and set the exception flags
movel IMM (QUIET_NaN),d0
- movew IMM (INVALID_OPERATION),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (SINGLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7
+ moveq IMM (SINGLE_FLOAT),d6
jmp $_exception_handler
Lf$div$0:
| Return a properly signed INFINITY and set the exception flags
movel IMM (INFINITY),d0
orl d7,d0
- movew IMM (DIVIDE_BY_ZERO),d7
- orw IMM (INEXACT_RESULT),d7
- movew IMM (SINGLE_FLOAT),d6
+ movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
+ moveq IMM (SINGLE_FLOAT),d6
jmp $_exception_handler
|=============================================================================
@@ -1793,8 +2491,13 @@ SYM (__subsf3):
| float __addsf3(float, float);
SYM (__addsf3):
+#ifndef __mcf5200__
link a6,IMM (0) | everything will be done in registers
moveml d2-d7,sp@- | save all data registers but d0-d1
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movel a6@(8),d0 | get first operand
movel a6@(12),d1 | get second operand
movel d0,d6 | get d0's sign bit '
@@ -1848,54 +2551,126 @@ Laddsf$2:
| same, and put the largest exponent in d6. Note that we are using two
| registers for each number (see the discussion by D. Knuth in "Seminumerical
| Algorithms").
+#ifndef __mcf5200__
cmpw d6,d7 | compare exponents
+#else
+ cmpl d6,d7 | compare exponents
+#endif
beq Laddsf$3 | if equal don't shift '
bhi 5f | branch if second exponent largest
1:
subl d6,d7 | keep the largest exponent
negl d7
+#ifndef __mcf5200__
lsrw IMM (8),d7 | put difference in lower byte
+#else
+ lsrl IMM (8),d7 | put difference in lower byte
+#endif
| if difference is too large we don't shift (actually, we can just exit) '
+#ifndef __mcf5200__
cmpw IMM (FLT_MANT_DIG+2),d7
+#else
+ cmpl IMM (FLT_MANT_DIG+2),d7
+#endif
bge Laddsf$b$small
+#ifndef __mcf5200__
cmpw IMM (16),d7 | if difference >= 16 swap
+#else
+ cmpl IMM (16),d7 | if difference >= 16 swap
+#endif
bge 4f
2:
+#ifndef __mcf5200__
subw IMM (1),d7
-3: lsrl IMM (1),d2 | shift right second operand
+#else
+ subql IMM (1), d7
+#endif
+3:
+#ifndef __mcf5200__
+ lsrl IMM (1),d2 | shift right second operand
roxrl IMM (1),d3
dbra d7,3b
+#else
+ lsrl IMM (1),d3
+ btst IMM (0),d2
+ beq 10f
+ bset IMM (31),d3
+10: lsrl IMM (1),d2
+ subql IMM (1), d7
+ bpl 3b
+#endif
bra Laddsf$3
4:
movew d2,d3
swap d3
movew d3,d2
swap d2
+#ifndef __mcf5200__
subw IMM (16),d7
+#else
+ subl IMM (16),d7
+#endif
bne 2b | if still more bits, go back to normal case
bra Laddsf$3
5:
+#ifndef __mcf5200__
exg d6,d7 | exchange the exponents
+#else
+ eorl d6,d7
+ eorl d7,d6
+ eorl d6,d7
+#endif
subl d6,d7 | keep the largest exponent
negl d7 |
+#ifndef __mcf5200__
lsrw IMM (8),d7 | put difference in lower byte
+#else
+ lsrl IMM (8),d7 | put difference in lower byte
+#endif
| if difference is too large we don't shift (and exit!) '
+#ifndef __mcf5200__
cmpw IMM (FLT_MANT_DIG+2),d7
+#else
+ cmpl IMM (FLT_MANT_DIG+2),d7
+#endif
bge Laddsf$a$small
+#ifndef __mcf5200__
cmpw IMM (16),d7 | if difference >= 16 swap
+#else
+ cmpl IMM (16),d7 | if difference >= 16 swap
+#endif
bge 8f
6:
+#ifndef __mcf5200__
subw IMM (1),d7
-7: lsrl IMM (1),d0 | shift right first operand
+#else
+ subl IMM (1),d7
+#endif
+7:
+#ifndef __mcf5200__
+ lsrl IMM (1),d0 | shift right first operand
roxrl IMM (1),d1
dbra d7,7b
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ subql IMM (1),d7
+ bpl 7b
+#endif
bra Laddsf$3
8:
movew d0,d1
swap d1
movew d1,d0
swap d0
+#ifndef __mcf5200__
subw IMM (16),d7
+#else
+ subl IMM (16),d7
+#endif
bne 6b | if still more bits, go back to normal case
| otherwise we fall through
@@ -1904,15 +2679,30 @@ Laddsf$2:
Laddsf$3:
| Here we have to decide whether to add or subtract the numbers
+#ifndef __mcf5200__
exg d6,a0 | get signs back
exg d7,a1 | and save the exponents
+#else
+ movel d6,d4
+ movel a0,d6
+ movel d4,d6
+ movel d7,d4
+ movel a1,d4
+ movel d4,a1
+#endif
eorl d6,d7 | combine sign bits
bmi Lsubsf$0 | if negative a and b have opposite
| sign so we actually subtract the
| numbers
| Here we have both positive or both negative
+#ifndef __mcf5200__
exg d6,a0 | now we have the exponent in d6
+#else
+ movel d6,d4
+ movel a0,d6
+ movel d4,a0
+#endif
movel a0,d7 | and sign in d7
andl IMM (0x80000000),d7
| Here we do the addition.
@@ -1923,7 +2713,11 @@ Laddsf$3:
| Put the exponent, in the first byte, in d2, to use the "standard" rounding
| routines:
movel d6,d2
+#ifndef __mcf5200__
lsrw IMM (8),d2
+#else
+ lsrl IMM (8),d2
+#endif
| Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider
| the case of denormalized numbers in the rounding routine itself).
@@ -1931,24 +2725,47 @@ Laddsf$3:
| one more bit we check this:
btst IMM (FLT_MANT_DIG+1),d0
beq 1f
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+#endif
addl IMM (1),d2
1:
lea Laddsf$4,a0 | to return from rounding routine
lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
movew a1@(6),d6 | rounding mode in d6
beq Lround$to$nearest
+#ifndef __mcf5200__
cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
bhi Lround$to$minus
blt Lround$to$zero
bra Lround$to$plus
Laddsf$4:
| Put back the exponent, but check for overflow.
+#ifndef __mcf5200__
cmpw IMM (0xff),d2
+#else
+ cmpl IMM (0xff),d2
+#endif
bhi 1f
bclr IMM (FLT_MANT_DIG-1),d0
+#ifndef __mcf5200__
lslw IMM (7),d2
+#else
+ lsll IMM (7),d2
+#endif
swap d2
orl d2,d0
bra Laddsf$ret
@@ -1970,8 +2787,15 @@ Lsubsf$0:
negl d1
negxl d0
1:
+#ifndef __mcf5200__
exg d2,a0 | now we have the exponent in d2
lsrw IMM (8),d2 | put it in the first byte
+#else
+ movel d2,d4
+ movel a0,d2
+ movel d4,a0
+ lsrl IMM (8),d2 | put it in the first byte
+#endif
| Now d0-d1 is positive and the sign bit is in d7.
@@ -1980,16 +2804,27 @@ Lsubsf$0:
| the rounding routines themselves.
lea Lsubsf$1,a0 | to return from rounding routine
lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
movew a1@(6),d6 | rounding mode in d6
beq Lround$to$nearest
+#ifndef __mcf5200__
cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
bhi Lround$to$minus
blt Lround$to$zero
bra Lround$to$plus
Lsubsf$1:
| Put back the exponent (we can't have overflow!). '
bclr IMM (FLT_MANT_DIG-1),d0
+#ifndef __mcf5200__
lslw IMM (7),d2
+#else
+ lsll IMM (7),d2
+#endif
swap d2
orl d2,d0
bra Laddsf$ret
@@ -2001,7 +2836,13 @@ Laddsf$a$small:
movel a6@(12),d0
lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 | and return
rts
@@ -2009,7 +2850,13 @@ Laddsf$b$small:
movel a6@(8),d0
lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 | and return
rts
@@ -2061,7 +2908,13 @@ Laddsf$ret:
lea SYM (_fpCCR),a0
movew IMM (0),a0@
orl d7,d0 | put sign bit
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | restore data registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 | and return
rts
@@ -2122,8 +2975,13 @@ Laddsf$nf:
| float __mulsf3(float, float);
SYM (__mulsf3):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movel a6@(8),d0 | get a into d0
movel a6@(12),d1 | and b into d1
movel d0,d7 | d7 will hold the sign of the product
@@ -2152,17 +3010,30 @@ SYM (__mulsf3):
andl d5,d0 | and isolate fraction
orl d4,d0 | and put hidden bit back
swap d2 | I like exponents in the first byte
+#ifndef __mcf5200__
lsrw IMM (7),d2 |
+#else
+ lsrl IMM (7),d2 |
+#endif
Lmulsf$1: | number
andl d6,d3 |
beq Lmulsf$b$den |
andl d5,d1 |
orl d4,d1 |
swap d3 |
+#ifndef __mcf5200__
lsrw IMM (7),d3 |
+#else
+ lsrl IMM (7),d3 |
+#endif
Lmulsf$2: |
+#ifndef __mcf5200__
addw d3,d2 | add exponents
subw IMM (F_BIAS+1),d2 | and subtract bias (plus one)
+#else
+ addl d3,d2 | add exponents
+ subl IMM (F_BIAS+1),d2 | and subtract bias (plus one)
+#endif
| We are now ready to do the multiplication. The situation is as follows:
| both a and b have bit FLT_MANT_DIG-1 set (even if they were
@@ -2188,28 +3059,58 @@ Lmulsf$2: |
bcc 2f | if not set skip sum
addl d5,d1 | add a
addxl d4,d0
-2: dbf d3,1b | loop back
+2:
+#ifndef __mcf5200__
+ dbf d3,1b | loop back
+#else
+ subql IMM (1),d3
+ bpl 1b
+#endif
| Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG
| (mod 32) of d0 set. The first thing to do now is to normalize it so bit
| FLT_MANT_DIG is set (to do the rounding).
+#ifndef __mcf5200__
rorl IMM (6),d1
swap d1
movew d1,d3
andw IMM (0x03ff),d3
andw IMM (0xfd00),d1
+#else
+ movel d1,d3
+ lsll IMM (8),d1
+ addl d1,d1
+ addl d1,d1
+ moveq IMM (22),d5
+ lsrl d5,d3
+ orl d3,d1
+ andl IMM (0xfffffd00),d1
+#endif
lsll IMM (8),d0
addl d0,d0
addl d0,d0
+#ifndef __mcf5200__
orw d3,d0
+#else
+ orl d3,d0
+#endif
movew IMM (MULTIPLY),d5
btst IMM (FLT_MANT_DIG+1),d0
beq Lround$exit
+#ifndef __mcf5200__
lsrl IMM (1),d0
roxrl IMM (1),d1
addw IMM (1),d2
+#else
+ lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ addql IMM (1),d2
+#endif
bra Lround$exit
Lmulsf$inop:
@@ -2242,7 +3143,13 @@ Lmulsf$a$0:
bge Lf$inop | if b is +/-INFINITY or NaN return NaN
lea SYM (_fpCCR),a0 | else return zero
movew IMM (0),a0@ |
+#ifndef __mcf5200__
moveml sp@+,d2-d7 |
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 |
rts |
@@ -2254,7 +3161,11 @@ Lmulsf$a$den:
movel IMM (1),d2
andl d5,d0
1: addl d0,d0 | shift a left (until bit 23 is set)
+#ifndef __mcf5200__
subw IMM (1),d2 | and adjust exponent
+#else
+ subql IMM (1),d2 | and adjust exponent
+#endif
btst IMM (FLT_MANT_DIG-1),d0
bne Lmulsf$1 |
bra 1b | else loop back
@@ -2263,7 +3174,11 @@ Lmulsf$b$den:
movel IMM (1),d3
andl d5,d1
1: addl d1,d1 | shift b left until bit 23 is set
+#ifndef __mcf5200__
subw IMM (1),d3 | and adjust exponent
+#else
+ subl IMM (1),d3 | and adjust exponent
+#endif
btst IMM (FLT_MANT_DIG-1),d1
bne Lmulsf$2 |
bra 1b | else loop back
@@ -2274,8 +3189,13 @@ Lmulsf$b$den:
| float __divsf3(float, float);
SYM (__divsf3):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movel a6@(8),d0 | get a into d0
movel a6@(12),d1 | and b into d1
movel d0,d7 | d7 will hold the sign of the result
@@ -2306,17 +3226,30 @@ SYM (__divsf3):
andl d5,d0 | and isolate fraction
orl d4,d0 | and put hidden bit back
swap d2 | I like exponents in the first byte
+#ifndef __mcf5200__
lsrw IMM (7),d2 |
+#else
+ lsrl IMM (7),d2 |
+#endif
Ldivsf$1: |
andl d6,d3 |
beq Ldivsf$b$den |
andl d5,d1 |
orl d4,d1 |
swap d3 |
+#ifndef __mcf5200__
lsrw IMM (7),d3 |
+#else
+ lsrl IMM (7),d3 |
+#endif
Ldivsf$2: |
+#ifndef __mcf5200__
subw d3,d2 | subtract exponents
addw IMM (F_BIAS),d2 | and add bias
+#else
+ subl d3,d2 | subtract exponents
+ addl IMM (F_BIAS),d2 | and add bias
+#endif
| We are now ready to do the division. We have prepared things in such a way
| that the ratio of the fractions will be less than 2 but greater than 1/2.
@@ -2337,19 +3270,34 @@ Ldivsf$2: |
subl d1,d0 | if a >= b a <-- a-b
beq 3f | if a is zero, exit
2: addl d0,d0 | multiply a by 2
+#ifndef __mcf5200__
dbra d3,1b
+#else
+ subql IMM (1),d3
+ bpl 1b
+#endif
| Now we keep going to set the sticky bit ...
movew IMM (FLT_MANT_DIG),d3
1: cmpl d0,d1
ble 2f
addl d0,d0
+#ifndef __mcf5200__
dbra d3,1b
+#else
+ subql IMM(1),d3
+ bpl 1b
+#endif
movel IMM (0),d1
bra 3f
2: movel IMM (0),d1
+#ifndef __mcf5200__
subw IMM (FLT_MANT_DIG),d3
addw IMM (31),d3
+#else
+ subl IMM (FLT_MANT_DIG),d3
+ addl IMM (31),d3
+#endif
bset d3,d1
3:
movel d6,d0 | put the ratio in d0-d1
@@ -2361,7 +3309,11 @@ Ldivsf$2: |
btst IMM (FLT_MANT_DIG+1),d0
beq 1f | if it is not set, then bit 24 is set
lsrl IMM (1),d0 |
+#ifndef __mcf5200__
addw IMM (1),d2 |
+#else
+ addl IMM (1),d2 |
+#endif
1:
| Now round, check for over- and underflow, and exit.
movew IMM (DIVIDE),d5
@@ -2391,7 +3343,13 @@ Ldivsf$a$0:
movel IMM (0),d0 | else return zero
lea SYM (_fpCCR),a0 |
movew IMM (0),a0@ |
+#ifndef __mcf5200__
moveml sp@+,d2-d7 |
+#else
+ moveml sp@,d2-d7 |
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6 |
rts |
@@ -2417,7 +3375,11 @@ Ldivsf$a$den:
movel IMM (1),d2
andl d5,d0
1: addl d0,d0 | shift a left until bit FLT_MANT_DIG-1 is set
+#ifndef __mcf5200__
subw IMM (1),d2 | and adjust exponent
+#else
+ subl IMM (1),d2 | and adjust exponent
+#endif
btst IMM (FLT_MANT_DIG-1),d0
bne Ldivsf$1
bra 1b
@@ -2426,7 +3388,11 @@ Ldivsf$b$den:
movel IMM (1),d3
andl d5,d1
1: addl d1,d1 | shift b left until bit FLT_MANT_DIG is set
+#ifndef __mcf5200__
subw IMM (1),d3 | and adjust exponent
+#else
+ subl IMM (1),d3 | and adjust exponent
+#endif
btst IMM (FLT_MANT_DIG-1),d1
bne Ldivsf$2
bra 1b
@@ -2435,20 +3401,43 @@ Lround$exit:
| This is a common exit point for __mulsf3 and __divsf3.
| First check for underlow in the exponent:
+#ifndef __mcf5200__
cmpw IMM (-FLT_MANT_DIG-1),d2
+#else
+ cmpl IMM (-FLT_MANT_DIG-1),d2
+#endif
blt Lf$underflow
| It could happen that the exponent is less than 1, in which case the
| number is denormalized. In this case we shift right and adjust the
| exponent until it becomes 1 or the fraction is zero (in the latter case
| we signal underflow and return zero).
movel IMM (0),d6 | d6 is used temporarily
+#ifndef __mcf5200__
cmpw IMM (1),d2 | if the exponent is less than 1 we
+#else
+ cmpl IMM (1),d2 | if the exponent is less than 1 we
+#endif
bge 2f | have to shift right (denormalize)
-1: addw IMM (1),d2 | adjust the exponent
+1:
+#ifndef __mcf5200__
+ addw IMM (1),d2 | adjust the exponent
lsrl IMM (1),d0 | shift right once
roxrl IMM (1),d1 |
roxrl IMM (1),d6 | d6 collect bits we would lose otherwise
cmpw IMM (1),d2 | is the exponent 1 already?
+#else
+ addql IMM (1),d2 | adjust the exponent
+ lsrl IMM (1),d6
+ btst IMM (0),d1
+ beq 11f
+ bset IMM (31),d6
+11: lsrl IMM (1),d1
+ btst IMM (0),d0
+ beq 10f
+ bset IMM (31),d1
+10: lsrl IMM (1),d0
+ cmpl IMM (1),d2 | is the exponent 1 already?
+#endif
beq 2f | if not loop back
bra 1b |
bra Lf$underflow | safety check, shouldn't execute '
@@ -2457,9 +3446,16 @@ Lround$exit:
| Now call the rounding routine (which takes care of denormalized numbers):
lea Lround$0,a0 | to return from rounding routine
lea SYM (_fpCCR),a1 | check the rounding mode
+#ifdef __mcf5200__
+ clrl d6
+#endif
movew a1@(6),d6 | rounding mode in d6
beq Lround$to$nearest
+#ifndef __mcf5200__
cmpw IMM (ROUND_TO_PLUS),d6
+#else
+ cmpl IMM (ROUND_TO_PLUS),d6
+#endif
bhi Lround$to$minus
blt Lround$to$zero
bra Lround$to$plus
@@ -2471,23 +3467,41 @@ Lround$0:
| check again for underflow!). We have to check for overflow or for a
| denormalized number (which also signals underflow).
| Check for overflow (i.e., exponent >= 255).
+#ifndef __mcf5200__
cmpw IMM (0x00ff),d2
+#else
+ cmpl IMM (0x00ff),d2
+#endif
bge Lf$overflow
| Now check for a denormalized number (exponent==0).
movew d2,d2
beq Lf$den
1:
| Put back the exponents and sign and return.
+#ifndef __mcf5200__
lslw IMM (7),d2 | exponent back to fourth byte
+#else
+ lsll IMM (7),d2 | exponent back to fourth byte
+#endif
bclr IMM (FLT_MANT_DIG-1),d0
swap d0 | and put back exponent
+#ifndef __mcf5200__
orw d2,d0 |
+#else
+ orl d2,d0
+#endif
swap d0 |
orl d7,d0 | and sign also
lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
@@ -2500,8 +3514,13 @@ Lround$0:
| float __negsf2(float);
SYM (__negsf2):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@-
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movew IMM (NEGATE),d5
movel a6@(8),d0 | get number to negate in d0
bchg IMM (31),d0 | negate
@@ -2517,7 +3536,13 @@ SYM (__negsf2):
bra Lf$infty
1: lea SYM (_fpCCR),a0
movew IMM (0),a0@
+#ifndef __mcf5200__
moveml sp@+,d2-d7
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
2: bclr IMM (31),d0
@@ -2533,8 +3558,13 @@ EQUAL = 0
| int __cmpsf2(float, float);
SYM (__cmpsf2):
+#ifndef __mcf5200__
link a6,IMM (0)
moveml d2-d7,sp@- | save registers
+#else
+ link a6,IMM (-24)
+ moveml d2-d7,sp@
+#endif
movew IMM (COMPARE),d5
movel a6@(8),d0 | get first operand
movel a6@(12),d1 | get second operand
@@ -2565,7 +3595,13 @@ Lcmpsf$2:
tstl d6
bpl 1f
| If both are negative exchange them
+#ifndef __mcf5200__
exg d0,d1
+#else
+ movel d0,d7
+ movel d1,d0
+ movel d7,d1
+#endif
1:
| Now that they are positive we just compare them as longs (does this also
| work for denormalized numbers?).
@@ -2574,17 +3610,33 @@ Lcmpsf$2:
bne Lcmpsf$a$gt$b | |b| < |a|
| If we got here a == b.
movel IMM (EQUAL),d0
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+#endif
unlk a6
rts
Lcmpsf$a$gt$b:
movel IMM (GREATER),d0
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
Lcmpsf$b$gt$a:
movel IMM (LESS),d0
+#ifndef __mcf5200__
moveml sp@+,d2-d7 | put back the registers
+#else
+ moveml sp@,d2-d7
+ | XXX if frame pointer is ever removed, stack pointer must
+ | be adjusted here.
+#endif
unlk a6
rts
@@ -2616,11 +3668,20 @@ Lround$to$nearest:
| Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent
| is one (remember that a denormalized number corresponds to an
| exponent of -F_BIAS+1).
+#ifndef __mcf5200__
cmpw IMM (1),d2 | remember that the exponent is at least one
+#else
+ cmpl IMM (1),d2 | remember that the exponent is at least one
+#endif
beq 2f | an exponent of one means denormalized
addl d1,d1 | else shift and adjust the exponent
addxl d0,d0 |
+#ifndef __mcf5200__
dbra d2,1b |
+#else
+ subql IMM (1),d2
+ bpl 1b
+#endif
2:
| Now round: we do it as follows: after the shifting we can write the
| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
@@ -2644,7 +3705,11 @@ Lround$to$nearest:
btst IMM (FLT_MANT_DIG),d0
beq 1f
lsrl IMM (1),d0
+#ifndef __mcf5200__
addw IMM (1),d2
+#else
+ addql IMM (1),d2
+#endif
1:
| If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we
| have to put the exponent to zero and return a denormalized number.
@@ -2668,162 +3733,92 @@ Lround$to$minus:
| easier to write efficient versions of these routines someday.
#ifdef L_eqdf2
-LL0:
.text
.proc
-|#PROC# 04
- LF18 = 4
- LS18 = 128
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__eqdf2)
SYM (__eqdf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(20),sp@-
movl a6@(16),sp@-
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpdf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_eqdf2 */
#ifdef L_nedf2
-LL0:
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__nedf2)
SYM (__nedf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(20),sp@-
movl a6@(16),sp@-
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpdf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_nedf2 */
#ifdef L_gtdf2
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__gtdf2)
SYM (__gtdf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(20),sp@-
movl a6@(16),sp@-
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpdf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_gtdf2 */
#ifdef L_gedf2
-LL0:
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__gedf2)
SYM (__gedf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(20),sp@-
movl a6@(16),sp@-
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpdf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_gedf2 */
#ifdef L_ltdf2
-LL0:
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__ltdf2)
SYM (__ltdf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(20),sp@-
movl a6@(16),sp@-
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpdf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_ltdf2 */
#ifdef L_ledf2
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__ledf2)
SYM (__ledf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(20),sp@-
movl a6@(16),sp@-
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpdf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_ledf2 */
@@ -2833,144 +3828,77 @@ SYM (__ledf2):
#ifdef L_eqsf2
.text
.proc
-|#PROC# 04
- LF18 = 4
- LS18 = 128
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__eqsf2)
SYM (__eqsf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpsf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_eqsf2 */
#ifdef L_nesf2
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__nesf2)
SYM (__nesf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpsf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_nesf2 */
#ifdef L_gtsf2
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__gtsf2)
SYM (__gtsf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpsf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_gtsf2 */
#ifdef L_gesf2
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__gesf2)
SYM (__gesf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpsf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_gesf2 */
#ifdef L_ltsf2
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__ltsf2)
SYM (__ltsf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpsf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_ltsf2 */
#ifdef L_lesf2
.text
.proc
-|#PROC# 04
- LF18 = 8
- LS18 = 132
- LFF18 = 0
- LSS18 = 0
- LV18 = 0
- .text
.globl SYM (__lesf2)
SYM (__lesf2):
-|#PROLOGUE# 0
link a6,IMM (0)
-|#PROLOGUE# 1
movl a6@(12),sp@-
movl a6@(8),sp@-
jbsr SYM (__cmpsf2)
-|#PROLOGUE# 2
unlk a6
-|#PROLOGUE# 3
rts
#endif /* L_lesf2 */
-
diff --git a/gnu/usr.bin/gcc/config/m68k/linux-aout.h b/gnu/usr.bin/gcc/config/m68k/linux-aout.h
index 980d08f72f9..692725edd4d 100644
--- a/gnu/usr.bin/gcc/config/m68k/linux-aout.h
+++ b/gnu/usr.bin/gcc/config/m68k/linux-aout.h
@@ -1,5 +1,5 @@
-/* Definitions for Motorola m68k running Linux
- Copyright (C) 1995 Free Software Foundation, Inc.
+/* Definitions for Motorola m68k running Linux-based GNU systems.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,15 +22,17 @@ Boston, MA 02111-1307, USA. */
#include <linux-aout.h>
/* 68020 with 68881 */
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#define DBX_DEBUGGING_INFO
+#define ASM_COMMENT_START "|"
+
#define CPP_PREDEFINES \
"-Dunix -Dmc68000 -Dmc68020 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(m68k) -Amachine(m68k)"
#undef CPP_SPEC
-#if TARGET_DEFAULT & 2
+#if TARGET_DEFAULT & MASK_68881
#define CPP_SPEC \
"%{!msoft-float:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE}"
#else
@@ -48,7 +50,7 @@ Boston, MA 02111-1307, USA. */
#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 Linux C library, please add -lc_p or -ggdb
+ 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}"
diff --git a/gnu/usr.bin/gcc/config/m68k/linux.h b/gnu/usr.bin/gcc/config/m68k/linux.h
index 589b361932e..9f2399da1e1 100644
--- a/gnu/usr.bin/gcc/config/m68k/linux.h
+++ b/gnu/usr.bin/gcc/config/m68k/linux.h
@@ -1,5 +1,6 @@
-/* Definitions for Motorola 68k running Linux with ELF format.
- Copyright (C) 1995 Free Software Foundation, Inc.
+/* Definitions for Motorola 68k running Linux-based GNU systems with
+ ELF format.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -26,10 +27,15 @@ Boston, MA 02111-1307, USA. */
#include <linux.h> /* some common stuff */
#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (68k Linux/ELF)");
+#define TARGET_VERSION fprintf (stderr, " (68k GNU/Linux with ELF)");
/* 68020 with 68881 */
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
+
+/* for 68k machines this only needs to be TRUE for the 68000 */
+
+#undef STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT 0
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES {"ieee-fp", 0},
@@ -57,6 +63,8 @@ Boston, MA 02111-1307, USA. */
#undef USER_LABEL_PREFIX
#define USER_LABEL_PREFIX ""
+#define ASM_COMMENT_START "|"
+
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number.
Motorola format uses different register names than defined in m68k.h. */
@@ -95,37 +103,36 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-#undef ASM_SPEC
-#define ASM_SPEC "%{m68030} %{m68040} %{fpic:-k} %{fPIC:-k}"
-
#define CPP_PREDEFINES \
"-D__ELF__ -Dunix -Dmc68000 -Dmc68020 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(m68k) -Amachine(m68k)"
#undef CPP_SPEC
-#if TARGET_DEFAULT & 2
+#ifdef USE_GNULIBC_1
+#if TARGET_DEFAULT & MASK_68881
#define CPP_SPEC \
"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!msoft-float:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE}"
#else
#define CPP_SPEC \
"%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m68881:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE}"
#endif
-
-#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 Linux C library, please add -lc_p or -ggdb
- to LDFLAGS at the link time, respectively. */
-#define LIB_SPEC \
- "%{!shared:%{!symbolic: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \
- %{!ggdb:-lc} %{ggdb:-lg}}}"
#else
-#define LIB_SPEC \
- "%{!shared:%{!symbolic: \
- %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \
- %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}}"
+#if TARGET_DEFAULT & MASK_68881
+#define CPP_SPEC \
+ "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!msoft-float:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
+#else
+#define CPP_SPEC \
+ "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m68881:-D__HAVE_68881__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#endif
+#endif
+
+/* We override the ASM_SPEC from svr4.h because we must pass -m68040 down
+ to the assembler. */
+#undef ASM_SPEC
+#define ASM_SPEC \
+ "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+%{m68040} %{m68060:-m68040}"
-/* Provide a LINK_SPEC appropriate for Linux. Here we provide support
+/* 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
@@ -142,6 +149,7 @@ Boston, MA 02111-1307, USA. */
/* 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 m68kelf %{shared} %{symbolic:-shared -Bsymbolic} \
%{!shared:%{!symbolic: \
@@ -157,6 +165,14 @@ Boston, MA 02111-1307, USA. */
%{!dynamic-linker*:-dynamic-linker /lib/ld-linux.so.1}} \
%{static}}}"
#endif
+#else
+#define LINK_SPEC "-m m68kelf %{shared} \
+ %{!shared: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker*:-dynamic-linker /lib/ld.so.1}} \
+ %{static}}"
+#endif
/* For compatibility with linux/a.out */
@@ -169,9 +185,13 @@ Boston, MA 02111-1307, USA. */
/* Use the default action for outputting the case label. */
#undef ASM_OUTPUT_CASE_LABEL
-
-#define ASM_RETURN_CASE_JUMP \
- return "jmp (2,%%pc,%0.w)"
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
/* This is how to output an assembler line that says to advance the
location counter to a multiple of 2**LOG bytes. */
@@ -181,6 +201,20 @@ Boston, MA 02111-1307, USA. */
if ((LOG) > 0) \
fprintf ((FILE), "\t%s \t%u\n", ALIGN_ASM_OP, 1 << (LOG));
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as uninitialized global
+ data. */
+
+#define BSS_SECTION_ASM_OP ".section\t.bss"
+
+/* 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)
+
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
@@ -259,7 +293,8 @@ do { \
#undef LIBCALL_VALUE
#define LIBCALL_VALUE(MODE) \
- (((MODE) == SFmode || (MODE) == DFmode) && TARGET_68881 \
+ ((((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode) \
+ && TARGET_68881) \
? gen_rtx (REG, (MODE), 16) \
: gen_rtx (REG, (MODE), 0))
@@ -267,7 +302,10 @@ do { \
an operand of a function call. */
#undef LEGITIMATE_PIC_OPERAND_P
#define LEGITIMATE_PIC_OPERAND_P(X) \
- (! symbolic_operand (X, VOIDmode) \
+ ((! symbolic_operand (X, VOIDmode) \
+ && ! (GET_CODE (X) == CONST_DOUBLE && CONST_DOUBLE_MEM (X) \
+ && GET_CODE (CONST_DOUBLE_MEM (X)) == MEM \
+ && symbolic_operand (XEXP (CONST_DOUBLE_MEM (X), 0), VOIDmode))) \
|| (GET_CODE (X) == SYMBOL_REF && SYMBOL_REF_FLAG (X)))
/* Turn off function cse if we are doing PIC. We always want function
@@ -283,3 +321,65 @@ do { \
technique. */
#undef PCC_STATIC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Finalize the trampoline by flushing the insn cache. */
+
+#undef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP) \
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__clear_cache"), \
+ 0, VOIDmode, 2, TRAMP, Pmode, \
+ plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode);
+
+/* Clear the instruction cache from `beg' to `end'. This makes an
+ inline system call to SYS_cacheflush. The arguments are as
+ follows:
+
+ cacheflush (addr, scope, cache, len)
+
+ addr - the start address for the flush
+ scope - the scope of the flush (see the cpush insn)
+ cache - which cache to flush (see the cpush insn)
+ len - a factor relating to the number of flushes to perform:
+ len/16 lines, or len/4096 pages. */
+
+#define CLEAR_INSN_CACHE(BEG, END) \
+{ \
+ register unsigned long _beg __asm ("%d1") = (unsigned long) (BEG); \
+ unsigned long _end = (unsigned long) (END); \
+ register unsigned long _len __asm ("%d4") = (_end - _beg + 32); \
+ __asm __volatile \
+ ("move%.l %#123, %/d0\n\t" /* system call nr */ \
+ "move%.l %#1, %/d2\n\t" /* clear lines */ \
+ "move%.l %#3, %/d3\n\t" /* insn+data caches */ \
+ "trap %#0" \
+ : /* no outputs */ \
+ : "d" (_beg), "d" (_len) \
+ : "%d0", "%d2", "%d3"); \
+}
+
+/* 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 { \
+ if (DELTA > 0 && DELTA <= 8) \
+ asm_fprintf (FILE, "\taddq.l %I%d,4(%Rsp)\n", DELTA); \
+ else if (DELTA < 0 && DELTA >= -8) \
+ asm_fprintf (FILE, "\tsubq.l %I%d,4(%Rsp)\n", -DELTA); \
+ else \
+ asm_fprintf (FILE, "\tadd.l %I%d,4(%Rsp)\n", DELTA); \
+ \
+ if (flag_pic) \
+ { \
+ fprintf (FILE, "\tbra.l "); \
+ assemble_name \
+ (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \
+ fprintf (FILE, "@PLTPC\n"); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\tjmp "); \
+ assemble_name \
+ (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \
+ fprintf (FILE, "\n"); \
+ } \
+} while (0)
diff --git a/gnu/usr.bin/gcc/config/m68k/lynx-ng.h b/gnu/usr.bin/gcc/config/m68k/lynx-ng.h
index 6921bcf79c7..ac3afac938e 100644
--- a/gnu/usr.bin/gcc/config/m68k/lynx-ng.h
+++ b/gnu/usr.bin/gcc/config/m68k/lynx-ng.h
@@ -1,5 +1,5 @@
/* Definitions for Motorola 680x0 running LynxOS, using Lynx's old as and ld.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -25,7 +25,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
/* Names to predefine in the preprocessor for this target machine. */
diff --git a/gnu/usr.bin/gcc/config/m68k/lynx.h b/gnu/usr.bin/gcc/config/m68k/lynx.h
index 0635ebba697..8c54b8bc13f 100644
--- a/gnu/usr.bin/gcc/config/m68k/lynx.h
+++ b/gnu/usr.bin/gcc/config/m68k/lynx.h
@@ -1,5 +1,5 @@
/* Definitions for Motorola 680x0 running 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.
@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
/* Names to predefine in the preprocessor for this target machine. */
diff --git a/gnu/usr.bin/gcc/config/m68k/m68k-aout.h b/gnu/usr.bin/gcc/config/m68k/m68k-aout.h
index 8f4487d7f60..b65f9fefcd1 100644
--- a/gnu/usr.bin/gcc/config/m68k/m68k-aout.h
+++ b/gnu/usr.bin/gcc/config/m68k/m68k-aout.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. "naked" 68020,
a.out object files and debugging, version.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -28,4 +28,17 @@ Boston, MA 02111-1307, USA. */
#define DBX_DEBUGGING_INFO
#undef SDB_DEBUGGING_INFO
-/* end of m68k-aout.h */
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as uninitialized global
+ data. */
+#define BSS_SECTION_ASM_OP "\t.bss"
+
+/* 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. The variable ROUNDED
+ is the size rounded up to whatever alignment the caller wants.
+ Try to use asm_output_bss to implement this macro. */
+/* a.out files typically can't handle arbitrary variable alignments so
+ define ASM_OUTPUT_BSS instead of ASM_OUTPUT_ALIGNED_BSS. */
+#define ASM_OUTPUT_BSS(FILE, DECL, NAME, SIZE, ROUNDED) \
+ asm_output_bss ((FILE), (DECL), (NAME), (SIZE), (ROUNDED))
diff --git a/gnu/usr.bin/gcc/config/m68k/m68k-none.h b/gnu/usr.bin/gcc/config/m68k/m68k-none.h
index 2f6761b4e8c..5ee2498ffff 100644
--- a/gnu/usr.bin/gcc/config/m68k/m68k-none.h
+++ b/gnu/usr.bin/gcc/config/m68k/m68k-none.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. "naked" 68020.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,76 +20,179 @@ Boston, MA 02111-1307, USA. */
#include "m68k/m68k.h"
-/* See m68k.h. 7 means 68020 with 68881. */
+/* Default to m68k (m68020). */
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT M68K_CPU_m68k
+#endif
+/* These are values set by the configure script in TARGET_CPU_DEFAULT.
+ They are ((desired value for TARGET_DEFAULT) << 4) + sequential integer.
+ See m68k.h for the values (it should really define MASK_FOO so we can
+ use them). */
+#define M68K_CPU_m68k ((7 << 4) + 0)
+#define M68K_CPU_m68000 ((0 << 4) + 1)
+#define M68K_CPU_m68010 ((0 << 4) + 1) /* make same as m68000 */
+#define M68K_CPU_m68020 ((7 << 4) + 2)
+#define M68K_CPU_m68030 ((7 << 4) + 3)
+#define M68K_CPU_m68040 ((01007 << 4) + 4)
+#define M68K_CPU_m68302 ((0 << 4) + 5)
+#define M68K_CPU_m68332 ((1 << 4) + 6)
+
+/* This is tested for below, so if target wants to override this, it
+ just set this first in cover file. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (TARGET_CPU_DEFAULT >> 4)
+#endif
+
+/* Defaults for the various specs below.
+ These are collected here so we only test TARGET_CPU_DEFAULT once. */
+/* ??? CC1_CPU_DEFAULT_SPEC was copied over from the earlier version of
+ this file. However, it's not used anywhere here because it doesn't
+ seem to be necessary. */
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68k || TARGET_CPU_DEFAULT == M68K_CPU_m68020
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68020 } -D__mc68020 -D__mc68020__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68020"
+#define CC1_CPU_DEFAULT_SPEC "-m68020"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68000
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68000 } -D__mc68000 -D__mc68000__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68000"
+#define CC1_CPU_DEFAULT_SPEC "-m68000"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68030
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68030 } -D__mc68030 -D__mc68030__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68030"
+#define CC1_CPU_DEFAULT_SPEC "-m68030"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68040
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68040 } -D__mc68040 -D__mc68040__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68040"
+#define CC1_CPU_DEFAULT_SPEC "-m68040"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68302
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68302 } -D__mc68302 -D__mc68302__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68302"
+#define CC1_CPU_DEFAULT_SPEC "-m68000"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68332
+#define CPP_CPU_DEFAULT_SPEC "%{!ansi:-Dmc68332 } -D__mc68332 -D__mc68332__"
+#define ASM_CPU_DEFAULT_SPEC "-mc68332"
+#define CC1_CPU_DEFAULT_SPEC "-m68020 -mnobitfield %{!m68881:-msoft-float}"
+#else
+Unrecognized value in TARGET_CPU_DEFAULT.
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+/* Always define mc68000.
+ Remember that GCC will automatically add __mc68000 and __mc68000__. */
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000"
+
+/* Define one of __HAVE_68881__, __HAVE_FPA__, or nothing (soft float), appropriately. */
+#undef CPP_FPU_SPEC
+#if TARGET_DEFAULT & MASK_68881
+/* ??? Why isn't m68302 treated like m68000 here? */
+#define CPP_FPU_SPEC \
+"%{!mc68000:%{!m68000:%{!m68332:%{!m5200:%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}}}}}"
+#else
+/* This can't currently happen, but we code it anyway to show how it's done. */
+#if TARGET_DEFAULT & MASK_FPA
+#define CPP_FPU_SPEC \
+"%{!msoft-float:%{m68881:-D__HAVE_68881__ }%{!m68881:-D__HAVE_FPA__ }}"
+#else
+#define CPP_FPU_SPEC \
+"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }"
+#endif
#endif
/* Names to predefine in the preprocessor for this target machine.
- Always define mc68000. Other definitions depend on switches given
- to the compiler:
+ Other definitions depend on what the default cpu is and switches
+ given to the compiler:
- -m68000: define nothing else
- default, -m68020, -mc68020: define mc68020
+ -m68000, -mc68000: define nothing else
+ -m68010: define mc68010
+ -m68020, -mc68020: define mc68020
-m68030: define mc68030
-m68040: define mc68040
+ -m68060: define mc68060
-m68020-40: define mc68020 mc68030 mc68040
-m68302: define mc68302
-m68332: define mc68332
- */
+ -m5200: define mcf5200
+ default: define as above appropriately
-#ifndef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dmc68000"
-#endif
-
-#ifndef CPP_SPEC
-
-#if TARGET_DEFAULT & 02
+ GCC won't automatically add __'d versions, we have to mention them
+ explicitly. */
-/* -m68881 is the default */
-#define CPP_SPEC \
-"%{!mc68000:%{!m68000:%{!m68332:%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}}}}\
-%{!ansi:%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68020 }}}}}}}}}}}\
-%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68020__ -D__mc68020 }}}}}}}}}}"
-
-#else
-#if TARGET_DEFAULT & 0100
+#undef CPP_SPEC
+#define CPP_SPEC "\
+%(cpp_fpu) \
+%{!ansi:%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68060:-Dmc68060 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{m5200:-Dmcf5200 }} \
+%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{mc68060:-D__mc68060__ -D__mc68060 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{m5200:-D__mcf5200__ -D__mcf5200 } \
+%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68060:%{!m68302:%{!m68332:%{!m5200:%(cpp_cpu_default)}}}}}}}}}}}} \
+%(cpp_subtarget) \
+"
-/* -mfpa is the default */
-#define CPP_SPEC \
-"%{!msoft-float:%{m68881:-D__HAVE_68881__ }%{!m68881:-D__HAVE_FPA__ }}\
-%{!ansi:%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68020 }}}}}}}}}}}\
-%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68020__ -D__mc68020 }}}}}}}}}}"
+/* Pass flags to gas indicating which type of processor we have. */
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881 } \
+%{m68000}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040}%{m68060}%{m68302}%{m68332}%{m5200} \
+%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68060:%{!m68302:%{!m68332:%{!m5200:%(asm_cpu_default)}}}}}}}}}}}} \
+"
+
+#undef CC1_SPEC
+#define CC1_SPEC "\
+%{m68000:%{!m68881:-msoft-float }}%{m68302:-m68000 }%{m68332:-m68020 -mnobitfield %{!m68881:-msoft-float }} \
+"
+/* ??? Is this needed?
+%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:%(cc1_cpu_default)}}}}}}}}}}
+*/
+
+/* 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_default", CPP_CPU_DEFAULT_SPEC }, \
+ { "cpp_fpu", CPP_FPU_SPEC }, \
+ { "cpp_subtarget", CPP_SUBTARGET_SPEC }, \
+ { "asm_cpu_default", ASM_CPU_DEFAULT_SPEC }, \
+/*{ "cc1_cpu_default", CC1_CPU_DEFAULT__SPEC },*/ \
+ SUBTARGET_EXTRA_SPECS
+
+#define CPP_SUBTARGET_SPEC ""
+#define SUBTARGET_EXTRA_SPECS
+
+/* Avoid building multilib libraries for the defaults.
+ t-m68kbare doesn't support -mfpa in the multilib'd libraries, so we don't
+ either.
+ For targets not handled here, just build the full set of multilibs.
+ The default is m68k 99.9% of the time anyway. */
+
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68k || TARGET_CPU_DEFAULT == M68K_CPU_m68020
+#if TARGET_DEFAULT & MASK_68881
+#define MULTILIB_DEFAULTS { "m68020", "m68881" }
#else
-
-/* -msoft-float is the default */
-#define CPP_SPEC \
-"%{m68881:-D__HAVE_68881__ }%{mfpa:-D__HAVE_FPA__ }\
-%{!ansi:%{m68010:-Dmc68010 }%{m68020:-Dmc68020 }%{mc68020:-Dmc68020 }%{m68030:-Dmc68030 }%{m68040:-Dmc68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 }%{m68302:-Dmc68302 }%{m68332:-Dmc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68020 }}}}}}}}}}}\
-%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68020__ -D__mc68020 }}}}}}}}}}"
-
+#define MULTILIB_DEFAULTS { "m68020", "msoft-float" }
#endif
#endif
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68000 || TARGET_CPU_DEFAULT == M68K_CPU_m68302
+#if TARGET_DEFAULT & MASK_68881
+#define MULTILIB_DEFAULTS { "m68000", "m68881" }
+#else
+#define MULTILIB_DEFAULTS { "m68000", "msoft-float" }
#endif
-
-/* Pass flags to gas indicating which type of processor we have. */
-
-#ifndef ASM_SPEC
-
-#define ASM_SPEC \
-"%{m68851}%{mno-68851}%{m68881}%{mno-68881}%{msoft-float:-mno-68881 }\
-%{m68000}%{mc68000}%{m68010}%{m68020}%{mc68020}%{m68030}%{m68040}%{m68020-40:-mc68040}%{m68302}%{m68332}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-mc68020}}}}}}}}}}"
-
-#endif
-
-#ifndef CC1_SPEC
-
-#define CC1_SPEC \
- "%{m68000:%{!m68881:-msoft-float }}%{m68302:-m68000}%{m68332:-m68020 -mnobitfield %{!m68881:-msoft-float}}%{!m68000:%{!mc68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-m68020}}}}}}}}}}"
-
#endif
-
-/* end of m68k-none.h */
diff --git a/gnu/usr.bin/gcc/config/m68k/m68k.c b/gnu/usr.bin/gcc/config/m68k/m68k.c
index 2b5b392bb86..5f932f0121f 100644
--- a/gnu/usr.bin/gcc/config/m68k/m68k.c
+++ b/gnu/usr.bin/gcc/config/m68k/m68k.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Motorola 68000 family.
- Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,8 +20,8 @@ Boston, MA 02111-1307, USA. */
/* Some output-actions in m68k.md need these. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
+#include "tree.h"
/* Needed for use_return_insn. */
#include "flags.h"
@@ -53,6 +54,76 @@ static rtx find_addr_reg ();
rtx legitimize_pic_address ();
+/* Alignment to use for loops and jumps */
+/* Specify power of two alignment used for loops. */
+char *m68k_align_loops_string;
+/* Specify power of two alignment used for non-loop jumps. */
+char *m68k_align_jumps_string;
+/* Specify power of two alignment used for functions. */
+char *m68k_align_funcs_string;
+
+/* Specify power of two alignment used for loops. */
+int m68k_align_loops;
+/* Specify power of two alignment used for non-loop jumps. */
+int m68k_align_jumps;
+/* Specify power of two alignment used for functions. */
+int m68k_align_funcs;
+
+/* Nonzero if the last compare/test insn had FP operands. The
+ sCC expanders peek at this to determine what to do for the
+ 68060, which has no fsCC instructions. */
+int m68k_last_compare_had_fp_operands;
+
+/* Sometimes certain combinations of command options do not make
+ sense on a particular target machine. You can define a macro
+ `OVERRIDE_OPTIONS' to take account of this. This macro, if
+ defined, is executed once just after all the command options have
+ been parsed.
+
+ Don't use this macro to turn on various extra optimizations for
+ `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */
+
+void
+override_options ()
+{
+ int def_align;
+
+ def_align = 1;
+
+ /* Validate -malign-loops= value, or provide default */
+ if (m68k_align_loops_string)
+ {
+ m68k_align_loops = atoi (m68k_align_loops_string);
+ if (m68k_align_loops < 1 || m68k_align_loops > MAX_CODE_ALIGN)
+ fatal ("-malign-loops=%d is not between 1 and %d",
+ m68k_align_loops, MAX_CODE_ALIGN);
+ }
+ else
+ m68k_align_loops = def_align;
+
+ /* Validate -malign-jumps= value, or provide default */
+ if (m68k_align_jumps_string)
+ {
+ m68k_align_jumps = atoi (m68k_align_jumps_string);
+ if (m68k_align_jumps < 1 || m68k_align_jumps > MAX_CODE_ALIGN)
+ fatal ("-malign-jumps=%d is not between 1 and %d",
+ m68k_align_jumps, MAX_CODE_ALIGN);
+ }
+ else
+ m68k_align_jumps = def_align;
+
+ /* Validate -malign-functions= value, or provide default */
+ if (m68k_align_funcs_string)
+ {
+ m68k_align_funcs = atoi (m68k_align_funcs_string);
+ if (m68k_align_funcs < 1 || m68k_align_funcs > MAX_CODE_ALIGN)
+ fatal ("-malign-functions=%d is not between 1 and %d",
+ m68k_align_funcs, MAX_CODE_ALIGN);
+ }
+ else
+ m68k_align_funcs = def_align;
+}
+
/* Emit a (use pic_offset_table_rtx) if we used PIC relocation in the
function at any time during the compilation process. In the future
we should try and eliminate the USE if we can easily determine that
@@ -94,6 +165,7 @@ output_function_prologue (stream, size)
int num_saved_regs = 0;
extern char call_used_regs[];
int fsize = (size + 3) & -4;
+ int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
if (frame_pointer_needed)
@@ -142,18 +214,76 @@ output_function_prologue (stream, size)
reg_names[FRAME_POINTER_REGNUM], -fsize);
#endif
}
+ if (dwarf2out_do_frame ())
+ {
+ char *l = dwarf2out_cfi_label ();
+
+ cfa_store_offset += 4;
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, FRAME_POINTER_REGNUM, cfa_offset);
+ dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, -cfa_store_offset);
+ cfa_store_offset += fsize;
+ }
}
else if (fsize)
{
- /* Adding negative number is faster on the 68040. */
if (fsize + 4 < 0x8000)
{
- /* asm_fprintf() cannot handle %. */
+#ifdef NO_ADDSUB_Q
+ if (fsize + 4 <= 8)
+ {
+ if (!TARGET_5200)
+ {
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tsubq.w %OI%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\tsubqw %OI%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ else
+ {
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tsubq.l %OI%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\tsubql %OI%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ }
+ else if (fsize + 4 <= 16 && TARGET_CPU32)
+ {
+ /* On the CPU32 it is faster to use two subqw instructions to
+ subtract a small integer (8 < N <= 16) to a register. */
+ /* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\tsubq.w %OI8,%Rsp\n\tsubq.w %OI%d,%Rsp\n",
+ fsize + 4);
#else
- asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
+ asm_fprintf (stream, "\tsubqw %OI8,%Rsp\n\tsubqw %OI%d,%Rsp\n",
+ fsize + 4);
#endif
+ }
+ else
+#endif /* NO_ADDSUB_Q */
+ if (TARGET_68040)
+ {
+ /* Adding negative number is faster on the 68040. */
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", - (fsize + 4));
+#else
+ asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", - (fsize + 4));
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", - (fsize + 4));
+#else
+ asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", - (fsize + 4));
+#endif
+ }
}
else
{
@@ -164,6 +294,12 @@ output_function_prologue (stream, size)
asm_fprintf (stream, "\taddl %0I%d,%Rsp\n", - (fsize + 4));
#endif
}
+ if (dwarf2out_do_frame ())
+ {
+ cfa_store_offset += fsize;
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset);
+ }
}
#ifdef SUPPORT_SUN_FPA
for (regno = 24; regno < 56; regno++)
@@ -176,20 +312,55 @@ output_function_prologue (stream, size)
asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n",
reg_names[regno]);
#endif
+ if (dwarf2out_do_frame ())
+ {
+ char *l = dwarf2out_cfi_label ();
+
+ cfa_store_offset += 8;
+ 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
- for (regno = 16; regno < 24; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- mask |= 1 << (regno - 16);
- if ((mask & 0xff) != 0)
+ if (TARGET_68881)
{
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ mask |= 1 << (regno - 16);
+ num_saved_regs++;
+ }
+ if ((mask & 0xff) != 0)
+ {
#ifdef MOTOROLA
- asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
+ asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff);
#else
- asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
+ asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff);
#endif
+ if (dwarf2out_do_frame ())
+ {
+ char *l = dwarf2out_cfi_label ();
+ int n_regs;
+
+ cfa_store_offset += num_saved_regs * 12;
+ if (! frame_pointer_needed)
+ {
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
+ }
+ for (regno = 16, n_regs = 0; regno < 24; regno++)
+ if (mask & (1 << (regno - 16)))
+ dwarf2out_reg_save (l, regno,
+ -cfa_store_offset + n_regs++ * 12);
+ }
+ }
+ mask = 0;
+ num_saved_regs = 0;
}
- mask = 0;
for (regno = 0; regno < 16; regno++)
if (regs_ever_live[regno] && ! call_used_regs[regno])
{
@@ -203,7 +374,15 @@ output_function_prologue (stream, size)
}
#if NEED_PROBE
- fprintf (stream, "\ttstl sp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
+#ifdef MOTOROLA
+#ifdef CRDS
+ asm_fprintf (stream, "\ttstl %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
+#else
+ asm_fprintf (stream, "\ttst.l %d(%Rsp)\n", NEED_PROBE - num_saved_regs * 4);
+#endif
+#else
+ asm_fprintf (stream, "\ttstl %Rsp@(%d)\n", NEED_PROBE - num_saved_regs * 4);
+#endif
#endif
if (num_saved_regs <= 2)
@@ -218,21 +397,81 @@ output_function_prologue (stream, size)
/* Undo the work from above. */
for (i = 0; i< 16; i++)
if (mask & (1 << i))
- asm_fprintf (stream,
+ {
+ asm_fprintf (stream,
#ifdef MOTOROLA
- "\t%Omove.l %s,-(%Rsp)\n",
+ "\t%Omove.l %s,-(%Rsp)\n",
#else
- "\tmovel %s,%Rsp@-\n",
+ "\tmovel %s,%Rsp@-\n",
#endif
- reg_names[15 - i]);
+ reg_names[15 - i]);
+ 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, 15 - i, -cfa_store_offset);
+ }
+ }
}
else if (mask)
{
+ if (TARGET_5200)
+ {
+ /* The coldfire does not support the predecrement form of the
+ movml instruction, so we must adjust the stack pointer and
+ then use the plain address register indirect mode. We also
+ have to invert the register save mask to use the new mode.
+
+ FIXME: if num_saved_regs was calculated earlier, we could
+ combine the stack pointer adjustment with any adjustment
+ done when the initial stack frame is created. This would
+ save an instruction */
+
+ int newmask = 0;
+ int i;
+
+ for (i = 0; i < 16; i++)
+ if (mask & (1 << i))
+ newmask |= (1 << (15-i));
+
#ifdef MOTOROLA
- asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
+ asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", -num_saved_regs*4);
+ asm_fprintf (stream, "\tmovm.l %0I0x%x,(%Rsp)\n", newmask);
#else
- asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
+ asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", -num_saved_regs*4);
+ asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@\n", newmask);
#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tmovm.l %0I0x%x,-(%Rsp)\n", mask);
+#else
+ asm_fprintf (stream, "\tmoveml %0I0x%x,%Rsp@-\n", mask);
+#endif
+ }
+ if (dwarf2out_do_frame ())
+ {
+ char *l = dwarf2out_cfi_label ();
+ int n_regs;
+
+ cfa_store_offset += num_saved_regs * 4;
+ if (! frame_pointer_needed)
+ {
+ cfa_offset = cfa_store_offset;
+ dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset);
+ }
+ for (regno = 0, n_regs = 0; regno < 16; regno++)
+ if (mask & (1 << (15 - regno)))
+ dwarf2out_reg_save (l, regno,
+ -cfa_store_offset + n_regs++ * 4);
+ }
}
if (flag_pic && current_function_uses_pic_offset_table)
{
@@ -290,6 +529,7 @@ output_function_epilogue (stream, size)
int fsize = (size + 3) & -4;
int big = 0;
rtx insn = get_last_insn ();
+ int restore_from_sp = 0;
/* If the last insn was a BARRIER, we don't have to write any code. */
if (GET_CODE (insn) == NOTE)
@@ -302,6 +542,13 @@ output_function_epilogue (stream, size)
return;
}
+#ifdef FUNCTION_BLOCK_PROFILER_EXIT
+ if (profile_block_flag == 2)
+ {
+ FUNCTION_BLOCK_PROFILER_EXIT (stream);
+ }
+#endif
+
#ifdef FUNCTION_EXTRA_EPILOGUE
FUNCTION_EXTRA_EPILOGUE (stream, size);
#endif
@@ -313,12 +560,15 @@ output_function_epilogue (stream, size)
fpoffset = nregs * 8;
#endif
nregs = 0;
- for (regno = 16; regno < 24; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- {
- nregs++;
- fmask |= 1 << (23 - regno);
- }
+ if (TARGET_68881)
+ {
+ for (regno = 16; regno < 24; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ nregs++;
+ fmask |= 1 << (23 - regno);
+ }
+ }
foffset = fpoffset + nregs * 12;
nregs = 0; mask = 0;
if (frame_pointer_needed)
@@ -330,8 +580,13 @@ output_function_epilogue (stream, size)
mask |= 1 << regno;
}
offset = foffset + nregs * 4;
+ /* FIXME : leaf_function_p below is too strong.
+ What we really need to know there is if there could be pending
+ stack adjustment needed at that point. */
+ restore_from_sp = ! frame_pointer_needed
+ || (! current_function_calls_alloca && leaf_function_p ());
if (offset + fsize >= 0x8000
- && frame_pointer_needed
+ && ! restore_from_sp
&& (mask || fmask || fpoffset))
{
#ifdef MOTOROLA
@@ -341,7 +596,7 @@ output_function_epilogue (stream, size)
#endif
fsize = 0, big = 1;
}
- if (nregs <= 2)
+ if (TARGET_5200 || nregs <= 2)
{
/* Restore each separately in the same order moveml does.
Using two movel instructions instead of a single moveml
@@ -367,7 +622,7 @@ output_function_epilogue (stream, size)
offset + fsize, reg_names[i]);
#endif
}
- else if (! frame_pointer_needed)
+ else if (restore_from_sp)
{
#ifdef MOTOROLA
asm_fprintf (stream, "\t%Omove.l (%Rsp)+,%s\n",
@@ -408,7 +663,7 @@ output_function_epilogue (stream, size)
offset + fsize, mask);
#endif
}
- else if (! frame_pointer_needed)
+ else if (restore_from_sp)
{
#ifdef MOTOROLA
asm_fprintf (stream, "\tmovm.l (%Rsp)+,%0I0x%x\n", mask);
@@ -445,7 +700,7 @@ output_function_epilogue (stream, size)
foffset + fsize, fmask);
#endif
}
- else if (! frame_pointer_needed)
+ else if (restore_from_sp)
{
#ifdef MOTOROLA
asm_fprintf (stream, "\tfmovm (%Rsp)+,%0I0x%x\n", fmask);
@@ -484,7 +739,7 @@ output_function_epilogue (stream, size)
fpoffset + fsize, reg_names[regno]);
#endif
}
- else if (! frame_pointer_needed)
+ else if (restore_from_sp)
{
#ifdef MOTOROLA
asm_fprintf (stream, "\tfpmovd (%Rsp)+,%s\n",
@@ -514,14 +769,60 @@ output_function_epilogue (stream, size)
reg_names[FRAME_POINTER_REGNUM]);
else if (fsize)
{
+#ifdef NO_ADDSUB_Q
+ if (fsize + 4 <= 8)
+ {
+ if (!TARGET_5200)
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\taddq.w %OI%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\taddqw %OI%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\taddq.l %OI%d,%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\taddql %OI%d,%Rsp\n", fsize + 4);
+#endif
+ }
+ }
+ else if (fsize + 4 <= 16 && TARGET_CPU32)
+ {
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register. */
+ /* asm_fprintf() cannot handle %. */
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\taddq.w %OI8,%Rsp\n\taddq.w %OI%d,%Rsp\n",
+ fsize + 4);
+#else
+ asm_fprintf (stream, "\taddqw %OI8,%Rsp\n\taddqw %OI%d,%Rsp\n",
+ fsize + 4);
+#endif
+ }
+ else
+#endif /* NO_ADDSUB_Q */
if (fsize + 4 < 0x8000)
{
- /* asm_fprintf() cannot handle %. */
+ if (TARGET_68040)
+ {
+ /* asm_fprintf() cannot handle %. */
#ifdef MOTOROLA
- asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\tadd.w %0I%d,%Rsp\n", fsize + 4);
#else
- asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
+ asm_fprintf (stream, "\taddw %0I%d,%Rsp\n", fsize + 4);
#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ asm_fprintf (stream, "\tlea (%d,%Rsp),%Rsp\n", fsize + 4);
+#else
+ asm_fprintf (stream, "\tlea %Rsp@(%d),%Rsp\n", fsize + 4);
+#endif
+ }
}
else
{
@@ -562,13 +863,8 @@ valid_dbcc_comparison_p (x, mode)
rtx x;
enum machine_mode mode;
{
- /* We could add support for these in the future */
- if (cc_prev_status.flags & CC_IN_68881)
- return 0;
-
switch (GET_CODE (x))
{
-
case EQ: case NE: case GTU: case LTU:
case GEU: case LEU:
return 1;
@@ -582,16 +878,23 @@ valid_dbcc_comparison_p (x, mode)
}
}
+/* Return non-zero if flags are currently in the 68881 flag register. */
+int
+flags_in_68881 ()
+{
+ /* We could add support for these in the future */
+ return cc_status.flags & CC_IN_68881;
+}
+
/* Output a dbCC; jCC sequence. Note we do not handle the
floating point version of this sequence (Fdbcc). We also
do not handle alternative conditions when CC_NO_OVERFLOW is
- set. It is assumed that valid_dbcc_comparison_p will kick
- those out before we get here. */
+ set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
+ kick those out before we get here. */
output_dbcc_and_branch (operands)
rtx *operands;
{
-
switch (GET_CODE (operands[3]))
{
case EQ:
@@ -708,6 +1011,9 @@ output_scc_di(op, operand1, operand2, dest)
rtx loperands[7];
enum rtx_code op_code = GET_CODE (op);
+ /* This does not produce a usefull cc. */
+ CC_STATUS_INIT;
+
/* The m68k cmp.l instruction requires operand1 to be a reg as used
below. Swap the operands and change the op if these requirements
are not fulfilled. */
@@ -1006,6 +1312,8 @@ legitimize_pic_address (orig, mode, reg)
gen_rtx (PLUS, Pmode,
pic_offset_table_rtx, orig));
current_function_uses_pic_offset_table = 1;
+ if (reload_in_progress)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
RTX_UNCHANGING_P (pic_ref) = 1;
emit_move_insn (reg, pic_ref);
return reg;
@@ -1042,11 +1350,7 @@ legitimize_pic_address (orig, mode, reg)
typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ } CONST_METHOD;
-use_movq (i)
- int i;
-{
- return (i >= -128 && i <= 127);
-}
+#define USE_MOVQ(i) ((unsigned)((i) + 128) <= 255)
CONST_METHOD
const_method (constant)
@@ -1056,22 +1360,28 @@ const_method (constant)
unsigned u;
i = INTVAL (constant);
- if (use_movq (i))
+ if (USE_MOVQ (i))
return MOVQ;
- /* if -256 < N < 256 but N is not in range for a moveq
- N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
- if (use_movq (i ^ 0xff))
- return NOTB;
- /* Likewise, try with not.w */
- if (use_movq (i ^ 0xffff))
- return NOTW;
- /* This is the only value where neg.w is useful */
- if (i == -65408)
- return NEGW;
- /* Try also with swap */
- u = i;
- if (use_movq ((u >> 16) | (u << 16)))
- return SWAP;
+
+ /* The Coldfire doesn't have byte or word operations. */
+ /* FIXME: This may not be useful for the m68060 either */
+ if (!TARGET_5200)
+ {
+ /* if -256 < N < 256 but N is not in range for a moveq
+ N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */
+ if (USE_MOVQ (i ^ 0xff))
+ return NOTB;
+ /* Likewise, try with not.w */
+ if (USE_MOVQ (i ^ 0xffff))
+ return NOTW;
+ /* This is the only value where neg.w is useful */
+ if (i == -65408)
+ return NEGW;
+ /* Try also with swap */
+ u = i;
+ if (USE_MOVQ ((u >> 16) | (u << 16)))
+ return SWAP;
+ }
/* Otherwise, use move.l */
return MOVL;
}
@@ -1150,6 +1460,216 @@ output_move_const_into_data_reg (operands)
}
}
+char *
+output_move_simode_const (operands)
+ rtx *operands;
+{
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.l %0";
+ else if (DATA_REG_P (operands[0]))
+ return output_move_const_into_data_reg (operands);
+ else if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return "move%.w %1,%0";
+ else if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+ && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM
+ && INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return "pea %a1";
+ return "move%.l %1,%0";
+}
+
+char *
+output_move_simode (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_move_simode_const (operands);
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && push_operand (operands[0], SImode))
+ return "pea %a1";
+ else if ((GET_CODE (operands[1]) == SYMBOL_REF
+ || GET_CODE (operands[1]) == CONST)
+ && ADDRESS_REG_P (operands[0]))
+ return "lea %a1,%0";
+ return "move%.l %1,%0";
+}
+
+char *
+output_move_himode (operands)
+ rtx *operands;
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ if (operands[1] == const0_rtx
+ && (DATA_REG_P (operands[0])
+ || GET_CODE (operands[0]) == MEM)
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM
+ && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.w %0";
+ else if (DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ {
+#if defined(MOTOROLA) && !defined(CRDS)
+ return "moveq%.l %1,%0";
+#else
+ return "moveq %1,%0";
+#endif
+ }
+ else if (INTVAL (operands[1]) < 0x8000
+ && INTVAL (operands[1]) >= -0x8000)
+ return "move%.w %1,%0";
+ }
+ else if (CONSTANT_P (operands[1]))
+ return "move%.l %1,%0";
+#ifndef SGS_NO_LI
+ /* Recognize the insn before a tablejump, one that refers
+ to a table of offsets. Such an insn will need to refer
+ to a label on the insn. So output one. Use the label-number
+ of the table of offsets to generate this label. This code,
+ and similar code below, assumes that there will be at most one
+ reference to each table. */
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
+ {
+ rtx labelref = XEXP (XEXP (operands[1], 0), 1);
+#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
+#ifdef SGS
+ asm_fprintf (asm_out_file, "\tset %LLI%d,.+2\n",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#else /* not SGS */
+ asm_fprintf (asm_out_file, "\t.set %LLI%d,.+2\n",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#endif /* not SGS */
+#else /* SGS_SWITCH_TABLES or not MOTOROLA */
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LI",
+ CODE_LABEL_NUMBER (XEXP (labelref, 0)));
+#ifdef SGS_SWITCH_TABLES
+ /* Set flag saying we need to define the symbol
+ LD%n (with value L%n-LI%n) at the end of the switch table. */
+ switch_table_difference_label_flag = 1;
+#endif /* SGS_SWITCH_TABLES */
+#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
+ }
+#endif /* SGS_NO_LI */
+ return "move%.w %1,%0";
+}
+
+char *
+output_move_qimode (operands)
+ rtx *operands;
+{
+ rtx xoperands[4];
+
+ /* This is probably useless, since it loses for pushing a struct
+ of several bytes a byte at a time. */
+ /* 68k family always modifies the stack pointer by at least 2, even for
+ byte pushes. The 5200 (coldfire) does not do this. */
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
+ && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
+ && ! ADDRESS_REG_P (operands[1])
+ && ! TARGET_5200)
+ {
+ xoperands[1] = operands[1];
+ xoperands[2]
+ = gen_rtx (MEM, QImode,
+ gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
+ /* Just pushing a byte puts it in the high byte of the halfword. */
+ /* We must put it in the low-order, high-numbered byte. */
+ if (!reg_mentioned_p (stack_pointer_rtx, operands[1]))
+ {
+ xoperands[3] = stack_pointer_rtx;
+#ifndef NO_ADDSUB_Q
+ output_asm_insn ("subq%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
+#else
+ output_asm_insn ("sub%.l %#2,%3\n\tmove%.b %1,%2", xoperands);
+#endif
+ }
+ else
+ output_asm_insn ("move%.b %1,%-\n\tmove%.b %@,%2", xoperands);
+ return "";
+ }
+
+ /* clr and st insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ if (!ADDRESS_REG_P (operands[0])
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ {
+ if (operands[1] == const0_rtx)
+ return "clr%.b %0";
+ if ((!TARGET_5200 || DATA_REG_P (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && (INTVAL (operands[1]) & 255) == 255)
+ {
+ CC_STATUS_INIT;
+ return "st %0";
+ }
+ }
+ if (GET_CODE (operands[1]) == CONST_INT
+ && DATA_REG_P (operands[0])
+ && INTVAL (operands[1]) < 128
+ && INTVAL (operands[1]) >= -128)
+ {
+#if defined(MOTOROLA) && !defined(CRDS)
+ return "moveq%.l %1,%0";
+#else
+ return "moveq %1,%0";
+#endif
+ }
+ if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
+ return "move%.l %1,%0";
+ /* 68k family doesn't support byte moves to from address registers. The
+ 5200 (coldfire) does not have this restriction. */
+ if ((ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
+ && ! TARGET_5200)
+ return "move%.w %1,%0";
+ return "move%.b %1,%0";
+}
+
+char *
+output_move_stricthi (operands)
+ rtx *operands;
+{
+ if (operands[1] == const0_rtx
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.w %0";
+ return "move%.w %1,%0";
+}
+
+char *
+output_move_strictqi (operands)
+ rtx *operands;
+{
+ if (operands[1] == const0_rtx
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ return "clr%.b %0";
+ return "move%.b %1,%0";
+}
+
/* Return the best assembler insn template
for moving operands[1] into operands[0] as a fullword. */
@@ -1161,14 +1681,9 @@ singlemove_string (operands)
if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
return "fpmoves %1,%0";
#endif
- if (DATA_REG_P (operands[0])
- && GET_CODE (operands[1]) == CONST_INT)
- return output_move_const_into_data_reg (operands);
- if (operands[1] != const0_rtx)
- return "move%.l %1,%0";
- if (! ADDRESS_REG_P (operands[0]))
- return "clr%.l %0";
- return "sub%.l %0,%0";
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return output_move_simode_const (operands);
+ return "move%.l %1,%0";
}
@@ -1550,6 +2065,97 @@ find_addr_reg (addr)
return addr;
abort ();
}
+
+/* Output assembler code to perform a 32 bit 3 operand add. */
+
+char *
+output_addsi3 (operands)
+ rtx *operands;
+{
+ if (! operands_match_p (operands[0], operands[1]))
+ {
+ if (!ADDRESS_REG_P (operands[1]))
+ {
+ rtx tmp = operands[1];
+
+ operands[1] = operands[2];
+ operands[2] = tmp;
+ }
+
+ /* These insns can result from reloads to access
+ stack slots over 64k from the frame pointer. */
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
+ return "move%.l %2,%0\n\tadd%.l %1,%0";
+#ifdef SGS
+ if (GET_CODE (operands[2]) == REG)
+ return "lea 0(%1,%2.l),%0";
+ else
+ return "lea %c2(%1),%0";
+#else /* not SGS */
+#ifdef MOTOROLA
+ if (GET_CODE (operands[2]) == REG)
+ return "lea (%1,%2.l),%0";
+ else
+ return "lea (%c2,%1),%0";
+#else /* not MOTOROLA (MIT syntax) */
+ if (GET_CODE (operands[2]) == REG)
+ return "lea %1@(0,%2:l),%0";
+ else
+ return "lea %1@(%c2),%0";
+#endif /* not MOTOROLA */
+#endif /* not SGS */
+ }
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+#ifndef NO_ADDSUB_Q
+ if (INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= 8)
+ return "addq%.l %2,%0";
+ if (INTVAL (operands[2]) < 0
+ && INTVAL (operands[2]) >= -8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]));
+ return "subq%.l %2,%0";
+ }
+ /* On the CPU32 it is faster to use two addql instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subql. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
+ {
+ if (INTVAL (operands[2]) > 8
+ && INTVAL (operands[2]) <= 16)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) - 8);
+ return "addq%.l %#8,%0\n\taddq%.l %2,%0";
+ }
+ if (INTVAL (operands[2]) < -8
+ && INTVAL (operands[2]) >= -16)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]) - 8);
+ return "subq%.l %#8,%0\n\tsubq%.l %2,%0";
+ }
+ }
+#endif
+ if (ADDRESS_REG_P (operands[0])
+ && INTVAL (operands[2]) >= -0x8000
+ && INTVAL (operands[2]) < 0x8000)
+ {
+ if (TARGET_68040)
+ return "add%.w %2,%0";
+ else
+#ifdef MOTOROLA
+ return "lea (%c2,%0),%0";
+#else
+ return "lea %0@(%c2),%0";
+#endif
+ }
+ }
+ return "add%.l %2,%0";
+}
/* Store in cc_status the expressions that the condition codes will
describe after execution of an instruction whose pattern is EXP.
@@ -1644,8 +2250,10 @@ notice_update_cc (exp, insn)
{
case PLUS: case MINUS: case MULT:
case DIV: case UDIV: case MOD: case UMOD: case NEG:
+#if 0 /* These instructions always clear the overflow bit */
case ASHIFT: case ASHIFTRT: case LSHIFTRT:
case ROTATE: case ROTATERT:
+#endif
if (GET_MODE (cc_status.value2) != VOIDmode)
cc_status.flags |= CC_NO_OVERFLOW;
break;
@@ -1776,11 +2384,11 @@ init_68881_table ()
REAL_VALUE_TYPE r;
enum machine_mode mode;
- mode = DFmode;
+ mode = SFmode;
for (i = 0; i < 7; i++)
{
if (i == 6)
- mode = SFmode;
+ mode = DFmode;
r = REAL_VALUE_ATOF (strings_68881[i], mode);
values_68881[i] = r;
}
@@ -2061,7 +2669,7 @@ standard_sun_fpa_constant_p (x)
'@' for a reference to the top word on the stack:
sp@, (sp) or (%sp) depending on the style of syntax.
'#' for an immediate operand prefix (# in MIT and Motorola syntax
- but & in SGS syntax).
+ but & in SGS syntax, $ in CRDS/UNOS syntax).
'!' for the cc register (used in an `and to cc' insn).
'$' for the letter `s' in an op code, but only on the 68040.
'&' for the letter `d' in an op code, but only on the 68040.
@@ -2090,7 +2698,7 @@ print_operand (file, op, letter)
if (letter == '.')
{
-#ifdef MOTOROLA
+#if defined (MOTOROLA) && !defined (CRDS)
asm_fprintf (file, ".");
#endif
}
@@ -2174,7 +2782,11 @@ print_operand (file, op, letter)
&& INTVAL (XEXP (op, 0)) < 0x8000
&& INTVAL (XEXP (op, 0)) >= -0x8000))
{
+#ifdef MOTOROLA
+ fprintf (file, ".l");
+#else
fprintf (file, ":l");
+#endif
}
}
#ifdef SUPPORT_SUN_FPA
@@ -2439,7 +3051,11 @@ print_operand_address (file, addr)
{
output_addr_const (file, addr);
if (flag_pic && (breg == pic_offset_table_rtx))
- fprintf (file, "@GOT");
+ {
+ fprintf (file, "@GOT");
+ if (flag_pic == 1)
+ fprintf (file, ".w");
+ }
}
fprintf (file, "(%s", reg_names[REGNO (breg)]);
if (ireg != 0)
@@ -2618,3 +3234,122 @@ const_sint32_operand (op, mode)
return (GET_CODE (op) == CONST_INT
&& (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
}
+
+char *
+output_andsi3 (operands)
+ rtx *operands;
+{
+ int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0]))
+ && !TARGET_5200)
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) & 0xffff);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (operands[2] == const0_rtx)
+ return "clr%.w %0";
+ return "and%.w %2,%0";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
+ }
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
+ }
+ /* This does not set condition codes in a standard way. */
+ CC_STATUS_INIT;
+ return "bclr %1,%0";
+ }
+ return "and%.l %2,%0";
+}
+
+char *
+output_iorsi3 (operands)
+ rtx *operands;
+{
+ register int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0]))
+ && !TARGET_5200)
+ {
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (INTVAL (operands[2]) == 0xffff)
+ return "mov%.w %2,%0";
+ return "or%.w %2,%0";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
+ }
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
+ }
+ CC_STATUS_INIT;
+ return "bset %1,%0";
+ }
+ return "or%.l %2,%0";
+}
+
+char *
+output_xorsi3 (operands)
+ rtx *operands;
+{
+ register int logval;
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) >> 16 == 0
+ && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
+ && !TARGET_5200)
+ {
+ if (! DATA_REG_P (operands[0]))
+ operands[0] = adj_offsettable_operand (operands[0], 2);
+ /* Do not delete a following tstl %0 insn; that would be incorrect. */
+ CC_STATUS_INIT;
+ if (INTVAL (operands[2]) == 0xffff)
+ return "not%.w %0";
+ return "eor%.w %2,%0";
+ }
+ if (GET_CODE (operands[2]) == CONST_INT
+ && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (DATA_REG_P (operands[0])
+ || offsettable_memref_p (operands[0])))
+ {
+ if (DATA_REG_P (operands[0]))
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
+ }
+ else
+ {
+ operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
+ operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
+ }
+ CC_STATUS_INIT;
+ return "bchg %1,%0";
+ }
+ return "eor%.l %2,%0";
+}
diff --git a/gnu/usr.bin/gcc/config/m68k/m68kemb.h b/gnu/usr.bin/gcc/config/m68k/m68kemb.h
index 9975b900ca3..4c02e1be6e6 100644
--- a/gnu/usr.bin/gcc/config/m68k/m68kemb.h
+++ b/gnu/usr.bin/gcc/config/m68k/m68kemb.h
@@ -38,6 +38,16 @@
#undef NEEDS_UNTYPED_CALL
#define NEEDS_UNTYPED_CALL 1
-/* crt0.o should be specified in the linker script. */
-#undef STARTFILE_SPEC
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -D__embedded__ -Asystem(embedded) \
+ -Amachine(mc68000)"
+
+/* Override the default LIB_SPEC from gcc.c. We don't currently support
+ profiling, or libg.a. */
+
+#define LIB_SPEC "-lc"
+
+/* Make this be null, since we want the crt0.o to come from the linker
+ script */
+
#define STARTFILE_SPEC ""
diff --git a/gnu/usr.bin/gcc/config/m68k/m68kv4.h b/gnu/usr.bin/gcc/config/m68k/m68kv4.h
index 48644134942..a40d919990d 100644
--- a/gnu/usr.bin/gcc/config/m68k/m68kv4.h
+++ b/gnu/usr.bin/gcc/config/m68k/m68kv4.h
@@ -1,7 +1,7 @@
/* Target definitions for GNU compiler for mc680x0 running System V.4
- Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
-
- Written by Ron Guilmette (rfg@netcom.com) and Fred Fish (fnf@cygnus.com).
+ Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.com) and
+ Fred Fish (fnf@cygnus.com).
This file is part of GNU CC.
@@ -36,7 +36,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (5 /*68020*/ + 2 /*68881*/)
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
/* When using an SGS assembler, modify the name of the artificial label which
@@ -84,7 +84,7 @@ while (0)
If a 68881 is not the default, gcc will only define __HAVE_68881__ if
-m68881 is specified. */
-#if TARGET_DEFAULT & 2
+#if TARGET_DEFAULT & MASK_68881
#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
#else
#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
@@ -103,6 +103,7 @@ while (0)
/* Local common symbols are declared to the assembler with ".lcomm" rather
than ".bss", so override the definition in svr4.h */
+/* ??? svr4.h no longer defines this, and this is only used by m68k/amix.h. */
#undef BSS_ASM_OP
#define BSS_ASM_OP ".lcomm"
@@ -113,6 +114,13 @@ while (0)
#undef STRUCT_VALUE_REGNUM
#define STRUCT_VALUE_REGNUM 8
+/* Register in which static-chain is passed to a function. The
+ default in m68k.h is a0, but that is already the struct value
+ regnum. Make it a1 instead. */
+
+#undef STATIC_CHAIN_REGNUM
+#define STATIC_CHAIN_REGNUM 9
+
#define ASM_COMMENT_START "#"
#undef TYPE_OPERAND_FMT
@@ -186,7 +194,8 @@ do { \
#undef LIBCALL_VALUE
#define LIBCALL_VALUE(MODE) \
- (((MODE) == SFmode || (MODE) == DFmode) && TARGET_68881 \
+ ((((MODE) == SFmode || (MODE) == DFmode || (MODE) == XFmode) \
+ && TARGET_68881) \
? gen_rtx (REG, (MODE), 16) \
: gen_rtx (REG, (MODE), 0))
@@ -302,3 +311,36 @@ int switch_table_difference_label_flag;
if (! TARGET_68020 && flag_pic == 2) \
error("-fPIC is not currently supported on the 68000 or 68010\n"); \
}
+
+/* Output assembler code for a block containing the constant parts
+ of a trampoline, leaving space for the variable parts. */
+
+/* On m68k svr4, the trampoline is different from the generic version
+ in that we use a1 as the static call chain. */
+
+#undef TRAMPOLINE_TEMPLATE
+#define TRAMPOLINE_TEMPLATE(FILE) \
+{ \
+ ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x227a)); \
+ ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 8)); \
+ ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x2f3a)); \
+ ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 8)); \
+ ASM_OUTPUT_SHORT (FILE, gen_rtx (CONST_INT, VOIDmode, 0x4e75)); \
+ ASM_OUTPUT_INT (FILE, const0_rtx); \
+ ASM_OUTPUT_INT (FILE, const0_rtx); \
+}
+
+/* Redefine since we are using a different trampoline */
+#undef TRAMPOLINE_SIZE
+#define TRAMPOLINE_SIZE 18
+
+/* 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) \
+{ \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 10)), CXT); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 14)), FNADDR); \
+}
diff --git a/gnu/usr.bin/gcc/config/m68k/mot3300.h b/gnu/usr.bin/gcc/config/m68k/mot3300.h
index c85511a42f3..65c2f476043 100644
--- a/gnu/usr.bin/gcc/config/m68k/mot3300.h
+++ b/gnu/usr.bin/gcc/config/m68k/mot3300.h
@@ -1,9 +1,11 @@
/* Definitions of target machine for GNU compiler,
SysV68 Motorola 3300 Delta Series.
- Copyright (C) 1987, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Abramo and Roberto Bagnara (bagnara@dipisa.di.unipi.it)
based on Alex Crain's 3B1 definitions.
Maintained by Philippe De Muyter (phdm@info.ucl.ac.be).
+ Support for GAS added by merging mot3300g.h into this file by
+ Manfred Hollstein (manfred@lts.sel.alcatel.de).
This file is part of GNU CC.
@@ -22,11 +24,13 @@ 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 USE_GAS
#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
#define MOTOROLA_BSR /* Use Span-dependent optimized bsr */
#define SGS /* Uses SGS assembler */
#define SGS_CMP_ORDER /* Takes cmp operands in reverse order */
#define SGS_SWAP_W /* Use swap.w rather than just plain swap */
+#endif /* USE_GAS */
#define NO_DOLLAR_IN_LABEL
#define NO_DOT_IN_LABEL
@@ -36,13 +40,18 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 0407 means 68020-68040. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 0407
+#define TARGET_DEFAULT (MASK_68040|MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
/* -m[c]6800 requires special flag to the assembler. */
#undef ASM_SPEC
+#ifndef USE_GAS
#define ASM_SPEC "%{m68000:-p 000}%{mc68000:-p 000}"
+#else /* USE_GAS */
+#define ASM_SPEC \
+ "%{v:-v} %{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
+#endif /* USE_GAS */
/* NYI: FP= is equivalent to -msoft-float */
@@ -52,16 +61,33 @@ Boston, MA 02111-1307, USA. */
/* NYI: if FP= library is -lc. */
/* Default for us: FP=M68881 library is -lc881 */
#undef LIB_SPEC
-#define LIB_SPEC "%{!shlib:%{p:-L/usr/lib/libp} %{pg:-L/usr/lib/libp} -lc881}"
+#define LIB_SPEC "%{!shlib:%{!msoft-float:-lc881}%{msoft-float:-lc}}"
+#ifdef CROSS_COMPILE
+#ifndef USE_GLD
+#define DEFAULT_A_OUT_NAME "m68ka.out"
+#endif
+#endif
-#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}"
+#ifdef USE_GLD
+#undef LINK_SPEC
+#define LINK_SPEC "%{v:-v}"
+#endif /* defined (USE_GLD) */
+
+#define CPP_SPEC "%{!msoft-float:-D__HAVE_68881__}\
+%{!mc68000:%{!m68000: -D__mc68020__}}"
/* Shared libraries need to use crt0s.o */
#undef STARTFILE_SPEC
+#ifdef CROSS_COMPILE
#define STARTFILE_SPEC \
"%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
- %{shlib:crt0s.o%s shlib.ifile%s} "
+ %{shlib:crt0s.o%s shlib.ifile%s} %{p:-L"TOOLDIR_BASE_PREFIX DEFAULT_TARGET_MACHINE"/lib/libp} %{pg:-L"TOOLDIR_BASE_PREFIX DEFAULT_TARGET_MACHINE"/lib/libp} "
+#else /* CROSS_COMPILE */
+#define STARTFILE_SPEC \
+ "%{!shlib:%{pg:mcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}\
+ %{shlib:crt0s.o%s shlib.ifile%s} %{p:-L/usr/lib/libp} %{pg:-L/usr/lib/libp} "
+#endif /* CROSS_COMPILE */
/* Generate calls to memcpy, memcmp and memset. */
@@ -95,11 +121,15 @@ Boston, MA 02111-1307, USA. */
#undef REGISTER_PREFIX
#define REGISTER_PREFIX "%"
-#if 0
#undef LOCAL_LABEL_PREFIX
-#define LOCAL_LABEL_PREFIX "~"
+#ifdef USE_GAS
+#define LOCAL_LABEL_PREFIX ".L"
+#else
+#define LOCAL_LABEL_PREFIX "L%"
#endif
+#undef USER_LABEL_PREFIX
+
#undef IMMEDIATE_PREFIX
#define IMMEDIATE_PREFIX "&"
@@ -118,7 +148,7 @@ Boston, MA 02111-1307, USA. */
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE, LABEL_NO) \
- fprintf (FILE, "\tmov.l &LP%%%d,%%a0\n\tjsr mcount%%\n", (LABEL_NO))
+ asm_fprintf (FILE, "\tmov.l %I%LLP%d,%Ra0\n\tjsr mcount%%\n", (LABEL_NO))
/* This is how to output an insn to push a register on the stack.
It need not be very fast code. */
@@ -134,6 +164,8 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
fprintf (FILE, "\tmov.l (%%sp)+,%s\n", reg_names[REGNO])
+#ifndef USE_GAS
+
#undef ASM_APP_ON
#define ASM_APP_ON ""
@@ -147,11 +179,86 @@ Boston, MA 02111-1307, USA. */
#undef ASCII_DATA_ASM_OP
#define ASCII_DATA_ASM_OP "byte"
+#undef SET_ASM_OP
+#define SET_ASM_OP "set"
+
+#endif /* USE_GAS */
+
+#ifdef USE_GLD
+/* Support the ctors and dtors sections for g++. */
+
+#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\""
+#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_ctors, in_dtors
+
+/* A list of extra section function definitions. */
+
+#undef EXTRA_SECTION_FUNCTIONS
+#define EXTRA_SECTION_FUNCTIONS \
+ 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; \
+ } \
+}
+
+/* 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 ", ASM_LONG); \
+ 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 ", ASM_LONG); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, "\n"); \
+ } while (0)
+#endif /* defined (USE_GLD) */
+
/* The file command should always begin the output. */
#undef ASM_FILE_START
+#ifndef USE_GAS
+#define ASM_FILE_START(FILE) \
+ output_file_directive ((FILE), main_input_filename)
+#else /* USE_GAS */
#define ASM_FILE_START(FILE) \
-output_file_directive ((FILE), main_input_filename)
+ { \
+ fprintf (FILE, "%s", ASM_APP_OFF); \
+ output_file_directive ((FILE), main_input_filename); \
+ }
+#endif /* USE_GAS */
/* The sysV68 assembler does not accept dots in labels.
Let's use percent instead */
@@ -166,15 +273,9 @@ output_file_directive ((FILE), main_input_filename)
#define CPP_PREDEFINES "-Dm68k -Dunix -DsysV68 -D__motorola__ -Asystem(unix) -Asystem(svr3) -Acpu(m68k) -Amachine(m68k)"
#undef TARGET_VERSION
+#ifndef USE_GAS
#define TARGET_VERSION fprintf (stderr, " (68k, SGS/AT&T sysV68 syntax)");
-
-/* Function calls save all but a0, a1, d0, d1, fp0, fp1. */
-
-#undef CALL_USED_REGISTERS
-#define CALL_USED_REGISTERS \
- {1, 1, 0, 0, 0, 0, 0, 0, \
- 1, 1, 0, 0, 0, 0, 0, 1, \
- 1, 1, 0, 0, 0, 0, 0, 0}
+#endif /* USE_GAS */
/* This will return small structs in d0. */
#define RETURN_IN_MEMORY(type) \
@@ -223,11 +324,13 @@ output_file_directive ((FILE), main_input_filename)
#undef NEEDS_UNTYPED_CALL
#define NEEDS_UNTYPED_CALL 1
+#ifndef USE_GAS
/* This is the command to make the user-level label named NAME
defined for reference from other files. */
#undef GLOBAL_ASM_OP
#define GLOBAL_ASM_OP "global"
+#endif /* USE_GAS */
/* Store in OUTPUT a string (made with alloca) containing
an assembler-name for a local static variable named NAME.
@@ -238,6 +341,30 @@ output_file_directive ((FILE), main_input_filename)
( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 12), \
sprintf ((OUTPUT), "%s_%%%d", (NAME), (LABELNO)))
+#ifdef USE_GAS
+#undef ASM_LONG
+#define ASM_LONG ".long"
+#undef ASM_SHORT
+#define ASM_SHORT ".short"
+#undef ASM_CHAR
+#define ASM_CHAR ".byte"
+#undef ASM_BYTE
+#define ASM_BYTE ".byte"
+#undef ASM_BYTE_OP
+#define ASM_BYTE_OP ".byte"
+#else
+#undef ASM_LONG
+#define ASM_LONG "long"
+#undef ASM_SHORT
+#define ASM_SHORT "short"
+#undef ASM_CHAR
+#define ASM_CHAR "byte"
+#undef ASM_BYTE
+#define ASM_BYTE "byte"
+#undef ASM_BYTE_OP
+#define ASM_BYTE_OP "byte"
+#endif /* USE_GAS */
+
/* The sysV68 as doesn't know about double's and float's. */
/* This is how to output an assembler line defining a `double' constant. */
@@ -245,14 +372,14 @@ output_file_directive ((FILE), main_input_filename)
#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
do { long l[2]; \
REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
- fprintf (FILE, "\tlong 0x%x,0x%x\n", l[0], l[1]); \
+ fprintf (FILE, "\t%s 0x%x,0x%x\n", ASM_LONG, l[0], l[1]); \
} while (0)
#undef ASM_OUTPUT_LONG_DOUBLE
#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
do { long l[3]; \
REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \
- fprintf (FILE, "\tlong 0x%x,0x%x,0x%x\n", l[0], l[1], l[2]); \
+ fprintf (FILE, "\t%s 0x%x,0x%x,0x%x\n", ASM_LONG, l[0], l[1], l[2]); \
} while (0)
/* This is how to output an assembler line defining a `float' constant. */
@@ -261,14 +388,14 @@ do { long l[3]; \
#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
do { long l; \
REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
- fprintf ((FILE), "\tlong 0x%x\n", l); \
+ fprintf ((FILE), "\t%s 0x%x\n", ASM_LONG, l); \
} while (0)
/* This is how to output an assembler line defining an `int' constant. */
#undef ASM_OUTPUT_INT
#define ASM_OUTPUT_INT(FILE,VALUE) \
-( fprintf (FILE, "\tlong "), \
+( fprintf (FILE, "\t%s ", ASM_LONG), \
output_addr_const (FILE, (VALUE)), \
fprintf (FILE, "\n"))
@@ -276,13 +403,13 @@ do { long l; \
#undef ASM_OUTPUT_SHORT
#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "\tshort "), \
+( fprintf (FILE, "\t%s ", ASM_SHORT), \
output_addr_const (FILE, (VALUE)), \
fprintf (FILE, "\n"))
#undef ASM_OUTPUT_CHAR
#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "\tbyte "), \
+( fprintf (FILE, "\t%s ", ASM_CHAR), \
output_addr_const (FILE, (VALUE)), \
fprintf (FILE, "\n"))
@@ -290,22 +417,32 @@ do { long l; \
#undef ASM_OUTPUT_BYTE
#define ASM_OUTPUT_BYTE(FILE,VALUE) \
- fprintf (FILE, "\tbyte 0x%x\n", (VALUE))
+ fprintf (FILE, "\t%s 0x%x\n", ASM_BYTE, (VALUE))
/* This is how to output an assembler line
that says to advance the location counter
to a multiple of 2**LOG bytes. */
+#ifndef USE_GAS
+#define ALIGN_ASM_OP "even"
+#else /* USE_GAS */
+#define ALIGN_ASM_OP ".even"
+#endif /* USE_GAS */
+
#undef ASM_OUTPUT_ALIGN
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG) == 1) \
- fprintf (FILE, "\teven\n"); \
- else if ((LOG) != 0) \
- abort ();
+ if ((LOG) >= 1) \
+ fprintf (FILE, "\t%s\n", ALIGN_ASM_OP);
+
+#ifndef USE_GAS
+#define SKIP_ASM_OP "space"
+#else /* USE_GAS */
+#define SKIP_ASM_OP ".skip"
+#endif /* USE_GAS */
#undef ASM_OUTPUT_SKIP
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\tspace %u\n", (SIZE))
+ fprintf (FILE, "\t%s %u\n", SKIP_ASM_OP, (SIZE))
/* Can't use ASM_OUTPUT_SKIP in text section. */
@@ -313,7 +450,10 @@ do { long l; \
/* The beginnings of sdb support... */
-#undef ASM_OUTPUT_SOURCE_FILENAME
+/* Undefining these will allow `output_file_directive' (in toplev.c)
+ to default to the right thing. */
+#undef ASM_OUTPUT_MAIN_SOURCE_FILENAME
+#ifndef USE_GAS
#define ASM_OUTPUT_SOURCE_FILENAME(FILE, FILENAME) \
do { fprintf (FILE, "\tfile\t"); \
output_quoted_string (FILE, FILENAME); \
@@ -331,7 +471,7 @@ do { long l; \
#undef ASM_OUTPUT_ASCII
#define ASM_OUTPUT_ASCII(FILE,PTR,LEN) \
do { register int sp = 0, lp = 0; \
- fprintf ((FILE), "\tbyte\t"); \
+ fprintf ((FILE), "\t%s\t", ASM_BYTE_OP); \
loop: \
if ((PTR)[sp] > ' ' && ! ((PTR)[sp] & 0x80) && (PTR)[sp] != '\\') \
{ lp += 3; \
@@ -347,7 +487,9 @@ do { long l; \
putc (',', (FILE)); \
goto loop; } \
putc ('\n', (FILE)); } while (0)
+#endif /* USE_GAS */
+#ifndef USE_GAS
/* Output a float value (represented as a C double) as an immediate operand.
This macro is a 68k-specific macro. */
@@ -367,6 +509,7 @@ do { long l; \
REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
fprintf ((FILE), "&0x%lx%08lx", l[0], l[1]); \
} while (0)
+#endif /* USE_GAS */
/* This is how to store into the string LABEL
the symbol_ref name of an internal numbered label where
@@ -375,38 +518,42 @@ do { long l; \
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
- sprintf ((LABEL), "%s%%%d", (PREFIX), (NUM))
+ sprintf ((LABEL), "%s%s%d", LOCAL_LABEL_PREFIX, (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)
+ asm_fprintf (FILE, "%L%s%d:\n", PREFIX, NUM)
-/* 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. */
-#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 element of a case-vector that is absolute.
(The 68000 does not use such vectors,
but we must define this macro anyway.) */
+/* The L after the local prefix is the "L" prefix for the normal labels
+ generated by gcc; why are ASM_OUTPUT_ADDR_VEC_ELT and
+ ASM_OUTPUT_ADDR_DIFF_ELT not called with a PREFIX parameter, like
+ ASM_OUTPUT_INTERNAL_LABEL ? */
#undef ASM_OUTPUT_ADDR_VEC_ELT
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- fprintf (FILE, "\tlong L%%%d\n", (VALUE))
+ asm_fprintf (FILE, "\t%s %LL%d\n", ASM_LONG, (VALUE))
/* 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, VALUE, REL) \
- fprintf (FILE, "\tshort L%%%d-L%%%d\n", (VALUE), (REL))
+ asm_fprintf (FILE, "\t%s %LL%d-%LL%d\n", ASM_SHORT, (VALUE), (REL))
+
+#ifndef USE_GAS
#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
- fprintf (FILE, "\tswbeg &%d\n%s%%%d:\n", \
+ asm_fprintf (FILE, "\tswbeg &%d\n%L%s%d:\n", \
XVECLEN (PATTERN (TABLE), 1), (PREFIX), (NUM))
/* sysV68 as cannot handle LD%n(%pc,%reg) */
@@ -416,8 +563,26 @@ do { long l; \
#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
asm_fprintf (file, "12(%Rpc,%s.", regname)
-#define ASM_RETURN_CASE_JUMP return "jmp 8(%%pc,%0.w)"
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp 8(%%pc,%0.l)"; \
+ else \
+ return "jmp 8(%%pc,%0.w)"; \
+ } while (0)
+#else /* USE_GAS */
+
+/* labelno is not used here */
+#define ASM_OUTPUT_CASE_FETCH(file, labelno, regname)\
+ asm_fprintf (file, "%Rpc@(6,%s:", regname)
+
+#define ASM_RETURN_CASE_JUMP return "jmp %%pc@(2,%0:w)"
+
+#endif /* USE_GAS */
+
+#ifndef USE_GAS
+
/* Translate some opcodes to fit the sysV68 assembler syntax. */
/* The opcodes fdmov and fsmov are guesses. */
@@ -474,6 +639,7 @@ do { long l; \
if ((PTR)[0] == 'a' || (PTR)[0] == 'i' \
|| (PTR)[0] == 'm') (PTR)++; } \
}
+#endif /* USE_GAS */
/* phdm@info.ucl.ac.be says to pass SIZE, not ROUNDED. */
@@ -481,21 +647,35 @@ do { long l; \
to define a global common symbol. */
#undef ASM_OUTPUT_COMMON
+#ifndef USE_GAS
#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
( fputs ("\tcomm ", (FILE)), \
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%u\n", (SIZE)))
+#else /* USE_GAS */
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.comm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+#endif /* USE_GAS */
/* This says how to output an assembler line
to define a local common symbol. */
#undef ASM_OUTPUT_LOCAL
+#ifndef USE_GAS
#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
( fputs ("\tlcomm ", (FILE)), \
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%u\n", (SIZE)))
+#else /* USE_GAS */
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
+( fputs ("\t.lcomm ", (FILE)), \
+ assemble_name ((FILE), (NAME)), \
+ fprintf ((FILE), ",%u\n", (SIZE)))
+#endif /* USE_GAS */
-
+#ifndef USE_GAS
/* Override usual definitions of SDB output macros.
These definitions differ only in the absence of the period
at the beginning of the name of the directive
@@ -554,6 +734,8 @@ do { fprintf (asm_out_file, "\ttag\t"); \
#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
sprintf ((BUFFER), "~%dfake", (NUMBER));
+#endif /* USE_GAS */
+
/* Define subroutines to call to handle multiply, divide, and remainder.
Use the subroutines that the sysV68's library provides.
The `*' prevents an underscore from being prepended by the compiler. */
@@ -575,7 +757,7 @@ struct sysV68_cumulative_args
#define CUMULATIVE_ARGS struct sysV68_cumulative_args
#undef INIT_CUMULATIVE_ARGS
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
do {(CUM).offset = 0;\
(CUM).libcall = (LIBNAME) && (*XSTR((LIBNAME), 0) == '*');} while(0)
@@ -600,3 +782,35 @@ do {(CUM).offset = 0;\
#undef FUNCTION_ARG_REGNO_P
#define FUNCTION_ARG_REGNO_P(N) (TARGET_68020 ? 0 : (N) == 0)
+
+/* manfred@lts.sel.alcatel.de: I believe that most delta machines are configured to have
+ a 6888[12] FPU for which we need to link -lm881 instead of -lm; define ALT_LIBM to
+ tell g++.c about that. */
+#define ALT_LIBM "-lm881"
+
+#if (TARGET_DEFAULT & MASK_68881) /* The default configuration has a 6888[12] FPU. */
+#define MATH_LIBRARY "-lm881"
+#endif
+
+/* Currently we do not have the atexit() function,
+ so take that from libgcc2.c */
+
+#define NEED_ATEXIT 1
+#define HAVE_ATEXIT 1
+
+#define EXIT_BODY \
+ do \
+ { \
+ __stop_monitor (); \
+ _cleanup (); \
+ } while (0)
+
+/* FINALIZE_TRAMPOLINE clears the instruction cache. */
+
+#undef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP) \
+ if (!TARGET_68040) \
+ ; \
+ else \
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__clear_insn_cache"), \
+ 0, VOIDmode, 0)
diff --git a/gnu/usr.bin/gcc/config/m68k/news.h b/gnu/usr.bin/gcc/config/m68k/news.h
index 8300801b681..f83524cc0cf 100644
--- a/gnu/usr.bin/gcc/config/m68k/news.h
+++ b/gnu/usr.bin/gcc/config/m68k/news.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. SONY NEWS-OS 4 version.
- Copyright (C) 1987, 1989, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 93, 94, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,7 +31,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
/* Define __HAVE_68881__ in preprocessor, unless -msoft-float is specified.
This will control the use of inline 68881 insns in certain macros. */
@@ -105,8 +105,6 @@ Boston, MA 02111-1307, USA. */
#undef ASM_OUTPUT_DOUBLE
#undef ASM_OUTPUT_SKIP
#undef ASM_FORMAT_PRIVATE_NAME
-#undef PRINT_OPERAND
-#undef PRINT_OPERAND_ADDRESS
#endif
#undef ASM_OUTPUT_ALIGN
@@ -299,6 +297,66 @@ do { char dstr[30]; \
( (OUTPUT) = (char *) alloca (strlen ((NAME)) + 13), \
sprintf ((OUTPUT), "%s$$$%d", (NAME), (LABELNO)))
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { \
+ if (CODE == 'f') \
+ { \
+ char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.9e", dstr); \
+ if (REAL_VALUE_ISINF (VALUE) || REAL_VALUE_ISNAN (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0f-99e999"); \
+ else \
+ fprintf (FILE, "#0f99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ fprintf (FILE, "#0f-0.0"); \
+ else \
+ fprintf (FILE, "#0f%s", dstr); \
+ } \
+ else \
+ { \
+ long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf (FILE, "#0x%lx", l); \
+ } \
+ } while (0)
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr ); \
+ if (REAL_VALUE_ISINF (VALUE) || REAL_VALUE_ISNAN (VALUE)) \
+ { \
+ if (REAL_VALUE_NEGATIVE (VALUE)) \
+ fprintf (FILE, "#0d-99e999"); \
+ else \
+ fprintf (FILE, "#0d99e999"); \
+ } \
+ else if (REAL_VALUE_MINUS_ZERO (VALUE)) \
+ fprintf (FILE, "#0d-0.0"); \
+ else \
+ fprintf (FILE, "#0d%s", dstr); \
+ } while (0)
+
+/* Note, long double immediate operands are not actually
+ generated by m68k.md. */
+#undef ASM_OUTPUT_LONG_DOUBLE_OPERAND
+#define ASM_OUTPUT_LONG_DOUBLE_OPERAND(FILE,VALUE) \
+ do { char dstr[30]; \
+ REAL_VALUE_TO_DECIMAL (VALUE, "%.20g", dstr); \
+ asm_fprintf (FILE, "%I0r%s", dstr); \
+ } while (0)
+
+#if 0
+#undef PRINT_OPERAND
#define PRINT_OPERAND(FILE, X, CODE) \
{ if (CODE == '.') fprintf (FILE, "."); \
else if (CODE == '#') fprintf (FILE, "#"); \
@@ -354,7 +412,9 @@ do { char dstr[30]; \
fprintf (FILE, "#0d%s", dstr); } \
else if (CODE == 'b') output_addr_const (FILE, X); \
else { putc ('#', FILE); output_addr_const (FILE, X); }}
+#endif
+#undef PRINT_OPERAND_ADDRESS
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
{ register rtx reg1, reg2, breg, ireg; \
register rtx addr = ADDR; \
diff --git a/gnu/usr.bin/gcc/config/m68k/newsgas.h b/gnu/usr.bin/gcc/config/m68k/newsgas.h
index 5e8c3b28348..8dc7801ea60 100644
--- a/gnu/usr.bin/gcc/config/m68k/newsgas.h
+++ b/gnu/usr.bin/gcc/config/m68k/newsgas.h
@@ -4,4 +4,16 @@
#define USE_GAS
+/* This is the assembler directive to equate two values. */
+
+#undef SET_ASM_OP
+#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); \
+ fputc ('\n', FILE); } while (0)
+
#include "m68k/news.h"
diff --git a/gnu/usr.bin/gcc/config/m68k/next.h b/gnu/usr.bin/gcc/config/m68k/next.h
index 91474950579..8391ab50cb1 100644
--- a/gnu/usr.bin/gcc/config/m68k/next.h
+++ b/gnu/usr.bin/gcc/config/m68k/next.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for mc680x0 running NeXTSTEP
- Copyright (C) 1989, 90, 91, 92, 93, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1989, 90-94, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,12 +20,10 @@ Boston, MA 02111-1307, USA. */
#include "m68k/m68k.h"
#include "nextstep.h"
-#include "machmode.h"
-#include "real.h"
/* See m68k.h. 0407 means 68040 (or 68030 or 68020, with 68881/2). */
-#define TARGET_DEFAULT 0407
+#define TARGET_DEFAULT (MASK_68040|MASK_BITFIELD|MASK_68881|MASK_68020)
/* Boundary (in *bits*) on which stack pointer should be aligned. */
@@ -34,7 +32,7 @@ Boston, MA 02111-1307, USA. */
/* Names to predefine in the preprocessor for this target machine. */
-#define CPP_PREDEFINES "-Dmc68000 -Dm68k -DNeXT -Dunix -D__MACH__ -D__BIG_ENDIAN__ -D__ARCHITECTURE__=\"m68k\" -Asystem(unix) -Asystem(mach) -Acpu(m68k) -Amachine(m68k)"
+#define CPP_PREDEFINES "-Dmc68000 -Dm68k -DNeXT -Dunix -D__MACH__ -D__BIG_ENDIAN__ -D__ARCHITECTURE__=\"m68k\" -Asystem(unix) -Asystem(mach) -Acpu(m68k) -Amachine(m68k) -D_NEXT_SOURCE"
/* Every structure or union's size must be a multiple of 2 bytes.
(Why isn't this in m68k.h?) */
@@ -174,7 +172,7 @@ Boston, MA 02111-1307, USA. */
Previously, references to labels generated pc-relative addressing modes
while references to symbol names generated absolute addressing modes. */
-#undef GO_IF_INDEXABLE_BASE(X, ADDR)
+#undef GO_IF_INDEXABLE_BASE
#define GO_IF_INDEXABLE_BASE(X, ADDR) \
{ if (LEGITIMATE_BASE_REG_P (X)) goto ADDR; }
@@ -183,21 +181,13 @@ Boston, MA 02111-1307, USA. */
#define OBJC_FORWARDING_STACK_OFFSET 8
#define OBJC_FORWARDING_MIN_OFFSET 8
-/* INITIALIZE_TRAMPOLINE is changed so that it also enables executable
- stack. The __enable_execute_stack also clears the insn cache. */
-
-/* NOTE: part of this is copied from m68k.h */
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- rtx _addr, _func; \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 2)), TRAMP); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 18)), CXT); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 22)), FNADDR); \
- _addr = memory_address (SImode, (TRAMP)); \
- _func = gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"); \
- emit_library_call (_func, 0, VOIDmode, 1, _addr, Pmode); \
-}
+/* FINALIZE_TRAMPOLINE enables executable stack. The
+ __enable_execute_stack also clears the insn cache. */
+
+#undef FINALIZE_TRAMPOLINE
+#define FINALIZE_TRAMPOLINE(TRAMP) \
+ emit_library_call(gen_rtx(SYMBOL_REF, Pmode, "__enable_execute_stack"), \
+ 0, VOIDmode, 1, memory_address(SImode, (TRAMP)), Pmode)
/* A C expression used to clear the instruction cache from
address BEG to address END. On NeXTSTEP this i a system trap. */
diff --git a/gnu/usr.bin/gcc/config/m68k/pbb.h b/gnu/usr.bin/gcc/config/m68k/pbb.h
index c3e7fd299d0..41319c219af 100644
--- a/gnu/usr.bin/gcc/config/m68k/pbb.h
+++ b/gnu/usr.bin/gcc/config/m68k/pbb.h
@@ -1,8 +1,6 @@
/* Definitions of target machine for GNU compiler.
-
Citicorp/TTI Unicom PBB version (using GAS with a %-register prefix)
-
- Copyright (C) 1987, 1988, 1990 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1990, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -29,7 +27,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 5 means 68020 without 68881. */
-#define TARGET_DEFAULT 5
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
/* Don't try using XFmode. */
#undef LONG_DOUBLE_TYPE_SIZE
@@ -116,7 +114,13 @@ Boston, MA 02111-1307, USA. */
! find_equiv_reg (0, get_last_insn (), 0, 0, 0, 8, Pmode)) \
asm_fprintf (FILE, "\tmovl %Rd0,%Ra0\n"); }
-#define ASM_RETURN_CASE_JUMP return "jmp %%pc@(2,%0:w)"
+#define ASM_RETURN_CASE_JUMP \
+ do { \
+ if (TARGET_5200) \
+ return "ext%.l %0\n\tjmp %%pc@(2,%0:l)"; \
+ else \
+ return "jmp %%pc@(2,%0:w)"; \
+ } while (0)
/* 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
diff --git a/gnu/usr.bin/gcc/config/m68k/plexus.h b/gnu/usr.bin/gcc/config/m68k/plexus.h
index 769b5fb5a33..3ca99fdb5bc 100644
--- a/gnu/usr.bin/gcc/config/m68k/plexus.h
+++ b/gnu/usr.bin/gcc/config/m68k/plexus.h
@@ -1,26 +1,7 @@
-/* Definitions of target machine for GNU compiler.
- Copyright (C) 1990, 1994 Free Software Foundation, Inc.
-
- Written by Randy Welch
- Send bug reports, questions and improvements to any of the following
- addresses:
-
- randy@kcin.uucp
- randy@tss.com
- rwelch@netcom.com
- plx-info@wpg.com Plexus users mailing list
-
- For 680X0 based Plexus Computers running SYSVR2
-
- The Plexus port of gcc requires you to use gas ( either 1.3X with COFF
- patches or 2.X ), If you use gas 2.X you have to use binutils-2.X.
-
- With using gas-2.X the Plexus gcc port is now capable of generating
- output suitable for use by gdb-4.X ( send mail to above address for
- info on getting gdb patches or other GNU items for the Plexus )
-
- This is configured for label output default by gas as LXXX instead of
- plexus cc/as combination requires .LXXX
+/* Definitions of target machine for GNU compiler, for 680X0 based Plexus
+ Computers running SYSVR2
+ Copyright (C) 1990, 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Randy Welch (rwelch@netcom.com).
This file is part of GNU CC.
@@ -40,12 +21,22 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* The Plexus port of gcc requires you to use gas ( either 1.3X with COFF
+ patches or 2.X ), If you use gas 2.X you have to use binutils-2.X.
+
+ With using gas-2.X the Plexus gcc port is now capable of generating
+ output suitable for use by gdb-4.X ( send mail to above address for
+ info on getting gdb patches or other GNU items for the Plexus )
+
+ This is configured for label output default by gas as LXXX instead of
+ plexus cc/as combination requires .LXXX */
+
#include "m68k/m68k.h"
/* Define __HAVE_68881 in preprocessor only if -m68881 is specified.
This will control the use of inline 68881 insns in certain macros. */
-#define TARGET_DEFAULT 5 /* set to 5 if on a '020 box */
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
/* Don't try using XFmode. */
#undef LONG_DOUBLE_TYPE_SIZE
@@ -54,7 +45,7 @@ Boston, MA 02111-1307, USA. */
#define CPP_SPEC "%{m68881:-D__HAVE_68881__}"
#define CPP_PREDEFINES "-Dm68 -Dunix -Dplexus -Asystem(unix) -Acpu(m68k) -Amachine(m68k)"
-#if TARGET_DEFAULT & 01
+#if TARGET_DEFAULT & MASK_68020
#define ASM_SPEC\
"%{m68000:-mc68000}%{mc68000:-mc68000}%{!mc68000:%{!m68000:-mc68020}}"
#undef STRICT_ALIGNMENT
diff --git a/gnu/usr.bin/gcc/config/m68k/sgs.h b/gnu/usr.bin/gcc/config/m68k/sgs.h
index f4476a0942c..447ca6ec5cc 100644
--- a/gnu/usr.bin/gcc/config/m68k/sgs.h
+++ b/gnu/usr.bin/gcc/config/m68k/sgs.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler for m68k targets using
assemblers derived from AT&T "SGS" releases.
- Copyright (C) 1991, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1996 Free Software Foundation, Inc.
Written by Fred Fish (fnf@cygnus.com)
This file is part of GNU CC.
@@ -419,10 +419,10 @@ do { \
#define ASM_OUTPUT_CASE_END(FILE,NUM,TABLE) \
{ if (switch_table_difference_label_flag) \
asm_fprintf (FILE, "\t%s %LLD%d,%LL%d-%LLI%d-2.b\n",\
- SET_ASM_OP, (NUM), (NUM), (NUM)) \
+ SET_ASM_OP, (NUM), (NUM), (NUM)); \
switch_table_difference_label_flag = 0; }
-int switch_table_difference_label_flag;
+extern int switch_table_difference_label_flag;
/* This is how to output an element of a case-vector that is relative. */
diff --git a/gnu/usr.bin/gcc/config/m68k/sun2o4.h b/gnu/usr.bin/gcc/config/m68k/sun2o4.h
index adaf48a5231..da722cfa6ec 100644
--- a/gnu/usr.bin/gcc/config/m68k/sun2o4.h
+++ b/gnu/usr.bin/gcc/config/m68k/sun2o4.h
@@ -1,5 +1,5 @@
-/* Definitions of target machine for GNU compiler. Sun 2 running Sunos 4.
- Copyright (C) 1987, 1988, 1993 Free Software Foundation, Inc.
+/* Definitions of target machine for GNU compiler. Sun 2 running SunOS 4.
+ Copyright (C) 1987, 1988, 1993, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 16
-#if TARGET_DEFAULT & 0200
+#if TARGET_DEFAULT & MASK_SKY
/* -msky is the default */
#define CPP_SPEC \
@@ -58,7 +58,7 @@ Boston, MA 02111-1307, USA. */
#undef STARTFILE_SPEC
-#if TARGET_DEFAULT & 0200
+#if TARGET_DEFAULT & MASK_SKY
/* -msky is the default */
#define STARTFILE_SPEC \
"%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
@@ -78,7 +78,7 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
-#if TARGET_DEFAULT & 0200
+#if TARGET_DEFAULT & MASK_SKY
/* -msky is the default */
#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
%{a:/usr/lib/bb_link.o -lc} %{g:-lg} \
diff --git a/gnu/usr.bin/gcc/config/m68k/sun3.h b/gnu/usr.bin/gcc/config/m68k/sun3.h
index 14fa9b60ad0..13e927ede4d 100644
--- a/gnu/usr.bin/gcc/config/m68k/sun3.h
+++ b/gnu/usr.bin/gcc/config/m68k/sun3.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
- Copyright (C) 1987, 1988, 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,7 +31,7 @@ Boston, MA 02111-1307, USA. */
/* See m68k.h. 7 means 68020 with 68881. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 7
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68881|MASK_68020)
#endif
/* Define __HAVE_FPA__ or __HAVE_68881__ in preprocessor,
@@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA. */
This will control the use of inline 68881 insns in certain macros.
Also inform the program which CPU this is for. */
-#if TARGET_DEFAULT & 02
+#if TARGET_DEFAULT & MASK_68881
/* -m68881 is the default */
#define CPP_SPEC \
@@ -98,7 +98,7 @@ Boston, MA 02111-1307, USA. */
I'm not sure what would happen below if people gave contradictory
arguments (eg. -msoft-float -mfpa) */
-#if TARGET_DEFAULT & 0100
+#if TARGET_DEFAULT & MASK_FPA
/* -mfpa is the default */
#define STARTFILE_SPEC \
"%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
@@ -106,7 +106,7 @@ Boston, MA 02111-1307, USA. */
%{msoft-float:Fcrt1.o%s} \
%{!m68881:%{!msoft-float:Wcrt1.o%s}}"
#else
-#if TARGET_DEFAULT & 2
+#if TARGET_DEFAULT & MASK_68881
/* -m68881 is the default */
#define STARTFILE_SPEC \
"%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}} \
@@ -127,23 +127,23 @@ Boston, MA 02111-1307, USA. */
Control choice of libm.a (if user says -lm)
based on fp arith default and options. */
-#if TARGET_DEFAULT & 0100
+#if TARGET_DEFAULT & MASK_FPA
/* -mfpa is the default */
#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
-%{a:/usr/lib/bb_link.o} %{g:-lg} \
+%{g:-lg} \
%{msoft-float:-L/usr/lib/fsoft}%{m68881:-L/usr/lib/f68881}\
%{!msoft_float:%{!m68881:-L/usr/lib/ffpa}}"
#else
-#if TARGET_DEFAULT & 2
+#if TARGET_DEFAULT & MASK_68881
/* -m68881 is the default */
#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
-%{a:/usr/lib/bb_link.o} %{g:-lg} \
+%{g:-lg} \
%{msoft-float:-L/usr/lib/fsoft}%{!msoft-float:%{!mfpa:-L/usr/lib/f68881}}\
%{mfpa:-L/usr/lib/ffpa}"
#else
/* -msoft-float is the default */
#define LIB_SPEC "%{g:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p} \
-%{a:/usr/lib/bb_link.o} %{g:-lg} \
+%{g:-lg} \
%{!m68881:%{!mfpa:-L/usr/lib/fsoft}}%{m68881:-L/usr/lib/f68881}\
%{mfpa:-L/usr/lib/ffpa}"
#endif
@@ -282,6 +282,10 @@ Boston, MA 02111-1307, USA. */
} \
} while (0)
+#if 0
+/* This was turned off as it caused linking errors on sunos4.1.
+ `gcc -a' links in /usr/lib/bb_link.o which does not provide __bb_link
+ but its own version of __bb_init_func. */
#undef BLOCK_PROFILER_CODE
#define BLOCK_PROFILER_CODE \
extern int ___tcov_init; \
@@ -294,3 +298,4 @@ __bb_init_func (blocks) \
\
___bb_link (blocks->filename, blocks->counts, blocks->ncounts); \
}
+#endif
diff --git a/gnu/usr.bin/gcc/config/m68k/sun3mach.h b/gnu/usr.bin/gcc/config/m68k/sun3mach.h
index 86c48d0f7c3..1c76cc4b828 100644
--- a/gnu/usr.bin/gcc/config/m68k/sun3mach.h
+++ b/gnu/usr.bin/gcc/config/m68k/sun3mach.h
@@ -6,7 +6,7 @@
/* Specify extra dir to search for include files. */
#define SYSTEM_INCLUDE_DIR "/usr/mach/include"
-/* LINK_SPEC is needed only for Sunos 4. */
+/* LINK_SPEC is needed only for SunOS 4. */
#undef LINK_SPEC
diff --git a/gnu/usr.bin/gcc/config/m68k/sun3n.h b/gnu/usr.bin/gcc/config/m68k/sun3n.h
index d93bee0fbe4..32f5f657dc0 100644
--- a/gnu/usr.bin/gcc/config/m68k/sun3n.h
+++ b/gnu/usr.bin/gcc/config/m68k/sun3n.h
@@ -1,6 +1,6 @@
/* Define target machine as a Sun 3 with no 68881. */
-#define TARGET_DEFAULT 5
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
#include "m68k/sun3.h"
diff --git a/gnu/usr.bin/gcc/config/m68k/sun3n3.h b/gnu/usr.bin/gcc/config/m68k/sun3n3.h
index 1c962bd68b8..38680d805e2 100644
--- a/gnu/usr.bin/gcc/config/m68k/sun3n3.h
+++ b/gnu/usr.bin/gcc/config/m68k/sun3n3.h
@@ -1,5 +1,5 @@
#include "m68k/sun3n.h"
-/* LINK_SPEC is needed only for Sunos 4. */
+/* LINK_SPEC is needed only for SunOS 4. */
#undef LINK_SPEC
diff --git a/gnu/usr.bin/gcc/config/m68k/sun3o3.h b/gnu/usr.bin/gcc/config/m68k/sun3o3.h
index 4d3e3dd2584..95f1ff65d03 100644
--- a/gnu/usr.bin/gcc/config/m68k/sun3o3.h
+++ b/gnu/usr.bin/gcc/config/m68k/sun3o3.h
@@ -1,5 +1,5 @@
#include "m68k/sun3.h"
-/* LINK_SPEC is needed only for Sunos 4. */
+/* LINK_SPEC is needed only for SunOS 4. */
#undef LINK_SPEC
diff --git a/gnu/usr.bin/gcc/config/m68k/t-linux b/gnu/usr.bin/gcc/config/m68k/t-linux
index 85f13a7f1ed..b60654d3895 100644
--- a/gnu/usr.bin/gcc/config/m68k/t-linux
+++ b/gnu/usr.bin/gcc/config/m68k/t-linux
@@ -1,5 +1,19 @@
+# Don't run fixproto
+STMP_FIXPROTO =
# Don't make libgcc1.a
LIBGCC1 =
CROSS_LIBGCC1 =
-# On Linux we can print long double
+# On GNU/Linux we can print long double
ENQUIRE_CFLAGS = -DNO_MEM -O0
+# Don't install assert.h
+INSTALL_ASSERT_H =
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = -fPIC
+# Compile libgcc2.a with pic.
+TARGET_LIBGCC2_CFLAGS = -fPIC
+# Don't install assert.h
+INSTALL_ASSERT_H =
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = -fPIC
+# Compile libgcc2.a with pic.
+TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gnu/usr.bin/gcc/config/m68k/t-m68kbare b/gnu/usr.bin/gcc/config/m68k/t-m68kbare
index 6b9b2d2e939..34c832a0f13 100644
--- a/gnu/usr.bin/gcc/config/m68k/t-m68kbare
+++ b/gnu/usr.bin/gcc/config/m68k/t-m68kbare
@@ -15,9 +15,10 @@ xfgnulib.c: $(srcdir)/config/m68k/fpgnulib.c
echo '#define EXTFLOAT' > xfgnulib.c
cat $(srcdir)/config/m68k/fpgnulib.c >> xfgnulib.c
-MULTILIB_OPTIONS = m68000/m68020 m68881/msoft-float
+MULTILIB_OPTIONS = m68000/m68020/m5200 m68881/msoft-float
MULTILIB_DIRNAMES =
MULTILIB_MATCHES = m68000=mc68000 m68000=m68302 m68000=m68332 m68020=mc68020 m68020=m68040
+MULTILIB_EXCEPTIONS = *m5200/*m68881 *m5200/*msoft-float
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/m68k/t-next b/gnu/usr.bin/gcc/config/m68k/t-next
index 439688b541b..787ee79968e 100644
--- a/gnu/usr.bin/gcc/config/m68k/t-next
+++ b/gnu/usr.bin/gcc/config/m68k/t-next
@@ -2,3 +2,5 @@
LIBGCC1=
CROSS_LIBGCC1=
+nextstep.o: $(srcdir)/config/nextstep.c $(CONFIG_H) flags.h tree.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gnu/usr.bin/gcc/config/m68k/t-vxworks68 b/gnu/usr.bin/gcc/config/m68k/t-vxworks68
index 7be1bb0ee76..7fa59430a28 100644
--- a/gnu/usr.bin/gcc/config/m68k/t-vxworks68
+++ b/gnu/usr.bin/gcc/config/m68k/t-vxworks68
@@ -7,7 +7,7 @@ LIB1ASMFUNCS = _mulsi3 _udivsi3 _divsi3 _umodsi3 _modsi3 \
# We don't want to put exit in libgcc.a for VxWorks, because VxWorks
# does not have _exit.
-LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) -g1 -Dexit=unused_exit
+TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit
# These are really part of libgcc1, but this will cause them to be
# built correctly, so...
diff --git a/gnu/usr.bin/gcc/config/m68k/tower-as.h b/gnu/usr.bin/gcc/config/m68k/tower-as.h
index d4f15d37535..46aa30a7478 100644
--- a/gnu/usr.bin/gcc/config/m68k/tower-as.h
+++ b/gnu/usr.bin/gcc/config/m68k/tower-as.h
@@ -1,14 +1,9 @@
/* Definitions of target machine for GNU compiler.
For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
- Copyright (C) 1990, 1993, 1994 Free Software Foundation, Inc.
- Written by Robert Andersson (ra@intsys.no), International Systems,
+ Copyright (C) 1990, 1993, 1994, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Robert Andersson (ra@intsys.no), International Systems,
Oslo, Norway.
- This file outputs assembler source suitable for the native Tower as
- and with sdb debugging symbols. See tower.h for more comments.
-
- This file was based on m68k.h, hp320.h and 3b1.h as of the 1.37.1 version.
-
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
@@ -27,6 +22,12 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* This file outputs assembler source suitable for the native Tower as
+ and with sdb debugging symbols. See tower.h for more comments.
+
+ This file was based on m68k.h, hp320.h and 3b1.h as of the
+ 1.37.1 version. */
+
#include "m68k/tower.h"
#undef SELECT_RTX_SECTION
@@ -49,6 +50,12 @@ Boston, MA 02111-1307, USA. */
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX ""
+/* The prefix to add to user-visible assembler symbols. */
+/* We do not want leading underscores. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+
/* These four macros control how m68k.md is expanded. */
#define MOTOROLA /* Use Motorola syntax rather than "MIT" */
@@ -322,6 +329,27 @@ do { long l; \
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
fprintf (FILE, "\tspace %d\n", (SIZE))
+/* Output a float value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+
+#undef ASM_OUTPUT_FLOAT_OPERAND
+#define ASM_OUTPUT_FLOAT_OPERAND(CODE,FILE,VALUE) \
+ do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (r, l); \
+ /* Use hex representation even if CODE is f. as needs it. */ \
+ fprintf ((FILE), "&0x%lx", l); \
+ } while (0)
+
+/* Output a double value (represented as a C double) as an immediate operand.
+ This macro is a 68k-specific macro. */
+#undef ASM_OUTPUT_DOUBLE_OPERAND
+#define ASM_OUTPUT_DOUBLE_OPERAND(FILE,VALUE) \
+ do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf ((FILE), "&0x%lx%08lx", l[0], l[1]); \
+ } while (0)
+
+#if 0
#undef PRINT_OPERAND
#define PRINT_OPERAND(FILE, X, CODE) \
{ if (CODE == '.') fprintf (FILE, "."); \
@@ -353,6 +381,7 @@ do { long l; \
REAL_VALUE_FROM_CONST_DOUBLE (r, X); \
ASM_OUTPUT_LONG_DOUBLE_OPERAND (FILE, r); } \
else { putc ('&', FILE); output_addr_const (FILE, X); }}
+#endif
/* Note that this contains a kludge that knows that the only reason
we have an address (plus (label_ref...) (reg...))
@@ -585,9 +614,3 @@ do { fprintf (asm_out_file, "\ttag\t"); \
assemble_name (FILE, NAME); \
fprintf (FILE, ",-(%%sp)\n"); \
} while (0)
-
-/* We do not want leading underscores. */
-
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, "%s", NAME)
diff --git a/gnu/usr.bin/gcc/config/m68k/tower.h b/gnu/usr.bin/gcc/config/m68k/tower.h
index 34c7cfb40c8..73faedbd0e7 100644
--- a/gnu/usr.bin/gcc/config/m68k/tower.h
+++ b/gnu/usr.bin/gcc/config/m68k/tower.h
@@ -1,21 +1,6 @@
/* Definitions of target machine for GNU compiler.
- Copyright (C) 1990, 1994 Free Software Foundation, Inc.
-
- Written by Robert Andersson, International Systems, Oslo, Norway.
- Please send bug reports, questions and improvements to ra@intsys.no.
-
- For NCR Tower 32/4x0 and 32/6x0 running System V Release 3.
- I don't have access to 200/700/800/850 machines, so I don't know if it
- works on those as well. It shouldn't be far from it however.
- The hardware floating point support is completely untested, as I do
- not have access to a machine with a 6888x FPU in it.
- It does not work on the System V Release 2 based OS releases. Making it
- work will not be easy, due to the silly way in which stack expansion is
- implemented in the OS.
-
- This file is included in tower-as.h.
- Do *NOT* include this file directly.
-
+ Copyright (C) 1990, 1994, 1996 Free Software Foundation, Inc.
+ Contributed by Robert Andersson, International Systems, Oslo, ra@intsys.no.
This file is part of GNU CC.
@@ -34,13 +19,21 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* For NCR Tower 32/4x0 and 32/6x0 running System V Release 3. I don't have
+ access to 200/700/800/850 machines, so I don't know if it works on those
+ as well. It shouldn't be far from it however. The hardware floating point
+ support is completely untested, as I do not have access to a machine with
+ a 6888x FPU in it. It does not work on the System V Release 2 based OS
+ releases. Making it work will not be easy, due to the silly way in which
+ stack expansion is implemented in the OS.
-#include "m68k/m68k.h"
+ This file is included in tower-as.h.
+ Do *NOT* include this file directly. */
-/* See m68k.h. 5 means 68020 with no 68881. */
+#include "m68k/m68k.h"
-#define TARGET_DEFAULT 5
+#define TARGET_DEFAULT (MASK_BITFIELD|MASK_68020)
/* Don't try using XFmode. */
#undef LONG_DOUBLE_TYPE_SIZE
@@ -103,8 +96,9 @@ Boston, MA 02111-1307, USA. */
#undef IMMEDIATE_PREFIX
#define IMMEDIATE_PREFIX "&"
+/* The prefix to add to user-visible assembler symbols. */
+
/* We do not want leading underscores. */
-#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/gnu/usr.bin/gcc/config/m68k/vxm68k.h b/gnu/usr.bin/gcc/config/m68k/vxm68k.h
index 862cdb827e4..063ded86a63 100644
--- a/gnu/usr.bin/gcc/config/m68k/vxm68k.h
+++ b/gnu/usr.bin/gcc/config/m68k/vxm68k.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Vxworks m68k version.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,26 +20,63 @@ Boston, MA 02111-1307, USA. */
/* This comment is here to see if it will keep Sun's cpp from dying. */
-#define CPP_PREDEFINES "-Dmc68000 -D__vxworks -D__vxworks_5 -Acpu(m68k) -Amachine(m68k)"
-
-/* Vxworks header files require that the macro CPU be set, so we must override
- the CPP_SPEC from m68k-none.h. */
-
-#define CPP_SPEC \
-"%{!mc68000:%{!m68000:%{!m68332:%{!msoft-float:%{mfpa:-D__HAVE_FPA__ }%{!mfpa:-D__HAVE_68881__ }}}}}\
-%{!ansi:%{m68000:-DCPU=MC68000 }%{m68010:-Dmc68010 -DCPU=MC68010 }%{m68020:-Dmc68020 -DCPU=MC68020 }%{mc68020:-Dmc68020 -DCPU=MC68020 }%{m68030:-Dmc68030 -DCPU=MC68030 }%{m68040:-Dmc68040 -DCPU=MC68040 }%{m68020-40:-Dmc68020 -Dmc68030 -Dmc68040 -DCPU=MC68020 }%{m68302:-Dmc68302 -DCPU=MC68000 }%{m68332:-Dmc68332 -DCPU=CPU32 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-Dmc68020 -DCPU=MC68020 }}}}}}}}}}}\
-%{m68010:-D__mc68010__ -D__mc68010 }%{m68020:-D__mc68020__ -D__mc68020 }%{mc68020:-D__mc68020__ -D__mc68020 }%{m68030:-D__mc68030__ -D__mc68030 }%{m68040:-D__mc68040__ -D__mc68040 }%{m68020-40:-D__mc68020__ -D__mc68030__ -D__mc68040__ -D__mc68020 -D__mc68030 -D__mc68040 }%{m68302:-D__mc68302__ -D__mc68302 }%{m68332:-D__mc68332__ -D__mc68332 }%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:-D__mc68020__ -D__mc68020 }}}}}}}}}}"
-
#include "m68k/m68k-none.h"
#include "aoutos.h"
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-Dmc68000 -D__vxworks -D__vxworks_5 -Acpu(m68k) -Amachine(m68k)"
+
+/* The default value for -DCPU=. */
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68k || TARGET_CPU_DEFAULT == M68K_CPU_m68020
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68020"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68000
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68000"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68030
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68030"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68040
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68040"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68302
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68302"
+#else
+#if TARGET_CPU_DEFAULT == M68K_CPU_m68332
+#define CPP_SUBTARGET_CPU_DEFAULT_SPEC "-DCPU=MC68332"
+#else
+Unrecognized value in TARGET_CPU_DEFAULT.
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+{ "cpp_subtarget_cpu_default", CPP_SUBTARGET_CPU_DEFAULT_SPEC }
+
+/* Vxworks header files require that the macro CPU be set. */
+/* ??? The previous code didn't set CPU if -ansi. */
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "\
+%{m68000:-DCPU=MC68000 }%{m68010:-DCPU=MC68010 }%{m68020:-DCPU=MC68020 }%{mc68020:-DCPU=MC68020 }%{m68030:-DCPU=MC68030 }%{m68040:-DCPU=MC68040 }%{m68020-40:-DCPU=MC68020 }%{m68302:-DCPU=MC68000 }%{m68332:-DCPU=CPU32 } \
+%{!mc68000:%{!m68000:%{!m68010:%{!mc68020:%{!m68020:%{!m68030:%{!m68040:%{!m68020-40:%{!m68302:%{!m68332:%(cpp_subtarget_cpu_default) }}}}}}}}}} \
+"
+
#define DBX_DEBUGGING_INFO
#undef SDB_DEBUGGING_INFO
+/* These are the official values from WRS. */
#undef WCHAR_TYPE
-#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE "char"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 8
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
#undef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
+#define SIZE_TYPE "unsigned int"
/* VxWorks does all the library stuff itself. */
diff --git a/gnu/usr.bin/gcc/config/m68k/x-hp3bsd44 b/gnu/usr.bin/gcc/config/m68k/x-hp3bsd44
index 936b5797801..b8dffd03805 100644
--- a/gnu/usr.bin/gcc/config/m68k/x-hp3bsd44
+++ b/gnu/usr.bin/gcc/config/m68k/x-hp3bsd44
@@ -1,2 +1 @@
-CC=/usr/local/bin/gcc
-INSTALL_HEADERS=
+USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)
diff --git a/gnu/usr.bin/gcc/config/m68k/x-mot3300 b/gnu/usr.bin/gcc/config/m68k/x-mot3300
index 44d7e06fe9a..634540ff675 100644
--- a/gnu/usr.bin/gcc/config/m68k/x-mot3300
+++ b/gnu/usr.bin/gcc/config/m68k/x-mot3300
@@ -9,4 +9,6 @@ ALLOCA=alloca.o
# ld: relocation entry found for non-relocatable symbol in combine.o
# and the produced "cc1" fails with SIGSEGV
# Another possible fix would be to split combine.c.
-XCFLAGS=`if [ x$@ = xcombine.o ]; then echo -Wa,-j; fi`
+# Since ss-961013, the same happens for expr.c compiled by gcc, but not by cc;
+# and for cp/decl.c; aren't those files too big ?
+XCFLAGS=`case $@ in combine.o|expr.o|decl.o) echo -Wa,-j;;esac`
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-3b1.h b/gnu/usr.bin/gcc/config/m68k/xm-3b1.h
index 9d6ad5412a3..c966bc16309 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-3b1.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-3b1.h
@@ -2,12 +2,6 @@
#include "m68k/xm-m68k.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 index strchr
-#define rindex strrchr
-
/* Override part of the obstack macros. */
#define __PTR_TO_INT(P) ((int)(P))
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-altos3068.h b/gnu/usr.bin/gcc/config/m68k/xm-altos3068.h
index 294f5645b5e..f540924d328 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-altos3068.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-altos3068.h
@@ -1,7 +1,3 @@
#define USG
#include "m68k/xm-m68k.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/gnu/usr.bin/gcc/config/m68k/xm-amix.h b/gnu/usr.bin/gcc/config/m68k/xm-amix.h
index 69b4bd17c74..c28ed787cad 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-amix.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-amix.h
@@ -1,7 +1,6 @@
/* Definitions of host machine for GNU compiler.
Commodore Amiga A3000UX version.
-
- Copyright (C) 1991 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,7 +21,6 @@ Boston, MA 02111-1307, USA. */
#include "m68k/xm-m68kv.h" /* Use the System V flavor of m68k host */
-#define HAVE_VPRINTF /* Host has vprintf() in library */
#define rindex strrchr
#define index strchr
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-atari.h b/gnu/usr.bin/gcc/config/m68k/xm-atari.h
index a28a98606ef..323d89052c0 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-atari.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-atari.h
@@ -1,6 +1,6 @@
/* Definitions of host machine for GNU compiler.
Atari TT ASV version.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-crds.h b/gnu/usr.bin/gcc/config/m68k/xm-crds.h
index 3bd3461ce10..80925dc8714 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-crds.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-crds.h
@@ -6,13 +6,6 @@
#include "m68k/xm-m68k.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)
-
-/* UNOS has vprintf() */
-#define HAVE_VPRINTF
-
/* Avoid conflict with C library by changing name of this symbol. */
#define gettime gcc_gettime
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-hp320.h b/gnu/usr.bin/gcc/config/m68k/xm-hp320.h
index d724c3a26c8..f3009a6db5a 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-hp320.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-hp320.h
@@ -3,12 +3,6 @@
#include "m68k/xm-m68k.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 rindex strrchr
-#define index strchr
-
/* If compiling with HPUX compiler, we are probably using alloca.c,
so help it work right. */
#ifndef __GNUC__
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-linux.h b/gnu/usr.bin/gcc/config/m68k/xm-linux.h
index 3b1050673fa..bfac3ae4ef6 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-linux.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-linux.h
@@ -1,4 +1,4 @@
-/* Configuration for GCC for Motorola m68k running Linux. */
+/* Configuration for GCC for Motorola m68k running Linux-based GNU systems. */
#include <m68k/xm-m68k.h>
#include <xm-linux.h>
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-m68kv.h b/gnu/usr.bin/gcc/config/m68k/xm-m68kv.h
index ce3cf665e81..d0931f03890 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-m68kv.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-m68kv.h
@@ -3,12 +3,6 @@
#include "m68k/xm-m68k.h"
#define USG
-#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 rindex strrchr
-#define index strchr
#ifndef __GNUC__
#define USE_C_ALLOCA
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-mot3300.h b/gnu/usr.bin/gcc/config/m68k/xm-mot3300.h
index 627aabb4376..c61bd293e25 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-mot3300.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-mot3300.h
@@ -1,6 +1,6 @@
/* Configuration for GNU C-compiler for Motorola 68000 family.
SysV68 Motorola 3300 Delta Series
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,26 +20,27 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define USG
+#define USG 1
#include "m68k/xm-m68k.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 rindex strrchr
-#define index strchr
-
#define NO_SYS_SIGLIST
/* do not use alloca from -lPW with cc, because function epilogues use %sp */
#ifndef __GNUC__
#define USE_C_ALLOCA
+#ifdef __STDC__
+extern void *alloca ();
+#else
extern char *alloca ();
#endif
+#endif
/* Override part of the obstack macros. */
#define __PTR_TO_INT(P) ((int)(P))
#define __INT_TO_PTR(P) ((char *)(P))
+
+/* We need POSIX/XOPEN symbols; otherwise make check will fail. */
+#define ADD_MISSING_POSIX 1
+#define ADD_MISSING_XOPEN 1
diff --git a/gnu/usr.bin/gcc/config/m68k/xm-plexus.h b/gnu/usr.bin/gcc/config/m68k/xm-plexus.h
index 6d191ceed26..fbc9a32846e 100644
--- a/gnu/usr.bin/gcc/config/m68k/xm-plexus.h
+++ b/gnu/usr.bin/gcc/config/m68k/xm-plexus.h
@@ -3,13 +3,6 @@
#include "m68k/xm-m68k.h"
#define USG
-#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 rindex strrchr
-#define index strchr
-
#ifndef __GNUC__
#define USE_C_ALLOCA
#endif
diff --git a/gnu/usr.bin/gcc/config/m88k/dgux.h b/gnu/usr.bin/gcc/config/m88k/dgux.h
index 6085dcd9f95..612cd5087f7 100644
--- a/gnu/usr.bin/gcc/config/m88k/dgux.h
+++ b/gnu/usr.bin/gcc/config/m88k/dgux.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Motorola m88100 running DG/UX.
- Copyright (C) 1988, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@mcc.com)
Currently maintained by (gcc@dg-rtp.dg.com)
@@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */
(TARGET_SVR4 ? DWARF_DEBUG : SDB_DEBUG)
#ifndef VERSION_INFO2
-#define VERSION_INFO2 "$Revision: 1.1.1.1 $"
+#define VERSION_INFO2 "$Revision: 1.1.1.2 $"
#endif
#ifndef NO_BUGS
#define AS_BUG_IMMEDIATE_LABEL
@@ -83,24 +83,13 @@ Boston, MA 02111-1307, USA. */
-traditional, or restricting include files to one specific source
target, specify full DG/UX features. */
#undef CPP_SPEC
-#define CPP_SPEC "%{!m88000:%{!m88100:%{m88110:-D__m88110__}}} \
- %{!m88000:%{!m88110:%{m88100:-D__m88100__}}} \
- %{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}} \
- %{msvr3:-D_M88KBCS_TARGET} %{!msvr3:-D_DGUX_TARGET}"
+#define CPP_SPEC "%(cpp_cpu) %{msvr3:-D_M88KBCS_TARGET} %{!msvr3:-D_DGUX_TARGET}"
/* Assembler support (-V, silicon filter, legends for mxdb). */
#undef ASM_SPEC
-#define ASM_SPEC "\
-%{V} %{v:%{!V:-V}} %{pipe:%{!.s: - }\
-%{!msvr3:%{!m88110:-KV3 }%{m88110:-KV04.00 }}}\
-%{g:\
-%{mno-legend:-Wc,off}\
-%{!mno-legend:-Wc,-fix-bb,-s\"%i\"\
-%{traditional:,-lc}%{!traditional:,-lansi-c}\
-%{mstandard:,-keep-std}\
-%{mkeep-coff:,-keep-coff}\
-%{mexternal-legend:,-external}\
-%{mocs-frame-position:,-ocs}}}"
+#define ASM_SPEC "%{pipe:%{!.s: - }\
+ %{!msvr3:%{!m88110:-KV3 }%{m88110:-KV04.00 }}}\
+ %(asm_cpu)"
/* Override svr4.h. */
#undef ASM_FINAL_SPEC
@@ -120,20 +109,61 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
#define LIB_SPEC "%{!msvr3:%{!shared:-lstaticdgc}} %{!shared:%{!symbolic:-lc}}"
#undef LINK_SPEC
-#define LINK_SPEC "%{z*} %{h*} %{V} %{v:%{!V:-V}} \
+#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}"
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt0.o%s} \
+#define STARTFILE_SPEC "%(startfile_default)"
+
+
+/* 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 }, \
+ { "asm_cpu", ASM_CPU_SPEC }, \
+ { "startfile_default", STARTFILE_DEFAULT_SPEC }, \
+ { "startfile_crtbegin", STARTFILE_CRTBEGIN_SPEC }
+
+/* Keep this left justified, no white space is allowed between
+ the arguments to the -Wc option */
+#define ASM_CPU_SPEC "\
+%{v:-V} \
+%{g:\
+%{mno-legend:-Wc,off}\
+%{!mno-legend:-Wc,-fix-bb,-s\"%i\"\
+%{traditional:,-lc}\
+%{!traditional:,-lansi-c}\
+%{mstandard:,-keep-std}\
+%{mexternal-legend:,-external}\
+%{mocs-frame-position:,-ocs}}}"
+
+#define CPP_CPU_SPEC "\
+ %{!m88000:%{!m88100:%{m88110:-D__m88110__}}} \
+ %{!m88000:%{!m88110:%{m88100:-D__m88100__}}} \
+ %{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}}"
+
+#define STARTFILE_DEFAULT_SPEC "\
+ %{!shared:%{!symbolic:%{pg:gcrt0.o%s} \
%{!pg:%{p:/lib/mcrt0.o}%{!p:/lib/crt0.o}} \
- %{msvr3:m88kdgux.ld%s bcscrtbegin.o%s} \
- %{!msvr3:crtbegin.o%s} \
+ %(startfile_crtbegin) \
%{svr4:%{ansi:/lib/values-Xc.o} \
%{!ansi:%{traditional:/lib/values-Xt.o} \
%{!traditional:/usr/lib/values-Xa.o}}}}}"
+#define STARTFILE_CRTBEGIN_SPEC "\
+ %{msvr3:m88kdgux.ld%s bcscrtbegin.o%s} \
+ %{!msvr3:crtbegin.o%s}"
+
#undef GPLUSPLUS_INCLUDE_DIR
#define GPLUSPLUS_INCLUDE_DIR "/usr/opt/g++/lib/g++-include"
diff --git a/gnu/usr.bin/gcc/config/m88k/dguxbcs.h b/gnu/usr.bin/gcc/config/m88k/dguxbcs.h
index 45f288bf76e..00ef9b3a289 100644
--- a/gnu/usr.bin/gcc/config/m88k/dguxbcs.h
+++ b/gnu/usr.bin/gcc/config/m88k/dguxbcs.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Motorola m88100 running DG/UX.
- Copyright (C) 1988, 89, 90, 91, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@mcc.com)
Currently maintained by (gcc@dg-rtp.dg.com)
@@ -36,36 +36,27 @@ Boston, MA 02111-1307, USA. */
/* Assembler support (-V, silicon filter, legends for mxdb). */
#undef ASM_SPEC
-#define ASM_SPEC "\
-%{V} %{v:%{!V:-V}} %{pipe:%{!.s: - }\
-%{msvr4:%{!m88110:-KV3 }%{m88110:-KV04.00 }}}\
-%{!mlegend:%{mstandard:-Wc,off}}\
-%{mlegend:-Wc,-fix-bb,-s\"%i\"\
-%{traditional:,-lc}%{!traditional:,-lansi-c}\
-%{mstandard:,-keep-std}\
-%{mkeep-coff:,-keep-coff}\
-%{mexternal-legend:,-external}\
-%{mocs-frame-position:,-ocs}}"
+#define ASM_SPEC "%{pipe:%{!.s: - }\
+ %{msvr4:%{!m88110:-KV3 }%{m88110:-KV04.00 }}}\
+ %(asm_cpu)"
/* If -m88100 is in effect, add -Dm88100; similarly for -m88110.
Here, the CPU_DEFAULT is assumed to be -m88000. If not -ansi,
-traditional, or restricting include files to one specific source
target, specify full DG/UX features. */
#undef CPP_SPEC
-#define CPP_SPEC "%{!m88000:%{!m88100:%{m88110:-D__m88110__}}} \
- %{!m88000:%{!m88110:%{m88100:-D__m88100__}}} \
- %{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}} \
+#define CPP_SPEC "%(cpp_cpu)
%{!msvr4:-D_M88KBCS_TARGET} %{msvr4:-D_DGUX_TARGET}"
/* Linker and library spec's.
-msvr3 is the default if -msvr4 is not specified. */
#undef LIB_SPEC
#define LIB_SPEC "%{msvr4:%{!shared:-lstaticdgc}} %{!shared:%{!symbolic:-lc}}"
+
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt0.o%s} \
- %{!pg:%{p:/lib/mcrt0.o}%{!p:/lib/crt0.o}} \
+#define STARTFILE_SPEC "%(startfile_default)"
+
+#undef STARTFILE_CRTBEGIN_SPEC
+#define STARTFILE_CRTBEGIN_SPEC "\
%{!msvr4:m88kdgux.ld%s bcscrtbegin.o%s} \
- %{msvr4:crtbegin.o%s} \
- %{svr4:%{ansi:/lib/values-Xc.o} \
- %{!ansi:%{traditional:/lib/values-Xt.o} \
- %{!traditional:/usr/lib/values-Xa.o}}}}}"
+ %{msvr4:crtbegin.o%s}"
diff --git a/gnu/usr.bin/gcc/config/m88k/dolph.h b/gnu/usr.bin/gcc/config/m88k/dolph.h
index 48c0378636a..bd772273d3f 100644
--- a/gnu/usr.bin/gcc/config/m88k/dolph.h
+++ b/gnu/usr.bin/gcc/config/m88k/dolph.h
@@ -1,7 +1,7 @@
/* Definitions of target machine for GNU compiler.
Motorola m88100 running the Dolphin UNIX System V/88 Release 3.2,
Version 3.8/7.83 and 3.6/5.86
- Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -41,14 +41,3 @@ Boston, MA 02111-1307, USA. */
#undef CPU_DEFAULT
#define CPU_DEFAULT MASK_88000
-
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 40)), FNADDR); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 36)), CXT); \
- emit_call_insn (gen_call( gen_rtx (MEM, SImode, \
- gen_rtx(SYMBOL_REF,Pmode, \
- "__enable_execute_stack")), \
- const0_rtx)); \
-}
diff --git a/gnu/usr.bin/gcc/config/m88k/luna.h b/gnu/usr.bin/gcc/config/m88k/luna.h
index 677afcdae56..ab6dbded109 100644
--- a/gnu/usr.bin/gcc/config/m88k/luna.h
+++ b/gnu/usr.bin/gcc/config/m88k/luna.h
@@ -1,7 +1,7 @@
/* Definitions of target machine for GNU compiler.
Motorola m88100 running Omron Luna/88k.
- Copyright (C) 1991 Free Software Foundation, Inc.
- Contributed by Jeffery Friedl (jfriedl@omron.co.jp)
+ Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+ Contributed by Jeffrey Friedl (jfriedl@omron.co.jp)
This file is part of GNU CC.
diff --git a/gnu/usr.bin/gcc/config/m88k/m88k-coff.h b/gnu/usr.bin/gcc/config/m88k/m88k-coff.h
index aac6c57d652..d32e1d97787 100644
--- a/gnu/usr.bin/gcc/config/m88k/m88k-coff.h
+++ b/gnu/usr.bin/gcc/config/m88k/m88k-coff.h
@@ -1,7 +1,7 @@
/* Definitions for "naked" Motorola 88k using coff object format files
and coff debugging info.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -25,14 +25,10 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dm88000 -Dm88k -Acpu(m88k) -Amachine(m88k)"
-#undef DBX_DEBUGGING_INFO
#define SDB_DEBUGGING_INFO
/* Output DBX (stabs) debugging information if using -gstabs. */
-#define DBX_DEBUGGING_INFO
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
+#include "dbxcoff.h"
/* end of m88k-coff.h */
diff --git a/gnu/usr.bin/gcc/config/m88k/m88k.c b/gnu/usr.bin/gcc/config/m88k/m88k.c
index d1ce399c12a..7c2debe018e 100644
--- a/gnu/usr.bin/gcc/config/m88k/m88k.c
+++ b/gnu/usr.bin/gcc/config/m88k/m88k.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Motorola 88000.
- Copyright (C) 1988, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92, 93, 94, 95, 16, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@mcc.com)
Currently maintained by (gcc@dg-rtp.dg.com)
@@ -20,13 +20,13 @@ 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 <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
-#include "assert.h"
-#include "config.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -261,17 +261,17 @@ emit_move_sequence (operands, mode, scratch)
/* Simplify the source if we need to. */
if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
{
- if (GET_CODE (operand1) != CONST_INT
- && GET_CODE (operand1) != CONST_DOUBLE)
- {
- rtx temp = ((reload_in_progress || reload_completed)
- ? operand0 : 0);
- operands[1] = legitimize_address (flag_pic
- && symbolic_address_p (operand1),
- operand1, temp, scratch);
- if (mode != SImode)
- operands[1] = gen_rtx (SUBREG, mode, operands[1], 0);
- }
+ if (GET_CODE (operand1) != CONST_INT
+ && GET_CODE (operand1) != CONST_DOUBLE)
+ {
+ rtx temp = ((reload_in_progress || reload_completed)
+ ? operand0 : 0);
+ operands[1] = legitimize_address (flag_pic
+ && symbolic_address_p (operand1),
+ operand1, temp, scratch);
+ if (mode != SImode)
+ operands[1] = gen_rtx (SUBREG, mode, operands[1], 0);
+ }
}
/* Now have insn-emit do whatever it normally does. */
@@ -500,9 +500,10 @@ expand_block_move (dest_mem, src_mem, operands)
int bytes = (constp ? INTVAL (operands[2]) : 0);
int target = (int) m88k_cpu;
- assert (PROCESSOR_M88100 == 0);
- assert (PROCESSOR_M88110 == 1);
- assert (PROCESSOR_M88000 == 2);
+ if (! (PROCESSOR_M88100 == 0
+ && PROCESSOR_M88110 == 1
+ && PROCESSOR_M88000 == 2))
+ abort ();
if (constp && bytes <= 0)
return;
@@ -532,13 +533,18 @@ expand_block_move (dest_mem, src_mem, operands)
VOIDmode, 3,
operands[0], Pmode,
operands[1], Pmode,
- operands[2], SImode);
+ convert_to_mode (TYPE_MODE (sizetype), operands[2],
+ TREE_UNSIGNED (sizetype)),
+ TYPE_MODE (sizetype));
#else
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"), 0,
VOIDmode, 3,
operands[1], Pmode,
operands[0], Pmode,
- operands[2], SImode);
+ convert_to_mode (TYPE_MODE (integer_type_node),
+ operands[2],
+ TREE_UNSIGNED (integer_type_node)),
+ TYPE_MODE (integer_type_node));
#endif
}
}
@@ -1570,10 +1576,6 @@ output_file_start (file, f_options, f_len, W_options, W_len)
data_section ();
ASM_COFFSEM (file);
- 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");
-
if (TARGET_IDENTIFY_REVISION)
{
char indent[256];
@@ -1582,8 +1584,17 @@ output_file_start (file, f_options, f_len, W_options, W_len)
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));
+#if 1
+ /* ??? It would be nice to call print_switch_values here (and thereby
+ let us delete output_options) but this is kept in until it is known
+ whether the change in content format matters. */
output_options (file, f_options, f_len, W_options, W_len,
pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
+#else
+ fprintf (file, "]\"\n");
+ print_switch_values (file, 0, 150 - strlen (indent),
+ indent + 3, " ", "]\"\n");
+#endif
}
}
@@ -1630,7 +1641,7 @@ output_ascii (file, opcode, max, p, size)
fprintf (file, "\\%03o", c);
num += 4;
}
- else if (c >= ' ' && c < 0177)
+ else if ((c >= ' ' && c < 0177) || (c == '\t'))
{
putc (c, file);
num++;
@@ -1641,7 +1652,6 @@ output_ascii (file, opcode, max, p, size)
switch (c)
{
/* Some assemblers can't handle \a, \v, or \?. */
- case '\t': c = 't'; goto escape;
case '\f': c = 'f'; goto escape;
case '\b': c = 'b'; goto escape;
case '\r': c = 'r'; goto escape;
@@ -1928,6 +1938,9 @@ m88k_begin_prologue (stream, size)
FILE *stream;
int size;
{
+ if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
+ fprintf (stderr, "$");
+
m88k_prologue_done = 1; /* it's ok now to put out ln directives */
}
@@ -2036,6 +2049,17 @@ m88k_end_epilogue (stream, size)
if (insn == 0 || GET_CODE (insn) != BARRIER)
fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
+ /* If the last insn is a barrier, and the insn before that is a call,
+ then add a nop instruction so that tdesc can walk the stack correctly
+ even though there is no epilogue. (Otherwise, the label for the
+ end of the tdesc region ends up at the start of the next function. */
+ if (insn && GET_CODE (insn) == BARRIER)
+ {
+ insn = prev_nonnote_insn (insn);
+ if (insn && GET_CODE (insn) == CALL_INSN)
+ fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
+ }
+
output_short_branch_defs (stream);
fprintf (stream, "\n");
@@ -2471,12 +2495,12 @@ output_block_profiler (file, blockno)
/* @@ Need to deal with PIC. I'm not sure what the requirements are on
register usage, so I used r26/r27 to be safe. */
fprintf (file, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names[27], reg_names[0],
- m88k_pound_sign, &block[1], 4 * blockno);
+ m88k_pound_sign, &block[1], 4 * blockno);
fprintf (file, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
- m88k_pound_sign, &block[1], 4 * blockno);
+ m88k_pound_sign, &block[1], 4 * blockno);
fprintf (file, "\taddu\t %s,%s,1\n", reg_names[26], reg_names[26]);
fprintf (file, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names[26], reg_names[27],
- m88k_pound_sign, &block[1], 4 * blockno);
+ m88k_pound_sign, &block[1], 4 * blockno);
}
/* Determine whether a function argument is passed in a register, and
@@ -2562,7 +2586,7 @@ struct rtx_def *
m88k_builtin_saveregs (arglist)
tree arglist;
{
- rtx block, addr, argsize;
+ rtx block, addr, argsize, dest;
tree fntype = TREE_TYPE (current_function_decl);
int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
@@ -2587,6 +2611,7 @@ m88k_builtin_saveregs (arglist)
/* Allocate the va_list constructor */
block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
+ MEM_IN_STRUCT_P (block) = 1;
RTX_UNCHANGING_P (block) = 1;
RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
@@ -2612,12 +2637,29 @@ m88k_builtin_saveregs (arglist)
/* Now store the incoming registers. */
if (fixed < 8)
- move_block_from_reg
- (2 + fixed,
- change_address (addr, Pmode,
- plus_constant (XEXP (addr, 0),
- fixed * UNITS_PER_WORD)),
- 8 - fixed, UNITS_PER_WORD * (8 - fixed));
+ {
+ dest = change_address (addr, Pmode,
+ plus_constant (XEXP (addr, 0),
+ fixed * UNITS_PER_WORD));
+ move_block_from_reg (2 + fixed, dest, 8 - fixed,
+ UNITS_PER_WORD * (8 - fixed));
+ }
+
+ if (flag_check_memory_usage)
+ {
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ block, ptr_mode,
+ GEN_INT (3 * UNITS_PER_WORD), TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+ if (fixed < 8)
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ dest, ptr_mode,
+ GEN_INT (UNITS_PER_WORD * (8 - fixed)),
+ 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. This fails when not optimizing and produces worse code when
diff --git a/gnu/usr.bin/gcc/config/m88k/m88k.h b/gnu/usr.bin/gcc/config/m88k/m88k.h
index 0e49a0e2cee..fe8895be18e 100644
--- a/gnu/usr.bin/gcc/config/m88k/m88k.h
+++ b/gnu/usr.bin/gcc/config/m88k/m88k.h
@@ -1,9 +1,8 @@
/* Definitions of target machine for GNU compiler for
Motorola m88100 in an 88open OCS/BCS environment.
- Copyright (C) 1988, 89, 90, 91, 93, 94, 1995 Free Software Foundation, Inc.
- Contributed by Michael Tiemann (tiemann@cygnus.com)
- Enhanced by Michael Meissner (meissner@cygnus.com)
- Version 2 port by Tom Wood (twood@pets.sps.mot.com)
+ Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@cygnus.com).
+ Currently maintained by (gcc@dg-rtp.dg.com)
This file is part of GNU CC.
@@ -197,15 +196,15 @@ extern char * reg_names[];
/* Print subsidiary information on the compiler version in use.
Redefined in sysv4.h, and luna.h. */
-#define VERSION_INFO1 "88open OCS/BCS, "
+#define VERSION_INFO1 "m88k, "
#ifndef VERSION_INFO2
-#define VERSION_INFO2 "$Revision: 1.1.1.1 $"
+#define VERSION_INFO2 "$Revision: 1.1.1.2 $"
#endif
#ifndef VERSION_STRING
#define VERSION_STRING version_string
#ifdef __STDC__
-#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.1.1.1 $ " __DATE__
+#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.1.1.2 $ " __DATE__
#else
#define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $"
#endif /* __STDC__ */
@@ -295,6 +294,7 @@ extern char * reg_names[];
{ "no-serialize-volatile", MASK_NO_SERIALIZE_VOLATILE }, \
{ "serialize-volatile", -MASK_NO_SERIALIZE_VOLATILE }, \
{ "omit-leaf-frame-pointer", MASK_OMIT_LEAF_FRAME_POINTER }, \
+ { "no-omit-leaf-frame-pointer", -MASK_OMIT_LEAF_FRAME_POINTER }, \
SUBTARGET_SWITCHES \
/* Default switches */ \
{ "", TARGET_DEFAULT }, \
@@ -361,6 +361,8 @@ extern char * reg_names[];
if (flag_pic) \
error ("-mshort-data-%s and PIC are incompatible", m88k_short_data); \
} \
+ if (TARGET_OMIT_LEAF_FRAME_POINTER) /* keep nonleaf frame pointers */ \
+ flag_omit_frame_pointer = 1; \
} while (0)
/*** Storage Layout ***/
@@ -1046,7 +1048,7 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
/* 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. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) ((CUM) = 0)
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) ((CUM) = 0)
/* A C statement (sans semicolon) to update the summarizer variable
CUM to advance past an argument in the argument list. The values
@@ -1545,6 +1547,7 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
/* Tell when to handle #pragma weak. This is only done for V.4. */
#define SUPPORTS_WEAK TARGET_SVR4
+#define SUPPORTS_ONE_ONLY TARGET_SVR4
/* Max number of bytes we can move from memory to memory
in one reasonably fast instruction. */
@@ -1706,10 +1709,6 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
(COST) -= 4; /* 88110 store reservation station. */ \
} while (0)
-/* Define this to be nonzero if the character `$' should be allowed
- by default in identifier names. */
-#define DOLLARS_IN_IDENTIFIERS 1
-
/* Do not break .stabs pseudos into continuations. */
#define DBX_CONTIN_LENGTH 0
@@ -1717,12 +1716,18 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
/* Control the assembler format that we output. */
+/* 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 ";"
+
/* Allow pseudo-ops to be overridden. Override these in svr[34].h. */
#undef INT_ASM_OP
#undef ASCII_DATA_ASM_OP
#undef CONST_SECTION_ASM_OP
#undef CTORS_SECTION_ASM_OP
#undef DTORS_SECTION_ASM_OP
+#undef ASM_OUTPUT_SECTION_NAME
#undef INIT_SECTION_ASM_OP
#undef FINI_SECTION_ASM_OP
#undef TYPE_ASM_OP
@@ -2030,6 +2035,11 @@ do { \
putc ('\n', FILE); \
} while (0)
+/* The prefix to add to user-visible assembler symbols.
+ Override svr[34].h. */
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX "_"
+
/* This is how to output a reference to a user-level label named NAME.
Override svr[34].h. */
#undef ASM_OUTPUT_LABELREF
diff --git a/gnu/usr.bin/gcc/config/m88k/m88k.md b/gnu/usr.bin/gcc/config/m88k/m88k.md
index 188e6cc075d..bf5124b2244 100644
--- a/gnu/usr.bin/gcc/config/m88k/m88k.md
+++ b/gnu/usr.bin/gcc/config/m88k/m88k.md
@@ -1,8 +1,7 @@
;;- Machine description for the Motorola 88000 for GNU C compiler
-;; Copyright (C) 1988, 92, 93, 94, 1995 Free Software Foundation, Inc.
+;;; Copyright (C) 1988, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@mcc.com)
-;; Additional changes by Michael Meissner (meissner@osf.org)
-;; Version 2 port by Tom Wood (twood@pets.sps.mot.com)
+;; Currently maintained by (gcc@dg-rtp.dg.com)
;; This file is part of GNU CC.
@@ -2729,14 +2728,13 @@
"mul %0,%1,%2"
[(set_attr "type" "imul")])
-;; Loses for acvs/P60504.c (mod case) on 88110
-;; (define_insn "umulsidi3"
-;; [(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_88110"
-;; "mulu.d %0,%1,%2"
-;; [(set_attr "type" "imul")])
+(define_insn "umulsidi3"
+ [(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_88110"
+ "mulu.d %0,%1,%2"
+ [(set_attr "type" "imul")])
;; patterns for mixed mode floating point
;; Do not define patterns that utilize mixed mode arithmetic that result
@@ -3995,7 +3993,23 @@
;; reloads, hence the `m' constraints. The `!' constraints direct reload
;; to not choose the register alternatives in the event a reload is needed.
-(define_insn "decrement_and_branch_until_zero"
+(define_expand "decrement_and_branch_until_zero"
+ [(parallel [(set (pc)
+ (if_then_else
+ (match_operator 0 "relop_no_unsigned"
+ [(match_operand:SI 1 "register_operand" "")
+ (const_int 0)])
+ (label_ref (match_operand 2 "" ""))
+ (pc)))
+ (set (match_dup 1)
+ (plus:SI (match_dup 1)
+ (match_operand:SI 3 "add_operand" "")))
+ (clobber (match_scratch:SI 4 ""))
+ (clobber (match_scratch:SI 5 "=X,X,&r,&r"))])]
+ ""
+ "")
+
+(define_insn ""
[(set (pc)
(if_then_else
(match_operator 0 "relop_no_unsigned"
diff --git a/gnu/usr.bin/gcc/config/m88k/sysv3.h b/gnu/usr.bin/gcc/config/m88k/sysv3.h
index 62fe8973d4f..ef351897398 100644
--- a/gnu/usr.bin/gcc/config/m88k/sysv3.h
+++ b/gnu/usr.bin/gcc/config/m88k/sysv3.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Motorola m88100 running the AT&T/Unisoft/Motorola V.3 reference port.
- Copyright (C) 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1997 Free Software Foundation, Inc.
Contributed by Ray Essick (ressick@mot.com)
Enhanced by Tom Wood (Tom_Wood@NeXT.com)
@@ -137,3 +137,14 @@ do { \
if (((int *)__DTOR_LIST__)[i] != -1) \
__DTOR_LIST__[i] (); \
} while (0)
+
+#undef INITIALIZE_TRAMPOLINE
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
+{ \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 40)), FNADDR); \
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 36)), CXT); \
+ emit_call_insn (gen_call (gen_rtx (MEM, SImode, \
+ gen_rtx (SYMBOL_REF, Pmode, \
+ "__enable_execute_stack")), \
+ const0_rtx)); \
+}
diff --git a/gnu/usr.bin/gcc/config/m88k/t-dgux b/gnu/usr.bin/gcc/config/m88k/t-dgux
index 594d9a00be9..cced6b1eca2 100644
--- a/gnu/usr.bin/gcc/config/m88k/t-dgux
+++ b/gnu/usr.bin/gcc/config/m88k/t-dgux
@@ -21,3 +21,6 @@ bcscrtbegin.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) -DCRT_BEGIN -DBCS \
-finhibit-size-directive -fno-inline-functions \
-g0 -c $(srcdir)/crtstuff.c -o bcscrtbegin.o
+
+# Build libgcc.a, crtbegin.o, and crtend.o as bcs objects
+GCC_FOR_TARGET = PATH=/usr/sde/m88kbcs/usr/bin/:/usr/bin TARGET_BINARY_INTERFACE=m88kbcs ./xgcc -B./ -msvr3 -D_M88KBCS_TARGET -mno-ocs-debug-info
diff --git a/gnu/usr.bin/gcc/config/m88k/x-dgux b/gnu/usr.bin/gcc/config/m88k/x-dgux
index 6636711c892..f2c55a7d79e 100644
--- a/gnu/usr.bin/gcc/config/m88k/x-dgux
+++ b/gnu/usr.bin/gcc/config/m88k/x-dgux
@@ -1,8 +1,6 @@
-CC = /bin/gcc
-# Build libgcc.a, crtbegin.o, and crtend.o as bcs objects
-GCC_FOR_TARGET = PATH=/usr/sde/m88kbcs/usr/bin/:/usr/bin TARGET_BINARY_INTERFACE=m88kbcs ./xgcc -B./ -msvr3 -D_M88KBCS_TARGET -mno-ocs-debug-info
+CC = gcc
BISONFLAGS = -l
-X_CFLAGS = -O -mstandard -mlegend
-INSTALL_HEADERS =
-STMP_FIXPROTO =
+USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)
+STMP_FIXPROTO =
+X_CFLAGS = -O -mstandard -mlegend
diff --git a/gnu/usr.bin/gcc/config/m88k/x-dguxbcs b/gnu/usr.bin/gcc/config/m88k/x-dguxbcs
index e49dbcf312c..8baf0caaf3f 100644
--- a/gnu/usr.bin/gcc/config/m88k/x-dguxbcs
+++ b/gnu/usr.bin/gcc/config/m88k/x-dguxbcs
@@ -1,8 +1,4 @@
-CC = /bin/gcc
-# Build libgcc.a, crtbegin.o, and crtend.o as bcs objects
-GCC_FOR_TARGET = PATH=/usr/sde/m88kbcs/usr/bin/:/usr/bin TARGET_BINARY_INTERFACE=m88kbcs ./xgcc -B./ -msvr3 -D_M88KBCS_TARGET
+CC = gcc
BISONFLAGS = -l
-X_CFLAGS = -D_M88KBCS_TARGET
-INSTALL_HEADERS =
+USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)
STMP_FIXPROTO =
-
diff --git a/gnu/usr.bin/gcc/config/m88k/xm-m88k.h b/gnu/usr.bin/gcc/config/m88k/xm-m88k.h
index 8691f865643..b330f5980fc 100644
--- a/gnu/usr.bin/gcc/config/m88k/xm-m88k.h
+++ b/gnu/usr.bin/gcc/config/m88k/xm-m88k.h
@@ -1,6 +1,6 @@
/* Configuration for GNU compiler.
Motorola m88100 in an 88open OCS/BCS environment.
- Copyright (C) 1988, 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1988, 89, 90, 91, 93, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -37,24 +37,15 @@ Boston, MA 02111-1307, USA. */
#define SUCCESS_EXIT_CODE 0
#define FATAL_EXIT_CODE 33
-/* Use System V memory functions. */
-#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 rindex strrchr
-#define index strchr
-
/* The 88open BCS (and ABI) environment doesn't support BSD features
(vfork, getrusage), so use USG. The Omron Luna/88k is BSD though. */
#ifndef luna88k
+#ifndef USG
#define USG
+#endif
#define NO_SYS_SIGLIST
#endif
-/* Define HAVE_VPRINTF if it is available on host system. */
-#define HAVE_VPRINTF
-
/* If not compiled with GNU C, use the C alloca */
#ifndef __GNUC__
#define USE_C_ALLOCA
diff --git a/gnu/usr.bin/gcc/config/m88k/xm-sysv3.h b/gnu/usr.bin/gcc/config/m88k/xm-sysv3.h
index 05d3e4cf4d4..3e8ab39dc95 100644
--- a/gnu/usr.bin/gcc/config/m88k/xm-sysv3.h
+++ b/gnu/usr.bin/gcc/config/m88k/xm-sysv3.h
@@ -1,6 +1,6 @@
/* Configuration for GNU C-compiler.
Motorola m88100 running the AT&T/Unisoft/Motorola V.3 reference port.
- Copyright (C) 1990 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -28,3 +28,7 @@ Boston, MA 02111-1307, USA. */
/* for the emacs version of alloca */
#define STACK_DIRECTION -1
+
+/* We need POSIX/XOPEN symbols; otherwise make check will fail. */
+#define ADD_MISSING_POSIX 1
+#define ADD_MISSING_XOPEN 1
diff --git a/gnu/usr.bin/gcc/config/mips/abi64.h b/gnu/usr.bin/gcc/config/mips/abi64.h
index fc98a304d6a..a3e768cdc2d 100644
--- a/gnu/usr.bin/gcc/config/mips/abi64.h
+++ b/gnu/usr.bin/gcc/config/mips/abi64.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. 64 bit ABI support.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -21,91 +21,58 @@ Boston, MA 02111-1307, USA. */
/* Macros to implement the 64 bit ABI. This file is meant to be included
after mips.h. */
-#undef ABI_64BIT
-#define ABI_64BIT 1
-
-/* For Irix 6, -mips3 implies TARGET_LONG64. */
-#undef TARGET_LONG64
-#define TARGET_LONG64 (target_flags & MASK_64BIT)
-
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES \
- "-Dunix -Dmips -Dsgi -Dhost_mips -DMIPSEB -D_MIPSEB -DSYSTYPE_SVR4 \
- -D_SVR4_SOURCE -D_MODERN_C -D__DSO__ \
- -Asystem(unix) -Asystem(svr4) -Acpu(mips) -Amachine(sgi)"
-
-/* We must make -mips3 do what -mlong64 used to do. */
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{!ansi:-D__EXTENSIONS__ -D_SGI_SOURCE -D_LONGLONG} \
-%{.cc: -D_LANGUAGE_C_PLUS_PLUS} \
-%{.cxx: -D_LANGUAGE_C_PLUS_PLUS} \
-%{.C: -D_LANGUAGE_C_PLUS_PLUS} \
-%{.m: -D_LANGUAGE_OBJECTIVE_C -D_LANGUAGE_C} \
-%{.S: -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.s: -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{!.S:%{!.s: %{!.cc: %{!.cxx: %{!.C: %{!.m: -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}}}}}}\
-%{mfp32: -D_MIPS_FPSET=16}%{!mfp32: -D_MIPS_FPSET=32} \
-%{mips1: -D_MIPS_ISA=_MIPS_ISA_MIPS1} \
-%{mips2: -D_MIPS_ISA=_MIPS_ISA_MIPS2} \
-%{mips3: -D_MIPS_ISA=_MIPS_ISA_MIPS3} \
-%{mips4: -D_MIPS_ISA=_MIPS_ISA_MIPS4} \
-%{!mips1: %{!mips2: %{!mips3: %{!mips4: -D_MIPS_ISA=_MIPS_ISA_MIPS4}}}} \
-%{mips1: -D_MIPS_SIM=_MIPS_SIM_ABI32} \
-%{mips2: -D_MIPS_SIM=_MIPS_SIM_ABI32} \
-%{mips3: -D_ABI64=3 -D_MIPS_SIM=_ABI64} \
-%{mips4: -D_ABI64=3 -D_MIPS_SIM=_ABI64} \
-%{!mips1: %{!mips2: %{!mips3: %{!mips4: -D_ABI64=3 -D_MIPS_SIM=_ABI64}}}} \
-%{!mint64: -D_MIPS_SZINT=32}%{mint64: -D_MIPS_SZINT=64} \
-%{mips1: -D_MIPS_SZLONG=32}%{mips2: -D_MIPS_SZLONG=32} \
-%{!mips1:%{!mips2: -D_MIPS_SZLONG=64}} \
-%{mips1: -D_MIPS_SZPTR=32}%{mips2: -D_MIPS_SZPTR=32} \
-%{mips3: -D_MIPS_SZPTR=64}%{mips4: -D_MIPS_SZPTR=64} \
-%{!mips1: %{!mips2: %{!mips3: %{!mips4: -D_MIPS_SZPTR=64}}}} \
-%{!mips1:%{!mips2: -D_COMPILER_VERSION=601}} \
-%{mips1: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{mips2: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{!mips1:%{!mips2: -D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int}} \
-%{mips3:-U__mips -D__mips=3 -D__mips64} \
-%{!mips1:%{!mips2:-U__mips -D__mips=4 -D__mips64}} \
-%{mgp32:-U__mips64} %{mgp64:-D__mips64} \
-%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
-
-#undef EMPTY_FIELD_BOUNDARY
-#define EMPTY_FIELD_BOUNDARY 32
+#undef SUBTARGET_TARGET_OPTIONS
+#define SUBTARGET_TARGET_OPTIONS\
+ { "abi=", &mips_abi_string },
#undef STACK_BOUNDARY
-#define STACK_BOUNDARY 128
+#define STACK_BOUNDARY \
+ ((mips_abi == ABI_32 || mips_abi == ABI_EABI) ? 64 : 128)
#undef MIPS_STACK_ALIGN
-#define MIPS_STACK_ALIGN(LOC) (((LOC)+15) & ~15)
+#define MIPS_STACK_ALIGN(LOC) \
+ ((mips_abi == ABI_32 || mips_abi == ABI_EABI) \
+ ? ((LOC) + 7) & ~7 \
+ : ((LOC) + 15) & ~15)
#undef GP_ARG_LAST
-#define GP_ARG_LAST (mips_isa < 3 ? GP_REG_FIRST + 7 : GP_REG_FIRST + 11)
+#define GP_ARG_LAST (mips_abi == ABI_32 ? GP_REG_FIRST + 7 : GP_REG_FIRST + 11)
#undef FP_ARG_LAST
-#define FP_ARG_LAST (mips_isa < 3 ? FP_REG_FIRST + 15 : FP_REG_FIRST + 19)
+#define FP_ARG_LAST (mips_abi == ABI_32 ? FP_REG_FIRST + 15 : FP_REG_FIRST + 19)
-/* fp20-23 are now caller saved. */
#undef SUBTARGET_CONDITIONAL_REGISTER_USAGE
#define SUBTARGET_CONDITIONAL_REGISTER_USAGE \
{ \
- if (mips_isa >= 3) \
+ /* fp20-23 are now caller saved. */ \
+ if (mips_abi == ABI_64) \
{ \
int regno; \
for (regno = FP_REG_FIRST + 20; regno < FP_REG_FIRST + 24; regno++) \
call_used_regs[regno] = 1; \
} \
+ /* odd registers from fp21 to fp31 are now caller saved. */ \
+ if (mips_abi == ABI_N32) \
+ { \
+ int regno; \
+ for (regno = FP_REG_FIRST + 21; regno <= FP_REG_FIRST + 31; regno+=2) \
+ call_used_regs[regno] = 1; \
+ } \
}
#undef MAX_ARGS_IN_REGISTERS
-#define MAX_ARGS_IN_REGISTERS (mips_isa < 3 ? 4 : 8)
+#define MAX_ARGS_IN_REGISTERS (mips_abi == ABI_32 ? 4 : 8)
#undef REG_PARM_STACK_SPACE
-#define REG_PARM_STACK_SPARC(FNDECL) \
- (mips_abi < 3 \
+#if 0
+/* ??? This is necessary in order for the ABI_32 support to work. However,
+ expr.c (emit_push_insn) has no support for a REG_PARM_STACK_SPACE
+ definition that returns zero. That would have to be fixed before this
+ can be enabled. */
+#define REG_PARM_STACK_SPACE(FNDECL) \
+ (mips_abi == ABI_32 \
? (MAX_ARGS_IN_REGISTERS*UNITS_PER_WORD) - FIRST_PARM_OFFSET (FNDECL) \
: 0)
+#endif
#define FUNCTION_ARG_PADDING(MODE, TYPE) \
(! BYTES_BIG_ENDIAN \
@@ -114,16 +81,16 @@ Boston, MA 02111-1307, USA. */
? ((TYPE) && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \
&& int_size_in_bytes (TYPE) < (PARM_BOUNDARY / BITS_PER_UNIT))\
: (GET_MODE_BITSIZE (MODE) < PARM_BOUNDARY \
- && (mips_isa < 3 || GET_MODE_CLASS (MODE) == MODE_INT))) \
+ && (mips_abi == ABI_32 || mips_abi == ABI_EABI \
+ || GET_MODE_CLASS (MODE) == MODE_INT))) \
? downward : upward))
-extern struct rtx_def *type_dependent_reg ();
-#define TYPE_DEPENDENT_REG(REGNO, INDEX, TYPE) \
- type_dependent_reg (REGNO, INDEX, TYPE)
-
#undef RETURN_IN_MEMORY
-#define RETURN_IN_MEMORY(TYPE) \
- (mips_isa < 3 ? TYPE_MODE (TYPE) == BLKmode : int_size_in_bytes (TYPE) > 16)
+#define RETURN_IN_MEMORY(TYPE) \
+ (mips_abi == ABI_32 \
+ ? TYPE_MODE (TYPE) == BLKmode \
+ : (int_size_in_bytes (TYPE) \
+ > (mips_abi == ABI_EABI ? 2 * UNITS_PER_WORD : 16)))
extern struct rtx_def *mips_function_value ();
#undef FUNCTION_VALUE
@@ -134,39 +101,125 @@ extern struct rtx_def *mips_function_value ();
For stdarg, we do not need to save the current argument, because it
is a real argument. */
#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
-{ if (mips_isa >= 3 \
- && ((CUM).arg_words \
- < (MAX_ARGS_IN_REGISTERS - ! current_function_varargs))) \
+{ int mips_off = (! current_function_varargs) && (! (CUM).last_arg_fp); \
+ int mips_fp_off = (! current_function_varargs) && ((CUM).last_arg_fp); \
+ if ((mips_abi != ABI_32 \
+ && (CUM).arg_words < MAX_ARGS_IN_REGISTERS - mips_off) \
+ || (mips_abi == ABI_EABI \
+ && ! TARGET_SOFT_FLOAT \
+ && (CUM).fp_arg_words < MAX_ARGS_IN_REGISTERS - mips_fp_off)) \
{ \
- PRETEND_SIZE \
- = (MAX_ARGS_IN_REGISTERS - (CUM).arg_words \
- - ! current_function_varargs) * UNITS_PER_WORD; \
+ int mips_save_gp_regs = \
+ MAX_ARGS_IN_REGISTERS - (CUM).arg_words - mips_off; \
+ int mips_save_fp_regs = \
+ (mips_abi != ABI_EABI ? 0 \
+ : MAX_ARGS_IN_REGISTERS - (CUM).fp_arg_words - mips_fp_off); \
+ \
+ if (mips_save_gp_regs < 0) \
+ mips_save_gp_regs = 0; \
+ if (mips_save_fp_regs < 0) \
+ mips_save_fp_regs = 0; \
+ PRETEND_SIZE = ((mips_save_gp_regs * UNITS_PER_WORD) \
+ + (mips_save_fp_regs * UNITS_PER_FPREG)); \
\
if (! (NO_RTL)) \
{ \
- rtx mem = gen_rtx (MEM, BLKmode, virtual_incoming_args_rtx); \
- /* va_arg is an array access in this case, which causes it to \
- get MEM_IN_STRUCT_P set. We must set it here so that the \
- insn scheduler won't assume that these stores can't \
- possibly overlap with the va_arg loads. */ \
- if (BYTES_BIG_ENDIAN) \
- MEM_IN_STRUCT_P (mem) = 1; \
- move_block_from_reg \
- ((CUM).arg_words + GP_ARG_FIRST + ! current_function_varargs, \
- mem, \
- (MAX_ARGS_IN_REGISTERS - (CUM).arg_words \
- - ! current_function_varargs), \
- PRETEND_SIZE); \
+ if ((CUM).arg_words < MAX_ARGS_IN_REGISTERS - mips_off) \
+ { \
+ rtx ptr, mem; \
+ if (mips_abi != ABI_EABI) \
+ ptr = virtual_incoming_args_rtx; \
+ else \
+ ptr = plus_constant (virtual_incoming_args_rtx, \
+ - (mips_save_gp_regs \
+ * UNITS_PER_WORD)); \
+ mem = gen_rtx (MEM, BLKmode, ptr); \
+ /* va_arg is an array access in this case, which causes \
+ it to get MEM_IN_STRUCT_P set. We must set it here \
+ so that the insn scheduler won't assume that these \
+ stores can't possibly overlap with the va_arg loads. */ \
+ if (mips_abi != ABI_EABI && BYTES_BIG_ENDIAN) \
+ MEM_IN_STRUCT_P (mem) = 1; \
+ move_block_from_reg \
+ ((CUM).arg_words + GP_ARG_FIRST + mips_off, \
+ mem, \
+ mips_save_gp_regs, \
+ mips_save_gp_regs * UNITS_PER_WORD); \
+ } \
+ if (mips_abi == ABI_EABI \
+ && ! TARGET_SOFT_FLOAT \
+ && (CUM).fp_arg_words < MAX_ARGS_IN_REGISTERS - mips_fp_off) \
+ { \
+ enum machine_mode mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode; \
+ int size = GET_MODE_SIZE (mode); \
+ int off; \
+ int i; \
+ /* We can't use move_block_from_reg, because it will use \
+ the wrong mode. */ \
+ off = - (mips_save_gp_regs * UNITS_PER_WORD); \
+ if (! TARGET_SINGLE_FLOAT) \
+ off &= ~ 7; \
+ if (! TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) \
+ off -= (mips_save_fp_regs / 2) * size; \
+ else \
+ off -= mips_save_fp_regs * size; \
+ for (i = 0; i < mips_save_fp_regs; i++) \
+ { \
+ rtx tem = \
+ gen_rtx (MEM, mode, \
+ plus_constant (virtual_incoming_args_rtx, \
+ off)); \
+ emit_move_insn (tem, \
+ gen_rtx (REG, mode, \
+ ((CUM).fp_arg_words \
+ + FP_ARG_FIRST \
+ + i \
+ + mips_fp_off))); \
+ off += size; \
+ if (! TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) \
+ ++i; \
+ } \
+ } \
} \
} \
}
+/* ??? Should disable for mips_abi == ABI32. */
#define STRICT_ARGUMENT_NAMING
+/* 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. */
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
+ (mips_abi == ABI_EABI \
+ && function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED))
+
+/* A C expression that indicates when it is the called function's
+ responsibility to make a copy of arguments passed by invisible
+ reference. Normally, the caller makes a copy and passes the
+ address of the copy to the routine being called. When
+ FUNCTION_ARG_CALLEE_COPIES is defined and is nonzero, the caller
+ does not make a copy. Instead, it passes a pointer to the "live"
+ value. The called function must not modify this value. If it can
+ be determined that the value won't be modified, it need not make a
+ copy; otherwise a copy must be made.
+
+ ??? The MIPS EABI says that the caller should copy in ``K&R mode.''
+ I don't know how to detect that here, since flag_traditional is not
+ a back end flag. */
+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
+ (mips_abi == ABI_EABI && (NAMED) \
+ && FUNCTION_ARG_PASS_BY_REFERENCE (CUM, MODE, TYPE, NAMED))
+
+#undef LONG_MAX_SPEC
+#define LONG_MAX_SPEC "%{!mno-long64:-D__LONG_MAX__=9223372036854775807LL}"
+
/* ??? Unimplemented stuff follows. */
/* ??? Add support for 16 byte/128 bit long doubles here when
- mips_isa >= 3. */
+ mips_abi != ABI32. */
/* ??? Make main return zero if user did not specify return value. */
@@ -177,3 +230,5 @@ extern struct rtx_def *mips_function_value ();
into the field decl, so that if we use the field, we can take the value from
a register instead of from memory. */
+
+
diff --git a/gnu/usr.bin/gcc/config/mips/dec-bsd.h b/gnu/usr.bin/gcc/config/mips/dec-bsd.h
index 4aef5dab194..126353b25dd 100644
--- a/gnu/usr.bin/gcc/config/mips/dec-bsd.h
+++ b/gnu/usr.bin/gcc/config/mips/dec-bsd.h
@@ -1,5 +1,5 @@
/* Definitions for DECstation running BSD as target machine for GNU compiler.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -27,36 +27,6 @@ Boston, MA 02111-1307, USA. */
-Asystem(unix) -Asystem(bsd) -Amachine(mips)"
#endif
-/* Always uses gas. */
-#ifndef ASM_SPEC
-#define ASM_SPEC "\
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC "\
-%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
-%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.s: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{!.S:%{!.s: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}} \
-%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{mips3:-U__mips -D__mips=3 -D__mips64} \
-%{mgp32:-U__mips64} %{mgp64:-D__mips64} \
-%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
-#endif
-
/* Always uses GNU ld. */
#ifndef LINK_SPEC
#define LINK_SPEC "%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3}"
diff --git a/gnu/usr.bin/gcc/config/mips/dec-osf1.h b/gnu/usr.bin/gcc/config/mips/dec-osf1.h
index 955add7557a..cc0e7e15a0a 100644
--- a/gnu/usr.bin/gcc/config/mips/dec-osf1.h
+++ b/gnu/usr.bin/gcc/config/mips/dec-osf1.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. DECstation (OSF/1) version.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -42,19 +42,10 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE "short unsigned int"
#define WCHAR_TYPE_SIZE SHORT_TYPE_SIZE
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.s: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
-%{!.S:%{!.s: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}} \
+#undef SUBTARGET_CPP_SIZE_SPEC
+#define SUBTARGET_CPP_SIZE_SPEC "\
%{mlong64:-D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__PTRDIFF_TYPE__=int} \
-%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
+%{!mlong64:-D__PTRDIFF_TYPE__=int}"
/* turn off collect2 COFF support, since ldfcn now has elf declaration */
#undef OBJECT_FORMAT_COFF
diff --git a/gnu/usr.bin/gcc/config/mips/elf.h b/gnu/usr.bin/gcc/config/mips/elf.h
index 9a85ae3f82c..51ca470dfa3 100644
--- a/gnu/usr.bin/gcc/config/mips/elf.h
+++ b/gnu/usr.bin/gcc/config/mips/elf.h
@@ -24,7 +24,9 @@ Boston, MA 02111-1307, USA. */
/* Until we figure out what MIPS ELF targets normally use, just do
stabs in ELF. */
+#ifndef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#endif
/* Mostly like ECOFF. */
#include "mips/ecoff.h"
@@ -44,3 +46,10 @@ do { \
extern FILE *asm_out_text_file; \
fprintf (asm_out_text_file, "\t.etype\t0x%x;", (a)); \
} 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)
diff --git a/gnu/usr.bin/gcc/config/mips/elf64.h b/gnu/usr.bin/gcc/config/mips/elf64.h
index ab5aee99a84..3d1a91bba8f 100644
--- a/gnu/usr.bin/gcc/config/mips/elf64.h
+++ b/gnu/usr.bin/gcc/config/mips/elf64.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. MIPS R4000 version with
GOFAST floating point library.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -25,11 +25,13 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT MASK_FLOAT64|MASK_64BIT
#define MIPS_ISA_DEFAULT 3
+#ifndef MULTILIB_DEFAULTS
#ifndef TARGET_ENDIAN_DEFAULT
#define MULTILIB_DEFAULTS { "EB", "mips3" }
#else
#define MULTILIB_DEFAULTS { "EL", "mips3" }
#endif
+#endif
/* Until we figure out what MIPS ELF targets normally use, just do
stabs in ELF. */
@@ -40,24 +42,11 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dmips -DMIPSEB -DR4000 -D_mips -D_MIPSEB -D_R4000"
-/* This is the same as the one in mips64.h except that it defines __mips=3
- at the end. I would rather put this in CPP_PREDEFINES, but the gcc
- driver doesn't handle -U options in CPP_PREDEFINES. */
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{.cc: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
-%{.cxx: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
-%{.C: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
-%{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C} \
-%{.S: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.s: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{!.S:%{!.s: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}} \
-%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{!mips1:%{!mips2:-U__mips -D__mips=3 -D__mips64}} \
-%{mgp32:-U__mips64} %{mgp64:-D__mips64} \
-%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
+/* I would rather put this in CPP_PREDEFINES, but the gcc driver
+ doesn't handle -U options in CPP_PREDEFINES. */
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "\
+%{!mips1:%{!mips2:-U__mips -D__mips=3 -D__mips64}}"
/* Use memcpy, et. al., rather than bcopy. */
#define TARGET_MEM_FUNCTIONS
@@ -66,6 +55,13 @@ Boston, MA 02111-1307, USA. */
#include "gofast.h"
#define INIT_TARGET_OPTABS INIT_GOFAST_OPTABS
+/* 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)
+
/* We need to use .esize and .etype instead of .size and .type to
avoid conflicting with ELF directives. */
#undef PUT_SDB_SIZE
@@ -87,12 +83,12 @@ do { \
NULL_TREE. Some target formats do not support arbitrary sections. Do not
define this macro in such cases. */
-#define ASM_OUTPUT_SECTION_NAME(F, DECL, NAME) \
+#define ASM_OUTPUT_SECTION_NAME(F, DECL, NAME, RELOC) \
do { \
extern FILE *asm_out_text_file; \
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
fprintf (asm_out_text_file, "\t.section %s,\"ax\",@progbits\n", (NAME)); \
- else if ((DECL) && TREE_READONLY (DECL)) \
+ else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
fprintf (F, "\t.section %s,\"a\",@progbits\n", (NAME)); \
else \
fprintf (F, "\t.section %s,\"aw\",@progbits\n", (NAME)); \
diff --git a/gnu/usr.bin/gcc/config/mips/gnu.h b/gnu/usr.bin/gcc/config/mips/gnu.h
index 083507b4121..039e05cd820 100644
--- a/gnu/usr.bin/gcc/config/mips/gnu.h
+++ b/gnu/usr.bin/gcc/config/mips/gnu.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. MIPS GNU Hurd version.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+#define TARGET_DEFAULT MASK_GAS
+
#include <mips/mips.h>
#undef SWITCH_TAKES_ARG
@@ -81,11 +83,7 @@ Boston, MA 02111-1307, USA. */
/* Switch Recognition by gcc.c. Add -G xx support */
#undef SWITCH_TAKES_ARG
#define SWITCH_TAKES_ARG(CHAR) \
- ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
- || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
- || (CHAR) == 'I' || (CHAR) == 'm' \
- || (CHAR) == 'h' || (CHAR) == 'z' \
- || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'G')
+ (DEFAULT_SWITCH_TAKES_ARG(CHAR) || (CHAR) == 'G')
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 1
@@ -100,24 +98,6 @@ Boston, MA 02111-1307, USA. */
"-DMIPSEB -DR3000 -D_MIPSEB -D_R3000 \
-D_MIPS_SZINT=32 -D_MIPS_SZLONG=32 -D_MIPS_SZPTR=32"
-#undef ASM_SPEC
-#define ASM_SPEC "\
-%{mmips-as: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{!mmips-as: \
- %{mcpu=*}} \
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \
-%{membedded-pic}"
-
#undef LINK_SPEC
#define LINK_SPEC "\
%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \
diff --git a/gnu/usr.bin/gcc/config/mips/iris3.h b/gnu/usr.bin/gcc/config/mips/iris3.h
index 42515e8dd4b..8843d69dc81 100644
--- a/gnu/usr.bin/gcc/config/mips/iris3.h
+++ b/gnu/usr.bin/gcc/config/mips/iris3.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Iris version.
- Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -28,21 +28,8 @@ Boston, MA 02111-1307, USA. */
#define STARTFILE_SPEC "%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}"
-#define CPP_SPEC "\
-%{!ansi:-D__EXTENSIONS__} -D_MIPSEB -D_SYSTYPE_SYSV \
-%{.S: -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.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: %{!.s: %{!.cc: %{!.cxx: %{!.C: %{!.m: -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}}}}}} \
-%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{mips3:-U__mips -D__mips=3 -D__mips64} \
-%{mgp32:-U__mips64} %{mgp64:-D__mips64} \
-%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
+#define SUBTARGET_CPP_SPEC "\
+%{!ansi:-D__EXTENSIONS__} -D_MIPSEB -D_SYSTYPE_SYSV"
#define LIB_SPEC \
"%{!p:%{!pg:%{!static:%{!g*:-lc_s}} -lc}}%{p:-lc_p}%{pg:-lc_p} crtn.o%s"
@@ -66,12 +53,7 @@ Boston, MA 02111-1307, USA. */
SIZE.constant = 32; \
}
-/* Define this macro to control use of the character `$' in
- identifier names. The value should be 0, 1, or 2. 0 means `$'
- is not allowed by default; 1 means it is allowed by default if
- `-traditional' is used; 2 means it is allowed by default provided
- `-ansi' is not used. 1 is the default; there is no need to
- define this macro in that case. */
+/* Do not allow `$' in identifiers. */
#define DOLLARS_IN_IDENTIFIERS 0
diff --git a/gnu/usr.bin/gcc/config/mips/iris4loser.h b/gnu/usr.bin/gcc/config/mips/iris4loser.h
index 9503d7a2c6a..971bb53be20 100644
--- a/gnu/usr.bin/gcc/config/mips/iris4loser.h
+++ b/gnu/usr.bin/gcc/config/mips/iris4loser.h
@@ -1,41 +1,7 @@
/* Like iris4.h, but always inhibits assembler optimization for MIPS as.
Use this via mips-sgi-iris4loser if you need it. */
-#include "mips/iris4.h"
-
-#undef ASM_SPEC
-#if ((TARGET_CPU_DEFAULT | TARGET_DEFAULT) & MASK_GAS) != 0
-/* GAS */
-#define ASM_SPEC "\
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{mmips-as: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- -O0 \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
+#define SUBTARGET_MIPS_AS_ASM_SPEC "-O0 %{v}"
+#define SUBTARGET_ASM_OPTIMIZING_SPEC ""
-#else
-/* not GAS */
-#define ASM_SPEC "\
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{!mgas: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- -O0 \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
-
-#endif
+#include "mips/iris4.h"
diff --git a/gnu/usr.bin/gcc/config/mips/iris5.h b/gnu/usr.bin/gcc/config/mips/iris5.h
index 7272698c82c..d7840b45a4a 100644
--- a/gnu/usr.bin/gcc/config/mips/iris5.h
+++ b/gnu/usr.bin/gcc/config/mips/iris5.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Iris version 5.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -50,6 +50,13 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE_SIZE LONG_TYPE_SIZE
#define MAX_WCHAR_TYPE_SIZE MAX_LONG_TYPE_SIZE
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
+ || !strcmp (STR, "rpath"))
+
+#undef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC "%{static: -mno-abicalls}"
+
/* ??? _MIPS_SIM and _MIPS_SZPTR should eventually depend on options when
options for them exist. */
@@ -60,42 +67,37 @@ Boston, MA 02111-1307, USA. */
-D_MIPS_SIM=_MIPS_SIM_ABI32 -D_MIPS_SZPTR=32 \
-Asystem(unix) -Asystem(svr4) -Acpu(mips) -Amachine(sgi)"
-#undef CPP_SPEC
-#define CPP_SPEC "\
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "\
%{!ansi:-D__EXTENSIONS__ -D_SGI_SOURCE -D_LONGLONG} \
-%{.cc: -D_LANGUAGE_C_PLUS_PLUS} \
-%{.cxx: -D_LANGUAGE_C_PLUS_PLUS} \
-%{.C: -D_LANGUAGE_C_PLUS_PLUS} \
-%{.m: -D_LANGUAGE_OBJECTIVE_C -D_LANGUAGE_C} \
-%{.S: -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.s: -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{!.S:%{!.s: %{!.cc: %{!.cxx: %{!.C: %{!.m: -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}}}}}}\
%{!mfp64: -D_MIPS_FPSET=16}%{mfp64: -D_MIPS_FPSET=32} \
%{mips1: -D_MIPS_ISA=_MIPS_ISA_MIPS1} \
%{mips2: -D_MIPS_ISA=_MIPS_ISA_MIPS2} \
%{mips3: -D_MIPS_ISA=_MIPS_ISA_MIPS3} \
%{!mips1: %{!mips2: %{!mips3: -D_MIPS_ISA=_MIPS_ISA_MIPS1}}} \
%{!mint64: -D_MIPS_SZINT=32}%{mint64: -D_MIPS_SZINT=64} \
-%{!mlong64: -D_MIPS_SZLONG=32}%{mlong64: -D_MIPS_SZLONG=64} \
-%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{mips3:-U__mips -D__mips=3 -D__mips64} \
-%{mgp32:-U__mips64} %{mgp64:-D__mips64} \
-%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
+%{!mlong64: -D_MIPS_SZLONG=32}%{mlong64: -D_MIPS_SZLONG=64}"
#undef LINK_SPEC
#define LINK_SPEC "\
%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \
%{bestGnum} %{shared} %{non_shared} \
%{call_shared} %{no_archive} %{exact_version} \
-%{!shared:%{!non_shared:%{!call_shared: -call_shared -no_unresolved}}} \
+%{static: -non_shared} \
+%{!static: \
+ %{!shared:%{!non_shared:%{!call_shared: -call_shared -no_unresolved}}}} \
+%{rpath} \
-_SYSTYPE_SVR4"
/* We now support shared libraries. */
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared:%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}}"
+#define STARTFILE_SPEC "\
+%{!static: \
+ %{!shared:%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}}} \
+%{static: \
+ %{pg:gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib/nonshared/mcrt1.o%s libprof1.a%s} \
+ %{!p:/usr/lib/nonshared/crt1.o%s}}}"
#undef LIB_SPEC
#define LIB_SPEC "%{!shared:%{p:-lprof1} %{pg:-lprof1} -lc}"
@@ -122,6 +124,9 @@ Boston, MA 02111-1307, USA. */
#undef MACHINE_TYPE
#define MACHINE_TYPE "SGI running IRIX 5.x"
+
+ /* Dollar signs are OK in Irix5 but not in Irix3. */
+#undef DOLLARS_IN_IDENTIFIERS
#undef NO_DOLLAR_IN_LABEL
/* -G is incompatible with -KPIC which is the default, so only allow objects
diff --git a/gnu/usr.bin/gcc/config/mips/iris6.h b/gnu/usr.bin/gcc/config/mips/iris6.h
index c677ee03867..5bc733cb427 100644
--- a/gnu/usr.bin/gcc/config/mips/iris6.h
+++ b/gnu/usr.bin/gcc/config/mips/iris6.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Iris version 6.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,35 +18,137 @@ 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. */
-/* Irix 6 uses DWARF. */
-#define DWARF_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG
+/* Default to -mabi=n32 and -mips3. */
+#define MIPS_ISA_DEFAULT 3
+#define MIPS_ABI_DEFAULT ABI_N32
+#define MULTILIB_DEFAULTS { "mabi=n32" }
-/* Default to -mips4. */
+#ifndef TARGET_DEFAULT
#define TARGET_DEFAULT MASK_ABICALLS|MASK_FLOAT64|MASK_64BIT
-#define MIPS_ISA_DEFAULT 4
-#define MULTILIB_DEFAULTS { "EB", "mips4" }
+#endif
-#include "mips/iris5gas.h"
+#include "mips/iris5.h"
#include "mips/abi64.h"
+/* For Irix 6, -mabi=64 implies TARGET_LONG64. */
+/* This is handled in override_options. */
+
+#undef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC "%{static: -mno-abicalls}"
+
+/* We must pass -D_LONGLONG always, even when -ansi is used, because irix6
+ system header files require it. This is OK, because gcc never warns
+ when long long is used in system header files. Alternatively, we can
+ add support for the SGI builtin type __long_long. */
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES \
+ "-Dunix -Dmips -Dsgi -Dhost_mips -DMIPSEB -D_MIPSEB -DSYSTYPE_SVR4 \
+ -D_LONGLONG -D_SVR4_SOURCE -D_MODERN_C -D__DSO__ \
+ -Asystem(unix) -Asystem(svr4) -Acpu(mips) -Amachine(sgi)"
+
+#undef SUBTARGET_CPP_SIZE_SPEC
+#define SUBTARGET_CPP_SIZE_SPEC "\
+%{mabi=32: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
+%{mabi=n32: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
+%{mabi=64: -D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
+%{!mabi*: -D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}"
+
+/* We must make -mips3 do what -mlong64 used to do. */
+/* ??? If no mipsX option given, but a mabi=X option is, then should set
+ _MIPS_ISA based on the mabi=X option. */
+/* ??? If no mabi=X option give, but a mipsX option is, then should set
+ _MIPS_SIM based on the mipsX option. */
+/* ??? Same for _MIPS_SZINT. */
+/* ??? Same for _MIPS_SZPTR. */
+/* ??? Same for __SIZE_TYPE and __PTRDIFF_TYPE. */
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "\
+%{!ansi:-D__EXTENSIONS__ -D_SGI_SOURCE} \
+%{mfp32: -D_MIPS_FPSET=16}%{!mfp32: -D_MIPS_FPSET=32} \
+%{mips1: -D_MIPS_ISA=_MIPS_ISA_MIPS1} \
+%{mips2: -D_MIPS_ISA=_MIPS_ISA_MIPS2} \
+%{mips3: -D_MIPS_ISA=_MIPS_ISA_MIPS3} \
+%{mips4: -D_MIPS_ISA=_MIPS_ISA_MIPS4} \
+%{!mips*: -D_MIPS_ISA=_MIPS_ISA_MIPS3} \
+%{mabi=32: -D_MIPS_SIM=_MIPS_SIM_ABI32} \
+%{mabi=n32: -D_ABIN32=2 -D_MIPS_SIM=_ABIN32} \
+%{mabi=64: -D_ABI64=3 -D_MIPS_SIM=_ABI64} \
+%{!mabi*: -D_ABIN32=2 -D_MIPS_SIM=_ABIN32} \
+%{!mint64: -D_MIPS_SZINT=32}%{mint64: -D_MIPS_SZINT=64} \
+%{mabi=32: -D_MIPS_SZLONG=32} \
+%{mabi=n32: -D_MIPS_SZLONG=32} \
+%{mabi=64: -D_MIPS_SZLONG=64} \
+%{!mabi*: -D_MIPS_SZLONG=32} \
+%{mabi=32: -D_MIPS_SZPTR=32} \
+%{mabi=n32: -D_MIPS_SZPTR=32} \
+%{mabi=64: -D_MIPS_SZPTR=64} \
+%{!mabi*: -D_MIPS_SZPTR=32} \
+%{!mips1:%{!mips2: -D_COMPILER_VERSION=601}} \
+%{!mips*: -U__mips -D__mips=3} \
+%{mabi=32: -U__mips64} \
+%{mabi=n32: -D__mips64} \
+%{mabi=64: -D__mips64} \
+%{!mabi*: -D__mips64}"
+
+/* Irix 6 uses DWARF-2. */
+#define DWARF2_DEBUGGING_INFO
+#define MIPS_DEBUGGING_INFO
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* The size in bytes of a DWARF field indicating an offset or length
+ relative to a debug info section, specified to be 4 bytes in the DWARF-2
+ specification. The SGI/MIPS ABI defines it to be the same as PTR_SIZE. */
+#define DWARF_OFFSET_SIZE PTR_SIZE
+
+#undef MACHINE_TYPE
+#define MACHINE_TYPE "SGI running IRIX 6.x"
+
/* The Irix 6.0.1 assembler doesn't like labels in the text section, so
just avoid emitting them. */
#define ASM_IDENTIFY_GCC
#define ASM_IDENTIFY_LANGUAGE
/* Irix 5 stuff that we don't need for Irix 6. */
+/* ??? We do need this for the -mabi=32 switch though. */
#undef ASM_OUTPUT_UNDEF_FUNCTION
#undef ASM_OUTPUT_EXTERNAL_LIBCALL
#undef ASM_DECLARE_FUNCTION_SIZE
/* Stuff we need for Irix 6 that isn't in Irix 5. */
+/* The SGI assembler doesn't like labels before the .ent, so we must output
+ the .ent and function name here, which is the normal place for it. */
+
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
+ do { \
+ fputs ("\t.ent\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs ("\n", STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs (":\n", STREAM); \
+ } while (0)
+
+/* Likewise, the SGI assembler doesn't like labels after the .end, so we
+ must output the .end here. */
+#define ASM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) \
+ do { \
+ fputs ("\t.end\t", STREAM); \
+ assemble_name (STREAM, NAME); \
+ fputs ("\n", STREAM); \
+ } while (0)
+
+/* Tell function_prologue in mips.c that we have already output the .ent/.end
+ pseudo-ops. */
+#define FUNCTION_NAME_ALREADY_DECLARED
+
#undef SET_ASM_OP /* Has no equivalent. See ASM_OUTPUT_DEF below. */
-/* 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'. */
+#if 0
+/* This is *NOT* how to equate one symbol to another symbol. The assembler
+ '=' syntax just equates a name to a constant expression.
+ See ASM_OUTPUT_WEAK_ALIAS. */
#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
do { fprintf ((FILE), "\t"); \
@@ -55,73 +157,100 @@ Boston, MA 02111-1307, USA. */
assemble_name (FILE, LABEL2); \
fprintf (FILE, "\n"); \
} while (0)
+#endif
+
+/* Define the strings used for the special svr4 .type and .size directives. */
+
+#define TYPE_ASM_OP ".type"
+#define SIZE_ASM_OP ".size"
+
+/* This is how we tell the assembler that a symbol is weak. */
+
+#define ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,VALUE) \
+ do { \
+ fputs ("\t.weakext\t", FILE); \
+ assemble_name (FILE, NAME); \
+ if (VALUE) \
+ { \
+ fputc (' ', FILE); \
+ assemble_name (FILE, VALUE); \
+ } \
+ fputc ('\n', FILE); \
+ } while (0)
+
+#define ASM_WEAKEN_LABEL(FILE,NAME) ASM_OUTPUT_WEAK_ALIAS(FILE,NAME,0)
#define POPSECTION_ASM_OP ".popsection"
-#define DEBUG_SECTION ".debug,1,0,0,1"
-#define LINE_SECTION ".line,1,0,0,1"
-#define SFNAMES_SECTION ".debug_sfnames,1,0,0,1"
-#define SRCINFO_SECTION ".debug_srcinfo,1,0,0,1"
-#define MACINFO_SECTION ".debug_macinfo,1,0,0,1"
-#define PUBNAMES_SECTION ".debug_pubnames,1,0,0,1"
-#define ARANGES_SECTION ".debug_aranges,1,0,0,1"
-
-#undef ASM_SPEC
-#if ((TARGET_CPU_DEFAULT | TARGET_DEFAULT) & MASK_GAS) != 0
-/* GAS */
-#define ASM_SPEC "\
-%{mmips-as: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} %{v} \
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \
-%{membedded-pic}"
-
-#else
-/* not GAS */
+#define DEBUG_INFO_SECTION ".debug_info,0x7000001e,0,0,1"
+#define DEBUG_LINE_SECTION ".debug_line,0x7000001e,0,0,1"
+#define SFNAMES_SECTION ".debug_sfnames,0x7000001e,0,0,1"
+#define SRCINFO_SECTION ".debug_srcinfo,0x7000001e,0,0,1"
+#define MACINFO_SECTION ".debug_macinfo,0x7000001e,0,0,1"
+#define PUBNAMES_SECTION ".debug_pubnames,0x7000001e,0,0,1"
+#define ARANGES_SECTION ".debug_aranges,0x7000001e,0,0,1"
+#define FRAME_SECTION ".debug_frame,0x7000001e,0x08000000,0,1"
+#define ABBREV_SECTION ".debug_abbrev,0x7000001e,0,0,1"
+
+/* ??? If no mabi=X option give, but a mipsX option is, then should depend
+ on the mipsX option. */
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC "%{!mabi*:-n32}"
+
/* Must pass -g0 to the assembler, otherwise it may overwrite our
debug info with its own debug info. */
/* Must pass -show instead of -v. */
/* Must pass -G 0 to the assembler, otherwise we may get warnings about
GOT overflow. */
-#define ASM_SPEC "\
-%{!mgas: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{G*} %{EB} %{EL} %{v:-show} \
-%{mips1} %{mips2} %{mips3} %{mips4} \
-%{!mips1: %{!mips2: %{!mips3: %{!mips4: -mips4}}}} \
-%{noasmopt:-O0} %{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
--g0 -G 0 %{membedded-pic}"
+/* ??? We pass -w to disable all assembler warnings. The `label should be
+ inside .ent/.end block' warning that we get for DWARF II debug info labels
+ is particularly annoying. */
+#undef SUBTARGET_MIPS_AS_ASM_SPEC
+#define SUBTARGET_MIPS_AS_ASM_SPEC "%{v:-show} -G 0 -w"
-#endif
+#undef SUBTARGET_ASM_DEBUGGING_SPEC
+#define SUBTARGET_ASM_DEBUGGING_SPEC "-g0"
/* Stuff for constructors. Start here. */
/* The assembler now accepts .section pseudo-ops, but it does not allow
- one to change the section in the middle of a function. crtstuff relies
- on this hack, and thus crtstuff won't work here. So, we do init and
- fini sections exactly the same way as they are done for Irix 5, and
- we ifdef out the ASM_OUTPUT_{CON,DE}STRUCTOR macros below. */
+ one to change the section in the middle of a function, so we can't use
+ the INIT_SECTION_ASM_OP code in crtstuff. But we can build up the ctor
+ and dtor lists this way, so we use -init and -fini to invoke the
+ do_global_* functions instead of running collect2. */
+#define BSS_SECTION_ASM_OP ".section\t.bss"
#define CONST_SECTION_ASM_OP_32 "\t.rdata"
#define CONST_SECTION_ASM_OP_64 ".section\t.rodata"
-#define CTORS_SECTION_ASM_OP ".section\t.ctors,1,2,0,4"
-#define DTORS_SECTION_ASM_OP ".section\t.dtors,1,2,0,4"
-
-/* 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 ".word"
+/* The IRIX 6 assembler .section directive takes four additional args:
+ section type, flags, entry size, and alignment. The alignment of the
+ .ctors and .dtors sections needs to be the same as the size of a pointer
+ so that the linker doesn't add padding between elements. */
+#if defined (CRT_BEGIN) || defined (CRT_END)
+
+/* If we are included from crtstuff.c, these need to be plain strings.
+ _MIPS_SZPTR is defined in SUBTARGET_CPP_SPEC above. */
+#if _MIPS_SZPTR == 64
+#define CTORS_SECTION_ASM_OP ".section\t.ctors,1,2,0,8"
+#define DTORS_SECTION_ASM_OP ".section\t.dtors,1,2,0,8"
+#else /* _MIPS_SZPTR != 64 */
+#define CTORS_SECTION_ASM_OP ".section\t.ctors,1,2,0,4"
+#define DTORS_SECTION_ASM_OP ".section\t.dtors,1,2,0,4"
+#endif /* _MIPS_SZPTR == 64 */
+
+#else /* ! (defined (CRT_BEGIN) || defined (CRT_END)) */
+
+/* If we are included from varasm.c, these need to depend on -mabi. */
+#define CTORS_SECTION_ASM_OP \
+ (TARGET_LONG64 ? ".section\t.ctors,1,2,0,8" : ".section\t.ctors,1,2,0,4")
+#define DTORS_SECTION_ASM_OP \
+ (TARGET_LONG64 ? ".section\t.dtors,1,2,0,8" : ".section\t.dtors,1,2,0,4")
+#endif /* defined (CRT_BEGIN) || defined (CRT_END) */
+
+/* dwarf2out will handle padding this data properly. We definitely don't
+ want it 8-byte aligned on n32. */
+#define EH_FRAME_SECTION_ASM_OP ".section\t.eh_frame,1,2,0,1"
/* 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
@@ -129,7 +258,7 @@ Boston, MA 02111-1307, USA. */
includes this file. */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_sdata, in_rdata, in_const, in_ctors, in_dtors, in_bss
+#define EXTRA_SECTIONS in_sdata, in_rdata, 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
@@ -154,7 +283,7 @@ rdata_section () \
{ \
if (in_section != in_rdata) \
{ \
- if (mips_isa >= 3) \
+ if (mips_abi != ABI_32) \
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP_64); \
else \
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP_32); \
@@ -186,14 +315,13 @@ dtors_section () \
} \
}
-#if 0
-
/* A C statement (sans semicolon) to output an element in the table of
global constructors. */
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
do { \
ctors_section (); \
- fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ fprintf (FILE, "\t%s\t ", \
+ TARGET_LONG64 ? ".dword" : ".word"); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
@@ -203,12 +331,26 @@ dtors_section () \
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
do { \
dtors_section (); \
- fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ fprintf (FILE, "\t%s\t ", \
+ TARGET_LONG64 ? ".dword" : ".word"); \
assemble_name (FILE, NAME); \
fprintf (FILE, "\n"); \
} while (0)
-#endif
+/* 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. */
+
+#define ASM_OUTPUT_SECTION_NAME(F, DECL, NAME, RELOC) \
+do { \
+ extern FILE *asm_out_text_file; \
+ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
+ fprintf (asm_out_text_file, "\t.section %s,1,6,4,4\n", (NAME)); \
+ else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
+ fprintf (F, "\t.section %s,1,2,0,8\n", (NAME)); \
+ else \
+ fprintf (F, "\t.section %s,1,3,0,8\n", (NAME)); \
+} while (0)
/* Stuff for constructors. End here. */
@@ -229,62 +371,175 @@ while (0)
/* ??? SGI assembler gives warning whenever .lcomm is used. */
#undef ASM_OUTPUT_LOCAL
-#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
-do \
- { \
- if (mips_isa >= 3) \
- { \
- fputs ("\t.section\t.bss\n", STREAM); \
- ASM_DECLARE_OBJECT_NAME (STREAM, NAME, 0); \
- ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \
- ASM_OUTPUT_SKIP (STREAM, SIZE); \
- fprintf (STREAM, "\t%s\n", POPSECTION_ASM_OP); \
- } \
- else \
+#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
+do \
+ { \
+ if (mips_abi != ABI_32) \
+ { \
+ fprintf (STREAM, "%s\n", BSS_SECTION_ASM_OP); \
+ mips_declare_object (STREAM, NAME, "", ":\n", 0); \
+ ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \
+ ASM_OUTPUT_SKIP (STREAM, SIZE); \
+ fprintf (STREAM, "\t%s\n", POPSECTION_ASM_OP); \
+ } \
+ else \
mips_declare_object (STREAM, NAME, "\n\t.lcomm\t", ",%u\n", (SIZE)); \
- } \
+ } \
while (0)
-#undef ASM_OUTPUT_INTERNAL_LABEL
-#define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM) \
- fprintf (STREAM, ".%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'. */
+/* 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)
+
+/* Write the extra assembler code needed to declare an object properly. */
+
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
+do \
+ { \
+ size_directive_output = 0; \
+ if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
+ { \
+ size_directive_output = 1; \
+ fprintf (STREAM, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (STREAM, NAME); \
+ fprintf (STREAM, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
+ } \
+ mips_declare_object (STREAM, NAME, "", ":\n", 0); \
+ } \
+while (0)
-#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*.%s%d", PREFIX, NUM)
+/* 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)
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX (mips_abi == ABI_32 ? "$" : ".")
-#undef STARTFILE_SPEC
/* Profiling is supported via libprof1.a not -lc_p as in Irix 3. */
+/* ??? If no mabi=X option give, but a mipsX option is, then should depend
+ on the mipsX option. */
#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
- "%{mips1:%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}} \
- %{mips2:%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}} \
- %{!mips1:%{!mips2:%{pg:/usr/lib64/gcrt1.o}%{!pg:%{p:/usr/lib64/mcrt1.o /usr/lib64/libprof1.a}%{!p:/usr/lib64/crt1.o}}}}"
+ "%{!static:%{!shared: \
+ %{mabi=32:%{pg:gcrt1.o%s} \
+ %{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}} \
+ %{mabi=n32: \
+ %{mips4:%{pg:/usr/lib32/mips4/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips4/mcrt1.o%s /usr/lib32/mips4/libprof1.a%s} \
+ %{!p:/usr/lib32/mips4/crt1.o%s}}} \
+ %{!mips4:%{pg:/usr/lib32/mips3/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips3/mcrt1.o%s /usr/lib32/mips3/libprof1.a%s} \
+ %{!p:/usr/lib32/mips3/crt1.o%s}}}} \
+ %{mabi=64: \
+ %{mips4:%{pg:/usr/lib64/mips4/gcrt1.o} \
+ %{!pg:%{p:/usr/lib64/mips4/mcrt1.o /usr/lib64/mips4/libprof1.a} \
+ %{!p:/usr/lib64/mips4/crt1.o}}} \
+ %{!mips4:%{pg:/usr/lib64/mips3/gcrt1.o} \
+ %{!pg:%{p:/usr/lib64/mips3/mcrt1.o /usr/lib64/mips3/libprof1.a} \
+ %{!p:/usr/lib64/mips3/crt1.o}}}} \
+ %{!mabi*: \
+ %{mips4:%{pg:/usr/lib32/mips4/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips4/mcrt1.o%s /usr/lib32/mips4/libprof1.a%s} \
+ %{!p:/usr/lib32/mips4/crt1.o%s}}} \
+ %{!mips4:%{pg:/usr/lib32/mips3/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips3/mcrt1.o%s /usr/lib32/mips3/libprof1.a%s} \
+ %{!p:/usr/lib32/mips3/crt1.o%s}}}}}} \
+ %{static: \
+ %{mabi=32:%{pg:/usr/lib/nonshared/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib/nonshared/mcrt1.o%s /usr/lib/nonshared/libprof1.a%s} \
+ %{!p:/usr/lib/nonshared/crt1.o%s}}} \
+ %{mabi=n32: \
+ %{mips4:%{pg:/usr/lib32/mips4/nonshared/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips4/nonshared/mcrt1.o%s \
+ /usr/lib32/mips4/nonshared/libprof1.a%s} \
+ %{!p:/usr/lib32/mips4/nonshared/crt1.o%s}}} \
+ %{!mips4:%{pg:/usr/lib32/mips3/nonshared/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips3/nonshared/mcrt1.o%s \
+ /usr/lib32/mips3/nonshared/libprof1.a%s} \
+ %{!p:/usr/lib32/mips3/nonshared/crt1.o%s}}}} \
+ %{mabi=64: \
+ %{mips4:%{pg:/usr/lib64/mips4/nonshared/gcrt1.o} \
+ %{!pg:%{p:/usr/lib64/mips4/nonshared/mcrt1.o \
+ /usr/lib64/mips4/nonshared/libprof1.a} \
+ %{!p:/usr/lib64/mips4/nonshared/crt1.o}}} \
+ %{!mips4:%{pg:/usr/lib64/mips3/nonshared/gcrt1.o} \
+ %{!pg:%{p:/usr/lib64/mips3/nonshared/mcrt1.o \
+ /usr/lib64/mips3/nonshared/libprof1.a} \
+ %{!p:/usr/lib64/mips3/nonshared/crt1.o}}}} \
+ %{!mabi*: \
+ %{mips4:%{pg:/usr/lib32/mips4/nonshared/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips4/nonshared/mcrt1.o%s \
+ /usr/lib32/mips4/nonshared/libprof1.a%s} \
+ %{!p:/usr/lib32/mips4/nonshared/crt1.o%s}}} \
+ %{!mips4:%{pg:/usr/lib32/mips3/nonshared/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips3/nonshared/mcrt1.o%s \
+ /usr/lib32/mips3/nonshared/libprof1.a%s} \
+ %{!pg:%{p:/usr/lib32/mips3/nonshared/mcrt1.o%s \
+ /usr/lib32/mips3/nonshared/libprof1.a%s} \
+ %{!p:/usr/lib32/mips3/nonshared/crt1.o%s}}}}}} \
+ crtbegin.o%s"
#undef LIB_SPEC
-#define LIB_SPEC "%{p:libprof1.a%s}%{pg:libprof1.a%s} -lc"
-
+#define LIB_SPEC \
+ "%{mabi=n32: %{mips4:-L/usr/lib32/mips4} %{!mips4:-L/usr/lib32/mips3} \
+ -L/usr/lib32} \
+ %{mabi=64: %{mips4:-L/usr/lib64/mips4} %{!mips4:-L/usr/lib64/mips3} \
+ -L/usr/lib64} \
+ %{!mabi*: %{mips4:-L/usr/lib32/mips4} %{!mips4:-L/usr/lib32/mips3} \
+ -L/usr/lib32} \
+ %{!shared: \
+ -dont_warn_unused %{p:libprof1.a%s}%{pg:libprof1.a%s} -lc -warn_unused}"
+
+/* Avoid getting two warnings for libgcc.a everytime we link. */
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "-dont_warn_unused -lgcc -warn_unused"
+
+/* ??? If no mabi=X option give, but a mipsX option is, then should depend
+ on the mipsX option. */
#undef ENDFILE_SPEC
#define ENDFILE_SPEC \
- "%{mips1:crtn.o%s}%{mips2:crtn.o%s}%{!mips1:%{!mips2:/usr/lib64/crtn.o}}"
-
+ "crtend.o%s \
+ %{!shared: \
+ %{mabi=32:crtn.o%s}\
+ %{mabi=n32:%{mips4:/usr/lib32/mips4/crtn.o%s}\
+ %{!mips4:/usr/lib32/mips3/crtn.o%s}}\
+ %{mabi=64:%{mips4:/usr/lib64/mips4/crtn.o%s}\
+ %{!mips4:/usr/lib64/mips3/crtn.o%s}}\
+ %{!mabi*:%{mips4:/usr/lib32/mips4/crtn.o%s}\
+ %{!mips4:/usr/lib32/mips3/crtn.o%s}}}"
+
+/* ??? If no mabi=X option give, but a mipsX option is, then should depend
+ on the mipsX option. */
#undef LINK_SPEC
#define LINK_SPEC "\
%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
%{bestGnum} %{shared} %{non_shared} \
-%{call_shared} %{no_archive} %{exact_version} \
-%{!shared: %{!non_shared: %{!call_shared: -call_shared -no_unresolved}}} \
--_SYSTYPE_SVR4"
-
-/* ??? Debugging does not work. We get many assembler core dumps,
- and even some linker core dumps. */
-#undef DBX_DEBUGGING_INFO
-#undef SDB_DEBUGGING_INFO
-#undef MIPS_DEBUGGING_INFO
-#undef DWARF_DEBUGGING_INFO
-#undef PREFERRED_DEBUGGING_TYPE
+%{call_shared} %{no_archive} %{exact_version} %{w} \
+%{static: -non_shared} \
+%{!static: \
+ %{!shared: %{!non_shared: %{!call_shared: -call_shared -no_unresolved}}}} \
+%{rpath} -init __do_global_ctors -fini __do_global_dtors \
+%{shared:-hidden_symbol __do_global_ctors,__do_global_dtors,__EH_FRAME_BEGIN__} \
+-_SYSTYPE_SVR4 %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64} %{!mabi*: -n32}"
diff --git a/gnu/usr.bin/gcc/config/mips/mips.h b/gnu/usr.bin/gcc/config/mips/mips.h
index cc1c8c84936..557fb09878c 100644
--- a/gnu/usr.bin/gcc/config/mips/mips.h
+++ b/gnu/usr.bin/gcc/config/mips/mips.h
@@ -1,9 +1,9 @@
/* Definitions of target machine for GNU compiler. MIPS version.
- Contributed by A. Lichnewsky, lich@inria.inria.fr
- Changed by Michael Meissner, meissner@osf.org
- 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
- Brendan Eich, brendan@microunity.com.
- Copyright (C) 1989, 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 90-6, 1997 Free Software Foundation, Inc.
+ Contributed by A. Lichnewsky (lich@inria.inria.fr).
+ Changed by Michael Meissner (meissner@osf.org).
+ 64 bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
+ Brendan Eich (brendan@microunity.com).
This file is part of GNU CC.
@@ -28,11 +28,8 @@ Boston, MA 02111-1307, USA. */
extern char *asm_file_name;
extern char call_used_regs[];
extern int current_function_calls_alloca;
-extern int flag_omit_frame_pointer;
-extern int frame_pointer_needed;
extern char *language_string;
extern int may_call_alloca;
-extern int optimize;
extern char **save_argv;
extern int target_flags;
extern char *version_string;
@@ -64,16 +61,37 @@ enum delay_type {
enum processor_type {
PROCESSOR_DEFAULT,
PROCESSOR_R3000,
+ PROCESSOR_R3900,
PROCESSOR_R6000,
PROCESSOR_R4000,
+ PROCESSOR_R4100,
+ PROCESSOR_R4300,
PROCESSOR_R4600,
PROCESSOR_R4650,
+ PROCESSOR_R5000,
PROCESSOR_R8000
};
/* Recast the cpu class to be the cpu attribute. */
#define mips_cpu_attr ((enum attr_cpu)mips_cpu)
+/* Which ABI to use. This is only used by the Irix 6 port currently. */
+
+enum mips_abi_type {
+ ABI_32,
+ ABI_N32,
+ ABI_64,
+ ABI_EABI
+};
+
+#ifndef MIPS_ABI_DEFAULT
+/* We define this away so that there is no extra runtime cost if the target
+ doesn't support multiple ABIs. */
+#define mips_abi ABI_32
+#else
+extern enum mips_abi_type mips_abi;
+#endif
+
/* Whether to emit abicalls code sequences or not. */
enum mips_abicalls_type {
@@ -119,6 +137,8 @@ extern enum mips_abicalls_type mips_abicalls;/* for svr4 abi pic calls */
extern int mips_isa; /* architectural level */
extern char *mips_cpu_string; /* for -mcpu=<xxx> */
extern char *mips_isa_string; /* for -mips{1,2,3,4} */
+extern char *mips_abi_string; /* for -misa={32,n32,64} */
+extern int mips_split_addresses; /* perform high/lo_sum support */
extern int dslots_load_total; /* total # load related delay slots */
extern int dslots_load_filled; /* # filled load delay slots */
extern int dslots_jump_total; /* total # jump related delay slots */
@@ -145,9 +165,11 @@ extern void final_prescan_insn ();
extern struct rtx_def * function_arg ();
extern void function_arg_advance ();
extern int function_arg_partial_nregs ();
+extern int function_arg_pass_by_reference ();
extern void function_epilogue ();
extern void function_prologue ();
extern void gen_conditional_branch ();
+extern void gen_conditional_move ();
extern struct rtx_def * gen_int_relational ();
extern void init_cumulative_args ();
extern int large_int ();
@@ -161,6 +183,7 @@ extern void mips_declare_object ();
extern int mips_epilogue_delay_slots ();
extern void mips_expand_epilogue ();
extern void mips_expand_prologue ();
+extern int mips_check_split ();
extern char *mips_fill_delay_slot ();
extern char *mips_move_1word ();
extern char *mips_move_2words ();
@@ -195,6 +218,14 @@ extern int nonimmediate_operand ();
extern int nonmemory_operand ();
extern int register_operand ();
extern int scratch_operand ();
+extern int move_operand ();
+extern int movdi_operand ();
+extern int se_register_operand ();
+extern int se_reg_or_0_operand ();
+extern int se_uns_arith_operand ();
+extern int se_arith_operand ();
+extern int se_nonmemory_operand ();
+extern int se_nonimmediate_operand ();
/* Functions to change what output section we are using. */
extern void data_section ();
@@ -203,22 +234,6 @@ extern void readonly_data_section ();
extern void sdata_section ();
extern void text_section ();
-/* Functions in the rest of the compiler that we reference. */
-extern void abort_with_insn ();
-extern void debug_rtx ();
-extern void fatal_io_error ();
-extern int get_frame_size ();
-extern int offsettable_address_p ();
-extern void output_address ();
-extern char *permalloc ();
-extern int reg_mentioned_p ();
-
-/* Functions in the standard library that we reference. */
-extern int atoi ();
-extern char *getenv ();
-extern char *mktemp ();
-
-
/* Stubs for half-pic support if not OSF/1 reference platform. */
#ifndef HALF_PIC_P
@@ -241,7 +256,7 @@ extern char *mktemp ();
/* Bits for real switches */
#define MASK_INT64 0x00000001 /* ints are 64 bits */
#define MASK_LONG64 0x00000002 /* longs and pointers are 64 bits */
-#define MASK_UNUSED 0x00000004
+#define MASK_SPLIT_ADDR 0x00000004 /* Address splitting is enabled. */
#define MASK_GPOPT 0x00000008 /* Optimize for global pointer */
#define MASK_GAS 0x00000010 /* Gas used instead of MIPS as */
#define MASK_NAME_REGS 0x00000020 /* Use MIPS s/w reg name convention */
@@ -258,7 +273,8 @@ extern char *mktemp ();
#define MASK_BIG_ENDIAN 0x00010000 /* Generate big endian code */
#define MASK_SINGLE_FLOAT 0x00020000 /* Only single precision FPU. */
#define MASK_MAD 0x00040000 /* Generate mad/madu as on 4650. */
-#define MASK_UNUSED1 0x00080000
+#define MASK_4300_MUL_FIX 0x00080000 /* Work-around early Vr4300 CPU bug */
+#define MASK_MIPS3900 0x00100000 /* like -mips1 only 3900 */
/* Dummy switches used only in spec's*/
#define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */
@@ -274,7 +290,6 @@ extern char *mktemp ();
#define MASK_DEBUG_G 0x00800000 /* don't support 64 bit arithmetic */
#define MASK_DEBUG_H 0x00400000 /* allow ints in FP registers */
#define MASK_DEBUG_I 0x00200000 /* unused */
-#define MASK_DEBUG_J 0x00100000 /* unused */
/* r4000 64 bit sizes */
#define TARGET_INT64 (target_flags & MASK_INT64)
@@ -282,6 +297,12 @@ extern char *mktemp ();
#define TARGET_FLOAT64 (target_flags & MASK_FLOAT64)
#define TARGET_64BIT (target_flags & MASK_64BIT)
+ /* Mips vs. GNU linker */
+#define TARGET_SPLIT_ADDRESSES (target_flags & MASK_SPLIT_ADDR)
+
+/* generate mips 3900 insns */
+#define TARGET_MIPS3900 (target_flags & MASK_MIPS3900)
+
/* Mips vs. GNU assembler */
#define TARGET_GAS (target_flags & MASK_GAS)
#define TARGET_UNIX_ASM (!TARGET_GAS)
@@ -298,7 +319,6 @@ extern char *mktemp ();
#define TARGET_DEBUG_G_MODE (target_flags & MASK_DEBUG_G)
#define TARGET_DEBUG_H_MODE (target_flags & MASK_DEBUG_H)
#define TARGET_DEBUG_I_MODE (target_flags & MASK_DEBUG_I)
-#define TARGET_DEBUG_J_MODE (target_flags & MASK_DEBUG_J)
/* Reg. Naming in .s ($21 vs. $a0) */
#define TARGET_NAME_REGS (target_flags & MASK_NAME_REGS)
@@ -342,6 +362,18 @@ extern char *mktemp ();
#define TARGET_MAD (target_flags & MASK_MAD)
+#define TARGET_4300_MUL_FIX (target_flags & MASK_4300_MUL_FIX)
+
+/* This is true if we must enable the assembly language file switching
+ code. */
+
+#define TARGET_FILE_SWITCHING (TARGET_GP_OPT && ! TARGET_GAS)
+
+/* We must disable the function end stabs when doing the file switching trick,
+ because the Lscope stabs end up in the wrong place, making it impossible
+ to debug the resulting code. */
+#define NO_DBX_FUNCTION_END TARGET_FILE_SWITCHING
+
/* Macro to define tables used to set the flags.
This is a list in braces of pairs in braces,
each pair being { "NAME", VALUE }
@@ -352,6 +384,8 @@ extern char *mktemp ();
{ \
{"int64", MASK_INT64 | MASK_LONG64}, \
{"long64", MASK_LONG64}, \
+ {"split-addresses", MASK_SPLIT_ADDR}, \
+ {"no-split-addresses", -MASK_SPLIT_ADDR}, \
{"mips-as", -MASK_GAS}, \
{"gas", MASK_GAS}, \
{"rnames", MASK_NAME_REGS}, \
@@ -388,7 +422,10 @@ extern char *mktemp ();
{"double-float", -MASK_SINGLE_FLOAT}, \
{"mad", MASK_MAD}, \
{"no-mad", -MASK_MAD}, \
+ {"fix4300", MASK_4300_MUL_FIX}, \
+ {"no-fix4300", -MASK_4300_MUL_FIX}, \
{"4650", MASK_MAD | MASK_SINGLE_FLOAT}, \
+ {"3900", MASK_MIPS3900}, \
{"debug", MASK_DEBUG}, \
{"debuga", MASK_DEBUG_A}, \
{"debugb", MASK_DEBUG_B}, \
@@ -399,7 +436,6 @@ extern char *mktemp ();
{"debugg", MASK_DEBUG_G}, \
{"debugh", MASK_DEBUG_H}, \
{"debugi", MASK_DEBUG_I}, \
- {"debugj", MASK_DEBUG_J}, \
{"", (TARGET_DEFAULT \
| TARGET_CPU_DEFAULT \
| TARGET_ENDIAN_DEFAULT)} \
@@ -431,6 +467,19 @@ extern char *mktemp ();
#endif
#endif
+/* We must pass -EL to the linker by default for little endian embedded
+ targets using linker scripts with a OUTPUT_FORMAT line. Otherwise, the
+ linker will default to using big-endian output files. The OUTPUT_FORMAT
+ line must be in the linker script, otherwise -EB/-EL will not work. */
+
+#ifndef LINKER_ENDIAN_SPEC
+#if TARGET_ENDIAN_DEFAULT == 0
+#define LINKER_ENDIAN_SPEC "%{!EB:%{!meb:-EL}}"
+#else
+#define LINKER_ENDIAN_SPEC ""
+#endif
+#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.
@@ -450,14 +499,24 @@ extern char *mktemp ();
#define TARGET_OPTIONS \
{ \
+ SUBTARGET_TARGET_OPTIONS \
{ "cpu=", &mips_cpu_string }, \
{ "ips", &mips_isa_string } \
}
+/* This is meant to be redefined in the host dependent files. */
+#define SUBTARGET_TARGET_OPTIONS
+
+#define GENERATE_BRANCHLIKELY (TARGET_MIPS3900 || (mips_isa >= 2))
+#define GENERATE_MULT3 (TARGET_MIPS3900)
+#define GENERATE_MADD (TARGET_MIPS3900)
+
+
+
/* Macros to decide whether certain features are available or not,
depending on the instruction set architecture level. */
-#define BRANCH_LIKELY_P() (mips_isa >= 2)
+#define BRANCH_LIKELY_P() GENERATE_BRANCHLIKELY
#define HAVE_SQRT_P() (mips_isa >= 2)
/* CC1_SPEC causes -mips3 and -mips4 to set -mfp64 and -mgp64; -mips1 or
@@ -480,10 +539,7 @@ extern char *mktemp ();
#endif
#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' || (CHAR) == 'G')
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -528,12 +584,24 @@ do \
\
for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) \
fixed_regs[regno] = call_used_regs[regno] = 1; \
+ for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) \
+ fixed_regs[regno] = call_used_regs[regno] = 1; \
+ } \
+ else if (mips_isa < 4) \
+ { \
+ int regno; \
+ \
+ /* We only have a single condition code register. We \
+ implement this by hiding all the condition code registers, \
+ and generating RTL that refers directly to ST_REG_FIRST. */ \
+ for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) \
+ fixed_regs[regno] = call_used_regs[regno] = 1; \
} \
SUBTARGET_CONDITIONAL_REGISTER_USAGE \
} \
while (0)
-/* This is meant to be redefined in the host dependent files */
+/* This is meant to be redefined in the host dependent files. */
#define SUBTARGET_CONDITIONAL_REGISTER_USAGE
/* Show we can debug even without a frame pointer. */
@@ -582,49 +650,83 @@ while (0)
-Asystem(unix) -Asystem(bsd) -Acpu(mips) -Amachine(mips)"
#endif
-/* Extra switches sometimes passed to the assembler. */
+/* Assembler specs. */
+
+/* MIPS_AS_ASM_SPEC is passed when using the MIPS assembler rather
+ than gas. */
+
+#define MIPS_AS_ASM_SPEC "\
+%{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
+%{pipe: %e-pipe is not supported.} \
+%{K} %(subtarget_mips_as_asm_spec)"
+
+/* SUBTARGET_MIPS_AS_ASM_SPEC is passed when using the MIPS assembler
+ rather than gas. It may be overridden by subtargets. */
+
+#ifndef SUBTARGET_MIPS_AS_ASM_SPEC
+#define SUBTARGET_MIPS_AS_ASM_SPEC "%{v}"
+#endif
+
+/* GAS_ASM_SPEC is passed when using gas, rather than the MIPS
+ assembler. */
+
+#define GAS_ASM_SPEC "%{mcpu=*} %{m4650} %{mmad:-m4650} %{m3900} %{v}"
+
+/* TARGET_ASM_SPEC is used to select either MIPS_AS_ASM_SPEC or
+ GAS_ASM_SPEC as the default, depending upon the value of
+ TARGET_DEFAULT. */
-#ifndef ASM_SPEC
#if ((TARGET_CPU_DEFAULT | TARGET_DEFAULT) & MASK_GAS) != 0
/* GAS */
-#define ASM_SPEC "\
-%{mmips-as: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{!mmips-as: \
- %{mcpu=*} %{m4650} %{mmad:-m4650}} \
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} %{v} \
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \
-%{membedded-pic}"
-#else
-/* not GAS */
-#define ASM_SPEC "\
-%{!mgas: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{mgas: \
- %{mcpu=*} %{m4650} %{mmad:-m4650}} \
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} %{v} \
+#define TARGET_ASM_SPEC "\
+%{mmips-as: %(mips_as_asm_spec)} \
+%{!mmips-as: %(gas_asm_spec)}"
+
+#else /* not GAS */
+
+#define TARGET_ASM_SPEC "\
+%{!mgas: %(mips_as_asm_spec)} \
+%{mgas: %(gas_asm_spec)}"
+
+#endif /* not GAS */
+
+/* SUBTARGET_ASM_OPTIMIZING_SPEC handles passing optimization options
+ to the assembler. It may be overridden by subtargets. */
+#ifndef SUBTARGET_ASM_OPTIMIZING_SPEC
+#define SUBTARGET_ASM_OPTIMIZING_SPEC "\
%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
+%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}}"
+#endif
+
+/* SUBTARGET_ASM_DEBUGGING_SPEC handles passing debugging options to
+ the assembler. It may be overridden by subtargets. */
+#ifndef SUBTARGET_ASM_DEBUGGING_SPEC
+#define SUBTARGET_ASM_DEBUGGING_SPEC "\
%{g} %{g0} %{g1} %{g2} %{g3} \
%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \
-%{membedded-pic}"
+%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
+#endif
+
+/* SUBTARGET_ASM_SPEC is always passed to the assembler. It may be
+ overridden by subtargets. */
+#ifndef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC ""
#endif
-#endif /* ASM_SPEC */
+
+/* ASM_SPEC is the set of arguments to pass to the assembler. */
+
+#define ASM_SPEC "\
+%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
+%(subtarget_asm_optimizing_spec) \
+%(subtarget_asm_debugging_spec) \
+%{membedded-pic} \
+%{mabi=32:-32}%{mabi=o32:-32}%{mabi=n32:-n32}%{mabi=64:-64}%{mabi=n64:-64} \
+%(target_asm_spec) \
+%(subtarget_asm_spec)"
/* Specify to run a post-processor, mips-tfile after the assembler
has run to stuff the mips debug information into the object file.
@@ -672,46 +774,118 @@ while (0)
#ifndef LINK_SPEC
#define LINK_SPEC "\
%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
-%{bestGnum} %{shared} %{non_shared}"
+%{bestGnum} %{shared} %{non_shared} \
+%(linker_endian_spec)"
#endif /* LINK_SPEC defined */
/* Specs for the compiler proper */
+/* SUBTARGET_CC1_SPEC is passed to the compiler proper. It may be
+ overridden by subtargets. */
+#ifndef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC ""
+#endif
+
+/* CC1_SPEC is the set of arguments to pass to the compiler proper. */
+
#ifndef CC1_SPEC
#define CC1_SPEC "\
%{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \
-%{mips1:-mfp32 -mgp32}%{mips2:-mfp32 -mgp32}\
+%{mips1:-mfp32 -mgp32} %{mips2:-mfp32 -mgp32}\
%{mips3:%{!msingle-float:%{!m4650:-mfp64}} -mgp64} \
%{mips4:%{!msingle-float:%{!m4650:-mfp64}} -mgp64} \
%{mfp64:%{msingle-float:%emay not use both -mfp64 and -msingle-float}} \
%{mfp64:%{m4650:%emay not use both -mfp64 and -m4650}} \
%{m4650:-mcpu=r4650} \
+%{m3900:-mips1 -mcpu=r3900 -mfp32 -mgp32} \
%{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}} \
%{pic-none: -mno-half-pic} \
%{pic-lib: -mhalf-pic} \
%{pic-extern: -mhalf-pic} \
%{pic-calls: -mhalf-pic} \
-%{save-temps: }"
+%{save-temps: } \
+%(subtarget_cc1_spec) "
#endif
-/* Preprocessor specs */
+/* Preprocessor specs. */
+
+/* SUBTARGET_CPP_SIZE_SPEC defines SIZE_TYPE and PTRDIFF_TYPE. It may
+ be overridden by subtargets. */
+
+#ifndef SUBTARGET_CPP_SIZE_SPEC
+#define SUBTARGET_CPP_SIZE_SPEC "\
+%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
+%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}"
+#endif
+
+/* SUBTARGET_CPP_SPEC is passed to the preprocessor. It may be
+ overridden by subtargets. */
+#ifndef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC ""
+#endif
+
+/* If we're using 64bit longs, then we have to define __LONG_MAX__
+ correctly. Similarly for 64bit ints and __INT_MAX__. */
+#ifndef LONG_MAX_SPEC
+#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_LONG64)
+#define LONG_MAX_SPEC "%{!mno-long64:-D__LONG_MAX__=9223372036854775807L}"
+#else
+#define LONG_MAX_SPEC "%{mlong64:-D__LONG_MAX__=9223372036854775807L}"
+#endif
+#endif
+
+/* CPP_SPEC is the set of arguments to pass to the preprocessor. */
#ifndef CPP_SPEC
#define CPP_SPEC "\
%{.cc: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
%{.cxx: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
%{.C: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
-%{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C} \
+%{.m: -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C -D__LANGUAGE_C -D_LANGUAGE_C} \
%{.S: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
%{.s: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{!.S:%{!.s: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}} \
-%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
+%{!.S: %{!.s: %{!.cc: %{!.cxx: %{!.C: %{!.m: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}}}}}} \
+%(subtarget_cpp_size_spec) \
%{mips3:-U__mips -D__mips=3 -D__mips64} \
%{mips4:-U__mips -D__mips=4 -D__mips64} \
%{mgp32:-U__mips64} %{mgp64:-D__mips64} \
+%{msingle-float:%{!msoft-float:-D__mips_single_float}} \
+%{m4650:%{!msoft-float:-D__mips_single_float}} \
+%{msoft-float:-D__mips_soft_float} \
+%{mabi=eabi:-D__mips_eabi} \
%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
+%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}} \
+%(long_max_spec) \
+%(subtarget_cpp_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. */
+
+#define EXTRA_SPECS \
+ { "subtarget_cc1_spec", SUBTARGET_CC1_SPEC }, \
+ { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
+ { "subtarget_cpp_size_spec", SUBTARGET_CPP_SIZE_SPEC }, \
+ { "long_max_spec", LONG_MAX_SPEC }, \
+ { "mips_as_asm_spec", MIPS_AS_ASM_SPEC }, \
+ { "gas_asm_spec", GAS_ASM_SPEC }, \
+ { "target_asm_spec", TARGET_ASM_SPEC }, \
+ { "subtarget_mips_as_asm_spec", SUBTARGET_MIPS_AS_ASM_SPEC }, \
+ { "subtarget_asm_optimizing_spec", SUBTARGET_ASM_OPTIMIZING_SPEC }, \
+ { "subtarget_asm_debugging_spec", SUBTARGET_ASM_DEBUGGING_SPEC }, \
+ { "subtarget_asm_spec", SUBTARGET_ASM_SPEC }, \
+ { "linker_endian_spec", LINKER_ENDIAN_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
+
+#ifndef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
#endif
/* If defined, this macro is an additional prefix to try after
@@ -749,7 +923,7 @@ while (0)
#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
/* By default, turn on GDB extensions. */
@@ -789,10 +963,21 @@ while (0)
since the length can run past this up to a continuation point. */
#define DBX_CONTIN_LENGTH 1500
-
/* How to renumber registers for dbx and gdb. */
#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[ (REGNO) ]
+/* The mapping from gcc register number to DWARF 2 CFA column number.
+ This mapping does not allow for tracking register 0, since SGI's broken
+ dwarf reader thinks column 0 is used for the frame address, but since
+ register 0 is fixed this is not a problem. */
+#define DWARF_FRAME_REGNUM(REG) \
+ (REG == GP_REG_FIRST + 31 ? DWARF_FRAME_RETURN_COLUMN : REG)
+
+/* The DWARF 2 CFA column which tracks the return address. */
+#define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1)
+
+/* Before the prologue, RA lives in r31. */
+#define INCOMING_RETURN_ADDR_RTX gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31)
/* Overrides for the COFF debug format. */
#define PUT_SDB_SCL(a) \
@@ -930,6 +1115,12 @@ do { \
#define PUT_SDB_EPILOGUE_END(NAME)
+#define PUT_SDB_SRC_FILE(FILENAME) \
+do { \
+ extern FILE *asm_out_text_file; \
+ output_file_directive (asm_out_text_file, (FILENAME)); \
+} while (0)
+
#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
sprintf ((BUFFER), ".%dfake", (NUMBER));
@@ -1070,7 +1261,7 @@ do { \
#define FUNCTION_BOUNDARY 32
/* Alignment of field after `int : 0' in a structure. */
-#define EMPTY_FIELD_BOUNDARY (TARGET_LONG64 ? 64 : 32)
+#define EMPTY_FIELD_BOUNDARY 32
/* Every structure's size must be a multiple of this. */
/* 8 is observed right on a DECstation and on riscos 4.02. */
@@ -1079,9 +1270,6 @@ do { \
/* There is no point aligning anything to a rounder boundary than this. */
#define BIGGEST_ALIGNMENT 64
-/* Biggest alignment any structure field can require in bits. */
-#define BIGGEST_FIELD_ALIGNMENT 64
-
/* Set this nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 1
@@ -1171,12 +1359,16 @@ do { \
even those that are not normally considered general registers.
On the Mips, we have 32 integer registers, 32 floating point
- registers and the special registers hi, lo, hilo, and fp status.
- The hilo register is only used in 64 bit mode. It represents a 64
- bit value stored as two 32 bit values in the hi and lo registers;
- this is the result of the mult instruction. */
+ registers, 8 condition code registers, and the special registers
+ hi, lo, hilo, and rap. The 8 condition code registers are only
+ used if mips_isa >= 4. The hilo register is only used in 64 bit
+ mode. It represents a 64 bit value stored as two 32 bit values in
+ the hi and lo registers; this is the result of the mult
+ instruction. rap is a pointer to the stack where the return
+ address reg ($31) was stored. This is needed for C++ exception
+ handling. */
-#define FIRST_PSEUDO_REGISTER 68
+#define FIRST_PSEUDO_REGISTER 76
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
@@ -1189,7 +1381,7 @@ do { \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 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, 1 \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 \
}
@@ -1206,7 +1398,7 @@ do { \
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, 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 \
}
@@ -1229,19 +1421,25 @@ do { \
#define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1)
#define ST_REG_FIRST 67
-#define ST_REG_LAST 67
+#define ST_REG_LAST 74
#define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1)
+#define RAP_REG_NUM 75
+
#define AT_REGNUM (GP_REG_FIRST + 1)
#define HI_REGNUM (MD_REG_FIRST + 0)
#define LO_REGNUM (MD_REG_FIRST + 1)
#define HILO_REGNUM (MD_REG_FIRST + 2)
+
+/* FPSW_REGNUM is the single condition code used if mips_isa < 4. If
+ mips_isa >= 4, it should not be used, and an arbitrary ST_REG
+ should be used instead. */
#define FPSW_REGNUM ST_REG_FIRST
#define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM)
#define FP_REG_P(REGNO) ((unsigned) ((REGNO) - FP_REG_FIRST) < FP_REG_NUM)
#define MD_REG_P(REGNO) ((unsigned) ((REGNO) - MD_REG_FIRST) < MD_REG_NUM)
-#define ST_REG_P(REGNO) ((REGNO) == ST_REG_FIRST)
+#define ST_REG_P(REGNO) ((unsigned) ((REGNO) - ST_REG_FIRST) < ST_REG_NUM)
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
@@ -1250,7 +1448,7 @@ do { \
On the MIPS, all general registers are one word long. Except on
the R4000 with the FR bit set, the floating point uses register
- pairs, with the second register not being allocatable. */
+ pairs, with the second register not being allocable. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
(! FP_REG_P (REGNO) \
@@ -1289,8 +1487,9 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
/* Register to use for pushing function arguments. */
#define STACK_POINTER_REGNUM (GP_REG_FIRST + 29)
-/* Offset from the stack pointer to the first available location. */
-#define STACK_POINTER_OFFSET 0
+/* Offset from the stack pointer to the first available location. Use
+ the default value zero. */
+/* #define STACK_POINTER_OFFSET 0 */
/* Base register for access to local variables of the function. */
#define FRAME_POINTER_REGNUM (GP_REG_FIRST + 30)
@@ -1304,6 +1503,10 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM GP_REG_FIRST
+/* Fake register that holds the address on the stack of the
+ current function's return address. */
+#define RETURN_ADDRESS_POINTER_REGNUM RAP_REG_NUM
+
/* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2)
@@ -1427,8 +1630,8 @@ enum reg_class
{ 0x00000000, 0x00000000, 0x00000002 }, /* lo register */ \
{ 0x00000000, 0x00000000, 0x00000004 }, /* hilo register */ \
{ 0x00000000, 0x00000000, 0x00000003 }, /* mul/div registers */ \
- { 0x00000000, 0x00000000, 0x00000008 }, /* status registers */ \
- { 0xffffffff, 0xffffffff, 0x0000000f } /* all registers */ \
+ { 0x00000000, 0x00000000, 0x000007f8 }, /* status registers */ \
+ { 0xffffffff, 0xffffffff, 0x000007ff } /* all registers */ \
}
@@ -1588,7 +1791,8 @@ extern enum reg_class mips_char_to_class[];
|| (CLASS2 == GR_REGS && CLASS1 == FP_REGS))))
/* The HI and LO registers can only be reloaded via the general
- registers. */
+ registers. Condition code registers can only be loaded to the
+ general registers, and from the floating point registers. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
mips_secondary_reload_class (CLASS, MODE, X, 1)
@@ -1628,10 +1832,6 @@ extern enum reg_class mips_secondary_reload_class ();
/* Stack layout; function entry, exit and calling. */
-/* Don't enable support for the 64 bit ABI calling convention.
- Some embedded code depends on the old 64 bit calling convention. */
-#define ABI_64BIT 0
-
/* Define this if pushing a word on the stack
makes the stack pointer a smaller address. */
#define STACK_GROWS_DOWNWARD
@@ -1673,6 +1873,25 @@ extern enum reg_class mips_secondary_reload_class ();
: current_function_outgoing_args_size)
#endif
+/* The return address for the current frame is in r31 is this is a leaf
+ function. Otherwise, it is on the stack. It is at a variable offset
+ from sp/fp/ap, so we define a fake hard register rap which is a
+ poiner to the return address on the stack. This always gets eliminated
+ during reload to be either the frame pointer or the stack pointer plus
+ an offset. */
+
+/* ??? This definition fails for leaf functions. There is currently no
+ general solution for this problem. */
+
+/* ??? There appears to be no way to get the return address of any previous
+ frame except by disassembling instructions in the prologue/epilogue.
+ So currently we support only the current frame. */
+
+#define RETURN_ADDR_RTX(count, frame) \
+ ((count == 0) \
+ ? gen_rtx (MEM, Pmode, gen_rtx (REG, Pmode, RETURN_ADDRESS_POINTER_REGNUM))\
+ : (rtx) 0)
+
/* Structure to be filled in by compute_frame_size with register
save masks, and offsets for the current function. */
@@ -1697,14 +1916,6 @@ struct mips_frame_info
extern struct mips_frame_info current_frame_info;
-/* Store in the variable DEPTH the initial difference between the
- frame pointer reg contents and the stack pointer reg contents,
- as of the start of the function body. This depends on the layout
- of the fixed parts of the stack frame and on how registers are saved. */
-
-/* #define INITIAL_FRAME_POINTER_OFFSET(VAR) \
- ((VAR) = compute_frame_size (get_frame_size ())) */
-
/* If defined, this macro specifies a table of register pairs used to
eliminate unneeded registers that point into the stack frame. If
it is not defined, the only elimination attempted by the compiler
@@ -1734,9 +1945,10 @@ extern struct mips_frame_info current_frame_info;
#define ELIMINABLE_REGS \
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
-
/* A C expression that returns non-zero if the compiler is allowed to
try to replace register number FROM-REG with register number
TO-REG. This macro need only be defined if `ELIMINABLE_REGS' is
@@ -1746,7 +1958,9 @@ extern struct mips_frame_info current_frame_info;
#define CAN_ELIMINATE(FROM, TO) \
(!frame_pointer_needed \
- || ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM))
+ || ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \
+ || ((FROM) == RETURN_ADDRESS_POINTER_REGNUM \
+ && (TO) == FRAME_POINTER_REGNUM))
/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It
specifies the initial difference between the specified pair of
@@ -1761,9 +1975,15 @@ extern struct mips_frame_info current_frame_info;
&& ((TO) == FRAME_POINTER_REGNUM \
|| (TO) == STACK_POINTER_REGNUM)) \
(OFFSET) = (current_frame_info.total_size \
- - (ABI_64BIT && mips_isa >= 3 \
+ - ((mips_abi != ABI_32 && mips_abi != ABI_EABI) \
? current_function_pretend_args_size \
: 0)); \
+ else if ((FROM) == RETURN_ADDRESS_POINTER_REGNUM \
+ && ((TO) == FRAME_POINTER_REGNUM \
+ || (TO) == STACK_POINTER_REGNUM)) \
+ (OFFSET) = current_frame_info.gp_sp_offset \
+ + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)) \
+ * (BYTES_BIG_ENDIAN != 0)); \
else \
abort (); \
}
@@ -1910,11 +2130,15 @@ extern struct mips_frame_info current_frame_info;
#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN)
-/* 1 if N is a possible register number for function argument passing. */
+/* 1 if N is a possible register number for function argument passing.
+ We have no FP argument registers when soft-float. When FP registers
+ are 32 bits, we can't directly reference the odd numbered ones. */
-#define FUNCTION_ARG_REGNO_P(N) (((N) >= GP_ARG_FIRST && (N) <= GP_ARG_LAST) \
- || ((N) >= FP_ARG_FIRST && (N) <= FP_ARG_LAST \
- && (0 == (N) % 2)))
+#define FUNCTION_ARG_REGNO_P(N) \
+ (((N) >= GP_ARG_FIRST && (N) <= GP_ARG_LAST) \
+ || (! TARGET_SOFT_FLOAT \
+ && ((N) >= FP_ARG_FIRST && (N) <= FP_ARG_LAST) \
+ && (TARGET_FLOAT64 || (0 == (N) % 2))))
/* A C expression which can inhibit the returning of certain function
values in registers, based on the type of value. A nonzero value says
@@ -1955,6 +2179,8 @@ typedef struct mips_args {
int gp_reg_found; /* whether a gp register was found yet */
int arg_number; /* argument number */
int arg_words; /* # total words the arguments take */
+ int fp_arg_words; /* # words for FP args (MIPS_EABI only) */
+ int last_arg_fp; /* nonzero if last arg was FP (EABI only) */
int num_adjusts; /* number of adjustments made */
/* Adjustments made to args pass in regs. */
/* ??? The size is doubled to work around a
@@ -1969,7 +2195,7 @@ typedef struct mips_args {
*/
-#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
@@ -2033,22 +2259,6 @@ typedef struct mips_args {
#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue(FILE, SIZE)
-/* Define the number of delay slots needed for the function epilogue.
-
- On the mips, we need a slot if either no stack has been allocated,
- or the only register saved is the return register. */
-
-#define DELAY_SLOTS_FOR_EPILOGUE mips_epilogue_delay_slots ()
-
-/* Define whether INSN can be placed in delay slot N for the epilogue.
- No references to the stack must be made, since on the MIPS, the
- delay slot is done after the stack has been cleaned up. */
-
-#define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN,N) \
- (get_attr_dslot (INSN) == DSLOT_NO \
- && get_attr_length (INSN) == 1 \
- && ! epilogue_reg_mentioned_p (PATTERN (INSN)))
-
/* Tell prologue and epilogue if register REGNO should be saved / restored. */
#define MUST_SAVE_REGISTER(regno) \
@@ -2139,6 +2349,13 @@ typedef struct mips_args {
#define TRAMPOLINE_ALIGNMENT (TARGET_LONG64 ? 64 : 32)
+/* INITIALIZE_TRAMPOLINE calls this library function to flush
+ program and data caches. */
+
+#ifndef CACHE_FLUSH_FUNC
+#define CACHE_FLUSH_FUNC "_flush_cache"
+#endif
+
/* A C statement to initialize the variable parts of a trampoline.
ADDR is an RTX for the address of the trampoline; FNADDR is an
RTX for the address of the nested function; STATIC_CHAIN is an
@@ -2159,13 +2376,13 @@ typedef struct mips_args {
emit_move_insn (gen_rtx (MEM, SImode, plus_constant (addr, 36)), CHAIN);\
} \
\
- /* Flush the instruction cache. */ \
- /* ??? Are the modes right? Maybe they should depend on -mint64/-mlong64? */\
+ /* Flush both caches. We need to flush the data cache in case \
+ the system has a write-back cache. */ \
/* ??? Should check the return value for errors. */ \
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "cacheflush"), \
+ emit_library_call (gen_rtx (SYMBOL_REF, Pmode, CACHE_FLUSH_FUNC), \
0, VOIDmode, 3, addr, Pmode, \
- GEN_INT (TRAMPOLINE_SIZE), SImode, \
- GEN_INT (1), SImode); \
+ GEN_INT (TRAMPOLINE_SIZE), TYPE_MODE (integer_type_node),\
+ GEN_INT (3), TYPE_MODE (integer_type_node)); \
}
/* Addressing modes, and classification of registers for them. */
@@ -2295,9 +2512,20 @@ typedef struct mips_args {
if (GET_CODE (xinsn) == REG && REG_OK_FOR_BASE_P (xinsn)) \
goto ADDR; \
\
- if (CONSTANT_ADDRESS_P (xinsn)) \
+ if (CONSTANT_ADDRESS_P (xinsn) \
+ && ! (mips_split_addresses && mips_check_split (xinsn, MODE))) \
goto ADDR; \
\
+ if (GET_CODE (xinsn) == LO_SUM && mips_split_addresses) \
+ { \
+ register rtx xlow0 = XEXP (xinsn, 0); \
+ register rtx xlow1 = XEXP (xinsn, 1); \
+ \
+ if (GET_CODE (xlow0) == REG && REG_OK_FOR_BASE_P (xlow0) \
+ && mips_check_split (xlow1, MODE)) \
+ goto ADDR; \
+ } \
+ \
if (GET_CODE (xinsn) == PLUS) \
{ \
register rtx xplus0 = XEXP (xinsn, 0); \
@@ -2339,8 +2567,9 @@ typedef struct mips_args {
/* ??? Reject combining an address with a register for the MIPS \
64 bit ABI, because the SGI assembler can not handle this. */ \
if (!TARGET_DEBUG_A_MODE \
- && ! ABI_64BIT \
+ && (mips_abi == ABI_32 || mips_abi == ABI_EABI) \
&& CONSTANT_ADDRESS_P (xplus1) \
+ && ! mips_split_addresses \
&& (!TARGET_EMBEDDED_PIC \
|| code1 != CONST \
|| GET_CODE (XEXP (xplus1, 0)) != MINUS)) \
@@ -2368,7 +2597,7 @@ typedef struct mips_args {
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH \
|| (GET_CODE (X) == CONST \
&& ! (flag_pic && pic_address_needs_scratch (X)) \
- && ! ABI_64BIT)) \
+ && (mips_abi == ABI_32 || mips_abi == ABI_EABI))) \
&& (!HALF_PIC_P () || !HALF_PIC_ADDRESS_P (X)))
/* Define this, so that when PIC, reload won't try to reload invalid
@@ -2387,7 +2616,8 @@ typedef struct mips_args {
#define LEGITIMATE_CONSTANT_P(X) \
((GET_CODE (X) != CONST_DOUBLE \
|| mips_const_double_ok (X, GET_MODE (X))) \
- && ! (GET_CODE (X) == CONST && ABI_64BIT))
+ && ! (GET_CODE (X) == CONST \
+ && mips_abi != ABI_32 && mips_abi != ABI_EABI))
/* A C compound statement that attempts to replace X with a valid
memory address for an operand of mode MODE. WIN will be a C
@@ -2438,10 +2668,18 @@ typedef struct mips_args {
GO_DEBUG_RTX (xinsn); \
} \
\
+ if (mips_split_addresses && mips_check_split (X, MODE)) \
+ { \
+ /* ??? Is this ever executed? */ \
+ X = gen_rtx (LO_SUM, Pmode, \
+ copy_to_mode_reg (Pmode, gen_rtx (HIGH, Pmode, X)), X); \
+ goto WIN; \
+ } \
+ \
if (GET_CODE (xinsn) == CONST \
&& ((flag_pic && pic_address_needs_scratch (xinsn)) \
/* ??? SGI's Irix 6 assembler can't handle CONST. */ \
- || ABI_64BIT)) \
+ || (mips_abi != ABI_32 && mips_abi != ABI_EABI))) \
{ \
rtx ptr_reg = gen_reg_rtx (Pmode); \
rtx constant = XEXP (XEXP (xinsn, 0), 1); \
@@ -2623,17 +2861,6 @@ while (0)
#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) \
(TARGET_64BIT ? ((INPREC) <= 32 || (OUTPREC) > 32) : 1)
-/* Define this macro to control use of the character `$' in
- identifier names. The value should be 0, 1, or 2. 0 means `$'
- is not allowed by default; 1 means it is allowed by default if
- `-traditional' is used; 2 means it is allowed by default provided
- `-ansi' is not used. 1 is the default; there is no need to
- define this macro in that case. */
-
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
-
/* 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. */
@@ -2767,7 +2994,8 @@ while (0)
enum machine_mode xmode = GET_MODE (X); \
if (xmode == SFmode || xmode == DFmode) \
{ \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R3900) \
return COSTS_N_INSNS (2); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (3); \
@@ -2789,7 +3017,9 @@ while (0)
enum machine_mode xmode = GET_MODE (X); \
if (xmode == SFmode) \
{ \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R3900 \
+ || mips_cpu == PROCESSOR_R5000) \
return COSTS_N_INSNS (4); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (5); \
@@ -2799,7 +3029,9 @@ while (0)
\
if (xmode == DFmode) \
{ \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R3900 \
+ || mips_cpu == PROCESSOR_R5000) \
return COSTS_N_INSNS (5); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (6); \
@@ -2809,8 +3041,12 @@ while (0)
\
if (mips_cpu == PROCESSOR_R3000) \
return COSTS_N_INSNS (12); \
+ else if (mips_cpu == PROCESSOR_R3900) \
+ return COSTS_N_INSNS (2); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (17); \
+ else if (mips_cpu == PROCESSOR_R5000) \
+ return COSTS_N_INSNS (5); \
else \
return COSTS_N_INSNS (10); \
} \
@@ -2821,7 +3057,8 @@ while (0)
enum machine_mode xmode = GET_MODE (X); \
if (xmode == SFmode) \
{ \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R3900) \
return COSTS_N_INSNS (12); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (15); \
@@ -2831,7 +3068,8 @@ while (0)
\
if (xmode == DFmode) \
{ \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R3900) \
return COSTS_N_INSNS (19); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (16); \
@@ -2843,12 +3081,32 @@ while (0)
\
case UDIV: \
case UMOD: \
- if (mips_cpu == PROCESSOR_R3000) \
+ if (mips_cpu == PROCESSOR_R3000 \
+ || mips_cpu == PROCESSOR_R3900) \
return COSTS_N_INSNS (35); \
else if (mips_cpu == PROCESSOR_R6000) \
return COSTS_N_INSNS (38); \
+ else if (mips_cpu == PROCESSOR_R5000) \
+ return COSTS_N_INSNS (36); \
+ else \
+ return COSTS_N_INSNS (69); \
+ \
+ case SIGN_EXTEND: \
+ /* A sign extend from SImode to DImode in 64 bit mode is often \
+ zero instructions, because the result can often be used \
+ directly by another instruction; we'll call it one. */ \
+ if (TARGET_64BIT && GET_MODE (X) == DImode \
+ && GET_MODE (XEXP (X, 0)) == SImode) \
+ return COSTS_N_INSNS (1); \
else \
- return COSTS_N_INSNS (69);
+ return COSTS_N_INSNS (2); \
+ \
+ case ZERO_EXTEND: \
+ if (TARGET_64BIT && GET_MODE (X) == DImode \
+ && GET_MODE (XEXP (X, 0)) == SImode) \
+ return COSTS_N_INSNS (2); \
+ else \
+ return COSTS_N_INSNS (1);
/* An expression giving the cost of an addressing mode that
contains ADDRESS. If not defined, the cost is computed from the
@@ -2922,6 +3180,8 @@ while (0)
: (((TO) == HI_REG || (TO) == LO_REG \
|| (TO) == MD_REGS || (FROM) == HILO_REG) \
&& (FROM) == GR_REGS) ? 6 \
+ : (FROM) == ST_REGS && (TO) == GR_REGS ? 4 \
+ : (FROM) == FP_REGS && (TO) == ST_REGS ? 8 \
: 12)
/* ??? Fix this to be right for the R8000. */
@@ -2974,12 +3234,30 @@ while (0)
{"small_int", { CONST_INT }}, \
{"large_int", { CONST_INT }}, \
{"mips_const_double_ok", { CONST_DOUBLE }}, \
+ {"const_float_1_operand", { CONST_DOUBLE }}, \
{"simple_memory_operand", { MEM, SUBREG }}, \
{"equality_op", { EQ, NE }}, \
{"cmp_op", { EQ, NE, GT, GE, GTU, GEU, LT, LE, \
LTU, LEU }}, \
{"pc_or_label_operand", { PC, LABEL_REF }}, \
- {"call_insn_operand", { MEM }}, \
+ {"call_insn_operand", { CONST_INT, CONST, SYMBOL_REF, REG}}, \
+ {"move_operand", { CONST_INT, CONST_DOUBLE, CONST, \
+ SYMBOL_REF, LABEL_REF, SUBREG, \
+ REG, MEM}}, \
+ {"movdi_operand", { CONST_INT, CONST_DOUBLE, CONST, \
+ SYMBOL_REF, LABEL_REF, SUBREG, REG, \
+ MEM, SIGN_EXTEND }}, \
+ {"se_register_operand", { SUBREG, REG, SIGN_EXTEND }}, \
+ {"se_reg_or_0_operand", { REG, CONST_INT, SUBREG, \
+ SIGN_EXTEND }}, \
+ {"se_uns_arith_operand", { REG, CONST_INT, SUBREG, \
+ SIGN_EXTEND }}, \
+ {"se_arith_operand", { REG, CONST_INT, SUBREG, \
+ SIGN_EXTEND }}, \
+ {"se_nonmemory_operand", { CONST_INT, CONST_DOUBLE, CONST, \
+ SYMBOL_REF, LABEL_REF, SUBREG, \
+ REG, SIGN_EXTEND }}, \
+ {"se_nonimmediate_operand", { SUBREG, REG, MEM, SIGN_EXTEND }},
/* If defined, a C statement to be executed just prior to the
@@ -3001,40 +3279,6 @@ while (0)
final_prescan_insn (INSN, OPVEC, NOPERANDS)
-/* Tell final.c how to eliminate redundant test instructions.
- Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). */
-
-/* A list of names to be used for additional modes for condition code
- values in registers. These names are added to `enum machine_mode'
- and all have class `MODE_CC'. By convention, they should start
- with `CC' and end with `mode'.
-
- You should only define this macro if your machine does not use
- `cc0' and only if additional modes are required.
-
- On the MIPS, we use CC_FPmode for all floating point except for not
- equal, CC_REV_FPmode for not equal (to reverse the sense of the
- jump), CC_EQmode for integer equality/inequality comparisons,
- CC_0mode for comparisons against 0, and CCmode for other integer
- comparisons. */
-
-#define EXTRA_CC_MODES CC_EQmode, CC_FPmode, CC_0mode, CC_REV_FPmode
-
-/* A list of C strings giving the names for the modes listed in
- `EXTRA_CC_MODES'. */
-
-#define EXTRA_CC_NAMES "CC_EQ", "CC_FP", "CC_0", "CC_REV_FP"
-
-/* Returns a mode from class `MODE_CC' to be used when comparison
- operation code OP is applied to rtx X. */
-
-#define SELECT_CC_MODE(OP, X, Y) \
- (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \
- ? SImode \
- : ((OP == NE) ? CC_REV_FPmode : CC_FPmode))
-
-
/* Control the assembler format that we output. */
/* Output at beginning of assembler file.
@@ -3134,6 +3378,14 @@ while (0)
&mips_reg_names[65][0], \
&mips_reg_names[66][0], \
&mips_reg_names[67][0], \
+ &mips_reg_names[68][0], \
+ &mips_reg_names[69][0], \
+ &mips_reg_names[70][0], \
+ &mips_reg_names[71][0], \
+ &mips_reg_names[72][0], \
+ &mips_reg_names[73][0], \
+ &mips_reg_names[74][0], \
+ &mips_reg_names[75][0], \
}
/* print-rtl.c can't use REGISTER_NAMES, since it depends on mips.c.
@@ -3148,7 +3400,8 @@ while (0)
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
- "hi", "lo", "accum","$fcr31" \
+ "hi", "lo", "accum","$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \
+ "$fcc5","$fcc6","$fcc7","$rap" \
}
/* If defined, a C initializer for an array of structures
@@ -3227,8 +3480,7 @@ while (0)
{ "fp", 30 + GP_REG_FIRST }, \
{ "ra", 31 + GP_REG_FIRST }, \
{ "$sp", 29 + GP_REG_FIRST }, \
- { "$fp", 30 + GP_REG_FIRST }, \
- { "cc", FPSW_REGNUM }, \
+ { "$fp", 30 + GP_REG_FIRST } \
}
/* Define results of standard character escape sequences. */
@@ -3457,12 +3709,6 @@ while (0)
HALF_PIC_DECLARE (NAME); \
}
-/* This is how to output a reference to a user-level label named NAME.
- `assemble_name' uses this. */
-
-#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
- fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, NAME)
-
/* This is how to output an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
@@ -3505,7 +3751,14 @@ do { \
if (TARGET_64BIT) \
{ \
fprintf (STREAM, "\t.dword\t"); \
- output_addr_const (STREAM, (VALUE)); \
+ if (HOST_BITS_PER_WIDE_INT < 64 || GET_CODE (VALUE) != CONST_INT) \
+ /* We can't use 'X' for negative numbers, because then we won't \
+ get the right value for the upper 32 bits. */ \
+ output_addr_const (STREAM, VALUE); \
+ else \
+ /* We must use 'X', because otherwise LONG_MIN will print as \
+ a number that the Irix 6 assembler won't accept. */ \
+ print_operand (STREAM, VALUE, 'X'); \
fprintf (STREAM, "\n"); \
} \
else \
@@ -3554,15 +3807,14 @@ do { \
fprintf (STREAM, "\t%s\t%sL%d-%sLS%d\n", \
TARGET_LONG64 ? ".dword" : ".word", \
LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
- else if (! ABI_64BIT) \
+ else if (mips_abi == ABI_32) \
fprintf (STREAM, "\t%s\t%sL%d\n", \
TARGET_LONG64 ? ".gpdword" : ".gpword", \
LOCAL_LABEL_PREFIX, VALUE); \
else \
- /* ??? Why does this one use . and not LOCAL_LABEL_PREFIX? */ \
- fprintf (STREAM, "\t%s\t.L%d\n", \
+ fprintf (STREAM, "\t%s\t%sL%d\n", \
TARGET_LONG64 ? ".dword" : ".word", \
- VALUE); \
+ LOCAL_LABEL_PREFIX, VALUE); \
} while (0)
/* When generating embedded PIC code we want to put the jump table in
@@ -3781,11 +4033,11 @@ while (0)
#define ASM_OPEN_PAREN "("
#define ASM_CLOSE_PAREN ")"
-/* How to start an assembler comment. */
+/* How to start an assembler comment.
+ The leading space is important (the mips native assembler requires it). */
#ifndef ASM_COMMENT_START
-#define ASM_COMMENT_START "\t\t# "
+#define ASM_COMMENT_START " #"
#endif
-
/* Macros for mips-tfile.c to encapsulate stabs in ECOFF, and for
@@ -3811,3 +4063,8 @@ while (0)
#define NO_BUILTIN_PTRDIFF_TYPE
#define PTRDIFF_TYPE (TARGET_LONG64 ? "long int" : "int")
#endif
+
+/* See mips_expand_prologue's use of loadgp for when this should be
+ true. */
+
+#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (TARGET_ABICALLS && mips_abi != ABI_32)
diff --git a/gnu/usr.bin/gcc/config/mips/mips.md b/gnu/usr.bin/gcc/config/mips/mips.md
index 23e35a3723a..8b81221ea3f 100644
--- a/gnu/usr.bin/gcc/config/mips/mips.md
+++ b/gnu/usr.bin/gcc/config/mips/mips.md
@@ -3,7 +3,7 @@
;; Changes by Michael Meissner, meissner@osf.org
;; 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
;; Brendan Eich, brendan@microunity.com.
-;; Copyright (C) 1989, 90, 91, 92, 93, 94, 95 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 90-96, 1997 Free Software Foundation, Inc.
;; This file is part of GNU CC.
@@ -22,12 +22,6 @@
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
-;; ??? MIPS4 has 8 floating point condition codes. This is not supported yet.
-
-;; ??? MIPS4 has floating point doubleword/word load/stores that accept a
-;; base+index addressing mode. There are no such load/stores for the integer
-;; registers. This is not supported yet.
-
;; ??? Currently does not have define_function_unit support for the R8000.
;; Must include new entries for fmadd in addition to existing entries.
@@ -93,15 +87,15 @@
;; (const_string "default"))))
;; ??? Fix everything that tests this attribute.
-(define_attr "cpu" "default,r3000,r6000,r4000,r4600,r4650,r8000"
+(define_attr "cpu"
+ "default,r3000,r3900,r6000,r4000,r4100,r4300,r4600,r4650,r5000,r8000"
(const (symbol_ref "mips_cpu_attr")))
;; Attribute defining whether or not we can use the branch-likely instructions
-;; (MIPS ISA level 2)
(define_attr "branch_likely" "no,yes"
(const
- (if_then_else (ge (symbol_ref "mips_isa") (const_int 2))
+ (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0))
(const_string "yes")
(const_string "no"))))
@@ -151,11 +145,13 @@
;; Make the default case (PROCESSOR_DEFAULT) handle the worst case
(define_function_unit "memory" 1 0
- (and (eq_attr "type" "load") (eq_attr "cpu" "!r3000,r4600,r4650"))
+ (and (eq_attr "type" "load")
+ (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4100,r4300,r5000"))
3 0)
(define_function_unit "memory" 1 0
- (and (eq_attr "type" "load") (eq_attr "cpu" "r3000,r4600,r4650"))
+ (and (eq_attr "type" "load")
+ (eq_attr "cpu" "r3000,r3900,r4600,r4650,r4100,r4300,r5000"))
2 0)
(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0)
@@ -167,11 +163,12 @@
1 3)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "imul") (eq_attr "cpu" "!r3000,r4000,r4600,r4650"))
+ (and (eq_attr "type" "imul")
+ (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000"))
17 17)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000"))
+ (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000,r3900"))
12 12)
(define_function_unit "imuldiv" 1 0
@@ -183,11 +180,37 @@
4 4)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "idiv") (eq_attr "cpu" "!r3000,r4000,r4600,r4650"))
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
+ 1 1)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
+ 4 4)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300,r5000")))
+ 5 5)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
+ 8 8)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "imul")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000")))
+ 9 9)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (eq_attr "cpu" "!r3000,r3900,r4000,r4600,r4650,r4100,r4300,r5000"))
38 38)
(define_function_unit "imuldiv" 1 0
- (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000"))
+ (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000,r3900"))
35 35)
(define_function_unit "imuldiv" 1 0
@@ -202,20 +225,61 @@
(and (eq_attr "type" "idiv") (eq_attr "cpu" "r4000"))
69 69)
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4100")))
+ 35 35)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4100")))
+ 67 67)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r4300")))
+ 37 37)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r4300")))
+ 69 69)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "SI") (eq_attr "cpu" "r5000")))
+ 36 36)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "idiv")
+ (and (eq_attr "mode" "DI") (eq_attr "cpu" "r5000")))
+ 68 68)
+
+;; The R4300 does *NOT* have a separate Floating Point Unit, instead
+;; the FP hardware is part of the normal ALU circuitry. This means FP
+;; instructions affect the pipe-line, and no functional unit
+;; parallelism can occur on R4300 processors. To force GCC into coding
+;; for only a single functional unit, we force the R4300 FP
+;; instructions to be processed in the "imuldiv" unit.
+
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r6000"))
+ (and (eq_attr "type" "fcmp") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000"))
3 0)
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r3000,r6000"))
+ (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r3000,r3900,r6000"))
2 0)
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r6000"))
+ (and (eq_attr "type" "fcmp") (eq_attr "cpu" "r5000"))
+ 1 0)
+
+(define_function_unit "adder" 1 1
+ (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r3900,r6000,r4300"))
4 0)
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000"))
+ (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000,r3900"))
2 0)
(define_function_unit "adder" 1 1
@@ -223,89 +287,155 @@
3 0)
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "!r3000,r4600,r4650"))
+ (and (eq_attr "type" "fabs,fneg")
+ (eq_attr "cpu" "!r3000,r3900,r4600,r4650,r4300,r5000"))
2 0)
(define_function_unit "adder" 1 1
- (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000,r4600,r4650"))
+ (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000,r3900,r4600,r4650,r5000"))
1 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000,r4600,r4650")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000")))
7 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000,r3900,r5000")))
4 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
5 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
8 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r3900,r6000,r4300,r5000")))
8 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000,r3900,r5000")))
5 0)
(define_function_unit "mult" 1 1
- (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fmul")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
6 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000,r4600,r4650")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300,r5000")))
23 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000,r3900")))
12 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000")))
15 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
32 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000,r4600,r4650")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000")))
+ 21 0)
+
+(define_function_unit "divide" 1 1
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "cpu" "!r3000,r3900,r6000,r4600,r4650,r4300")))
36 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000,r3900")))
19 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000")))
16 0)
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
61 0)
;;; ??? Is this number right?
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
54 0)
+
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4600,r4650")))
31 0)
+(define_function_unit "divide" 1 1
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r5000")))
+ 21 0)
+
;;; ??? Is this number right?
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r4600,r4650,r4300,r5000")))
112 0)
+
(define_function_unit "divide" 1 1
- (and (eq_attr "type" "fsqrt") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4600,r4650")))
60 0)
+(define_function_unit "divide" 1 1
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r5000")))
+ 36 0)
+
+;; R4300 FP instruction classes treated as part of the "imuldiv"
+;; functional unit:
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "fadd") (eq_attr "cpu" "r4300"))
+ 3 3)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "fcmp,fabs,fneg") (eq_attr "cpu" "r4300"))
+ 1 1)
+
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300")))
+ 5 5)
+(define_function_unit "imuldiv" 1 0
+ (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300")))
+ 8 8)
+
+(define_function_unit "imuldiv" 1 0
+ (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt"))
+ (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300")))
+ 29 29)
+(define_function_unit "imuldiv" 1 0
+ (and (and (eq_attr "type" "fdiv") (eq_attr "type" "fsqrt"))
+ (and (eq_attr "mode" "DF") (eq_attr "cpu" "r4300")))
+ 58 58)
;; The following functional units do not use the cpu type, and use
;; much less memory in genattrtab.c.
@@ -385,8 +515,8 @@
(define_expand "adddi3"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "arith_operand" "")))
+ (plus:DI (match_operand:DI 1 "se_register_operand" "")
+ (match_operand:DI 2 "se_arith_operand" "")))
(clobber (match_dup 3))])]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
"
@@ -541,8 +671,8 @@
(define_insn "adddi3_internal_3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (plus:DI (match_operand:DI 1 "reg_or_0_operand" "dJ")
- (match_operand:DI 2 "arith_operand" "dI")))]
+ (plus:DI (match_operand:DI 1 "se_reg_or_0_operand" "dJ")
+ (match_operand:DI 2 "se_arith_operand" "dI")))]
"TARGET_64BIT && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
"*
{
@@ -622,8 +752,8 @@
(define_expand "subdi3"
[(parallel [(set (match_operand:DI 0 "register_operand" "=d")
- (minus:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))
+ (minus:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))
(clobber (match_dup 3))])]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
"
@@ -765,8 +895,8 @@
(define_insn "subdi3_internal_3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (minus:DI (match_operand:DI 1 "reg_or_0_operand" "dJ")
- (match_operand:DI 2 "arith_operand" "dI")))]
+ (minus:DI (match_operand:DI 1 "se_reg_or_0_operand" "dJ")
+ (match_operand:DI 2 "se_arith_operand" "dI")))]
"TARGET_64BIT && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768)"
"*
{
@@ -803,26 +933,90 @@
;; ....................
;;
-(define_insn "muldf3"
+;; Early Vr4300 silicon has a CPU bug where multiplies with certain
+;; operands may corrupt immediately following multiplies. This is a
+;; simple fix to insert NOPs.
+
+(define_expand "muldf3"
[(set (match_operand:DF 0 "register_operand" "=f")
(mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "
+{
+ if (mips_cpu != PROCESSOR_R4300)
+ emit_insn (gen_muldf3_internal (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_muldf3_r4300 (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_insn "muldf3_internal"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && mips_cpu != PROCESSOR_R4300"
"mul.d\\t%0,%1,%2"
[(set_attr "type" "fmul")
(set_attr "mode" "DF")
(set_attr "length" "1")])
-(define_insn "mulsf3"
+(define_insn "muldf3_r4300"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mult:DF (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && mips_cpu == PROCESSOR_R4300"
+ "*
+{
+ output_asm_insn (\"mul.d\\t%0,%1,%2\", operands);
+ if (TARGET_4300_MUL_FIX)
+ output_asm_insn (\"nop\", operands);
+ return \"\";
+}"
+ [(set_attr "type" "fmul")
+ (set_attr "mode" "DF")
+ (set_attr "length" "2")]) ;; mul.d + nop
+
+(define_expand "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_HARD_FLOAT"
+ "
+{
+ if (mips_cpu != PROCESSOR_R4300)
+ emit_insn( gen_mulsf3_internal (operands[0], operands[1], operands[2]));
+ else
+ emit_insn( gen_mulsf3_r4300 (operands[0], operands[1], operands[2]));
+ DONE;
+}")
+
+(define_insn "mulsf3_internal"
+ [(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_HARD_FLOAT && mips_cpu != PROCESSOR_R4300"
"mul.s\\t%0,%1,%2"
[(set_attr "type" "fmul")
(set_attr "mode" "SF")
(set_attr "length" "1")])
+(define_insn "mulsf3_r4300"
+ [(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_HARD_FLOAT && mips_cpu == PROCESSOR_R4300"
+ "*
+{
+ output_asm_insn (\"mul.s\\t%0,%1,%2\", operands);
+ if (TARGET_4300_MUL_FIX)
+ output_asm_insn (\"nop\", operands);
+ return \"\";
+}"
+ [(set_attr "type" "fmul")
+ (set_attr "mode" "SF")
+ (set_attr "length" "2")]) ;; mul.s + nop
+
;; ??? The R4000 (only) has a cpu bug. If a double-word shift executes while
;; a multiply is in progress, it may give an incorrect result. Avoid
;; this by keeping the mflo with the mult on the R4000.
@@ -836,7 +1030,9 @@
""
"
{
- if (TARGET_MAD)
+ if (GENERATE_MULT3)
+ emit_insn (gen_mulsi3_mult3 (operands[0], operands[1], operands[2]));
+ else if (TARGET_MAD)
emit_insn (gen_mulsi3_r4650 (operands[0], operands[1], operands[2]));
else if (mips_cpu != PROCESSOR_R4000)
emit_insn (gen_mulsi3_internal (operands[0], operands[1], operands[2]));
@@ -845,6 +1041,19 @@
DONE;
}")
+(define_insn "mulsi3_mult3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mult:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (clobber (match_scratch:SI 3 "=h"))
+ (clobber (match_scratch:SI 4 "=l"))
+ (clobber (match_scratch:SI 5 "=a"))]
+ "GENERATE_MULT3"
+ "mult\\t%0,%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
(define_insn "mulsi3_internal"
[(set (match_operand:SI 0 "register_operand" "=l")
(mult:SI (match_operand:SI 1 "register_operand" "d")
@@ -895,7 +1104,7 @@
(define_expand "muldi3"
[(set (match_operand:DI 0 "register_operand" "=l")
- (mult:DI (match_operand:DI 1 "register_operand" "d")
+ (mult:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "register_operand" "d")))
(clobber (match_scratch:DI 3 "=h"))
(clobber (match_scratch:DI 4 "=a"))]
@@ -909,9 +1118,14 @@
DONE;
}")
+;; Don't accept both operands using se_register_operand, because if
+;; both operands are sign extended we would prefer to use mult in the
+;; mulsidi3 pattern. Commutativity should permit either operand to be
+;; sign extended.
+
(define_insn "muldi3_internal"
[(set (match_operand:DI 0 "register_operand" "=l")
- (mult:DI (match_operand:DI 1 "register_operand" "d")
+ (mult:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "register_operand" "d")))
(clobber (match_scratch:DI 3 "=h"))
(clobber (match_scratch:DI 4 "=a"))]
@@ -923,7 +1137,7 @@
(define_insn "muldi3_r4000"
[(set (match_operand:DI 0 "register_operand" "=d")
- (mult:DI (match_operand:DI 1 "register_operand" "d")
+ (mult:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "register_operand" "d")))
(clobber (match_scratch:DI 3 "=h"))
(clobber (match_scratch:DI 4 "=l"))
@@ -1051,8 +1265,8 @@
(define_insn "smuldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=h")
(truncate:DI
- (lshiftrt:TI (mult:TI (sign_extend:TI (match_operand:DI 1 "register_operand" "d"))
- (sign_extend:TI (match_operand:DI 2 "register_operand" "d")))
+ (lshiftrt:TI (mult:TI (sign_extend:TI (match_operand:DI 1 "se_register_operand" "d"))
+ (sign_extend:TI (match_operand:DI 2 "se_register_operand" "d")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=l"))
(clobber (match_scratch:DI 4 "=a"))]
@@ -1065,8 +1279,8 @@
(define_insn "umuldi3_highpart"
[(set (match_operand:DI 0 "register_operand" "=h")
(truncate:DI
- (lshiftrt:TI (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "d"))
- (zero_extend:TI (match_operand:DI 2 "register_operand" "d")))
+ (lshiftrt:TI (mult:TI (zero_extend:TI (match_operand:DI 1 "se_register_operand" "d"))
+ (zero_extend:TI (match_operand:DI 2 "se_register_operand" "d")))
(const_int 64))))
(clobber (match_scratch:DI 3 "=l"))
(clobber (match_scratch:DI 4 "=a"))]
@@ -1086,8 +1300,14 @@
(match_dup 0)))
(clobber (match_scratch:SI 3 "=h"))
(clobber (match_scratch:SI 4 "=a"))]
- "TARGET_MAD"
- "mad\\t%1,%2"
+ "TARGET_MAD || GENERATE_MADD"
+ "*
+{
+ if (TARGET_MAD)
+ return \"mad\\t%1,%2\";
+ else
+ return \"madd\\t%1,%2\";
+}"
[(set_attr "type" "imul")
(set_attr "mode" "SI")
(set_attr "length" "1")])
@@ -1150,6 +1370,20 @@
(set_attr "mode" "SI")
(set_attr "length" "1")])
+(define_insn "madd3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))
+ (match_operand:SI 3 "register_operand" "l")))
+ (clobber (match_scratch:SI 4 "=l"))
+ (clobber (match_scratch:SI 5 "=h"))
+ (clobber (match_scratch:SI 6 "=a"))]
+ "GENERATE_MADD"
+ "madd\\t%0,%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
;; Floating point multiply accumulate instructions.
(define_insn ""
@@ -1157,7 +1391,7 @@
(plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f"))
(match_operand:DF 3 "register_operand" "f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"madd.d\\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1179,7 +1413,7 @@
(minus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f"))
(match_operand:DF 3 "register_operand" "f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"msub.d\\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1202,7 +1436,7 @@
(neg:DF (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f"))
(match_operand:DF 3 "register_operand" "f"))))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"nmadd.d\\t%0,%3,%1,%2"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1224,7 +1458,7 @@
(minus:DF (match_operand:DF 1 "register_operand" "f")
(mult:DF (match_operand:DF 2 "register_operand" "f")
(match_operand:DF 3 "register_operand" "f"))))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"nmsub.d\\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "DF")
@@ -1269,6 +1503,26 @@
(set_attr "mode" "SF")
(set_attr "length" "1")])
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (div:DF (match_operand:DF 1 "const_float_1_operand" "")
+ (match_operand:DF 2 "register_operand" "f")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math"
+ "recip.d\\t%0,%2"
+ [(set_attr "type" "fdiv")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (div:SF (match_operand:SF 1 "const_float_1_operand" "")
+ (match_operand:SF 2 "register_operand" "f")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && flag_fast_math"
+ "recip.s\\t%0,%2"
+ [(set_attr "type" "fdiv")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
;; If optimizing, prefer the divmod functions over separate div and
;; mod functions, since this will allow using one instruction for both
;; the quotient and remainder. At present, the divmod is not moved out
@@ -1309,8 +1563,8 @@
(define_insn "divmoddi4"
[(set (match_operand:DI 0 "register_operand" "=d")
- (div:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))
+ (div:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))
(set (match_operand:DI 3 "register_operand" "=d")
(mod:DI (match_dup 1)
(match_dup 2)))
@@ -1359,8 +1613,8 @@
(define_insn "udivmoddi4"
[(set (match_operand:DI 0 "register_operand" "=d")
- (udiv:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))
+ (udiv:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))
(set (match_operand:DI 3 "register_operand" "=d")
(umod:DI (match_dup 1)
(match_dup 2)))
@@ -1397,8 +1651,8 @@
(define_insn "divdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (div:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "nonmemory_operand" "di")))
+ (div:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
(clobber (match_scratch:DI 3 "=l"))
(clobber (match_scratch:DI 4 "=h"))
(clobber (match_scratch:DI 6 "=a"))]
@@ -1423,8 +1677,8 @@
(define_insn "moddi3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (mod:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "nonmemory_operand" "di")))
+ (mod:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
(clobber (match_scratch:DI 3 "=l"))
(clobber (match_scratch:DI 4 "=h"))
(clobber (match_scratch:DI 6 "=a"))]
@@ -1449,8 +1703,8 @@
(define_insn "udivdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (udiv:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "nonmemory_operand" "di")))
+ (udiv:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
(clobber (match_scratch:DI 3 "=l"))
(clobber (match_scratch:DI 4 "=h"))
(clobber (match_scratch:DI 6 "=a"))]
@@ -1475,8 +1729,8 @@
(define_insn "umoddi3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (umod:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "nonmemory_operand" "di")))
+ (umod:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_nonmemory_operand" "di")))
(clobber (match_scratch:DI 3 "=l"))
(clobber (match_scratch:DI 4 "=h"))
(clobber (match_scratch:DI 6 "=a"))]
@@ -1512,6 +1766,26 @@
(set_attr "mode" "SF")
(set_attr "length" "1")])
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (div:DF (match_operand:DF 1 "const_float_1_operand" "")
+ (sqrt:DF (match_operand:DF 2 "register_operand" "f"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && flag_fast_math"
+ "rsqrt.d\\t%0,%2"
+ [(set_attr "type" "fsqrt")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (div:SF (match_operand:SF 1 "const_float_1_operand" "")
+ (sqrt:SF (match_operand:SF 2 "register_operand" "f"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && flag_fast_math"
+ "rsqrt.s\\t%0,%2"
+ [(set_attr "type" "fsqrt")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
;;
;; ....................
@@ -1535,7 +1809,7 @@
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- if (mips_isa >= 2)
+ if (GENERATE_BRANCHLIKELY)
return \"%(bltzl\\t%1,1f\\n\\tsubu\\t%0,%z2,%0\\n1:%)\";
else
return \"bgez\\t%1,1f%#\\n\\tsubu\\t%0,%z2,%0\\n1:\";
@@ -1549,7 +1823,7 @@
(define_insn "absdi2"
[(set (match_operand:DI 0 "register_operand" "=d")
- (abs:DI (match_operand:DI 1 "register_operand" "d")))]
+ (abs:DI (match_operand:DI 1 "se_register_operand" "d")))]
"TARGET_64BIT"
"*
{
@@ -1631,7 +1905,7 @@ move\\t%0,%z4\\n\\
(define_insn "ffsdi2"
[(set (match_operand:DI 0 "register_operand" "=&d")
- (ffs:DI (match_operand:DI 1 "register_operand" "d")))
+ (ffs:DI (match_operand:DI 1 "se_register_operand" "d")))
(clobber (match_scratch:DI 2 "=&d"))
(clobber (match_scratch:DI 3 "=&d"))]
"TARGET_64BIT"
@@ -1688,7 +1962,7 @@ move\\t%0,%z4\\n\\
(define_expand "negdi2"
[(parallel [(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (match_operand:DI 1 "register_operand" "d")))
+ (neg:DI (match_operand:DI 1 "se_register_operand" "d")))
(clobber (match_dup 2))])]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
"
@@ -1718,7 +1992,7 @@ move\\t%0,%z4\\n\\
(define_insn "negdi2_internal_2"
[(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (match_operand:DI 1 "register_operand" "d")))]
+ (neg:DI (match_operand:DI 1 "se_register_operand" "d")))]
"TARGET_64BIT"
"*
{
@@ -1762,7 +2036,7 @@ move\\t%0,%z4\\n\\
(define_insn "one_cmpldi2"
[(set (match_operand:DI 0 "register_operand" "=d")
- (not:DI (match_operand:DI 1 "register_operand" "d")))]
+ (not:DI (match_operand:DI 1 "se_register_operand" "d")))]
""
"*
{
@@ -1789,51 +2063,6 @@ move\\t%0,%z4\\n\\
(set (subreg:SI (match_dup 0) 1) (not:SI (subreg:SI (match_dup 1) 1)))]
"")
-;; Simple hack to recognize the "nor" instruction on the MIPS
-;; This must appear before the normal or patterns, so that the
-;; combiner will correctly fold things.
-
-(define_insn "norsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (not:SI (ior:SI (match_operand:SI 1 "reg_or_0_operand" "dJ")
- (match_operand:SI 2 "reg_or_0_operand" "dJ"))))]
- ""
- "nor\\t%0,%z1,%z2"
- [(set_attr "type" "arith")
- (set_attr "mode" "SI")
- (set_attr "length" "1")])
-
-(define_insn "nordi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (not:DI (ior:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d"))))]
- ""
- "*
-{
- if (TARGET_64BIT)
- return \"nor\\t%0,%z1,%z2\";
- return \"nor\\t%M0,%M1,%M2\;nor\\t%L0,%L1,%L2\";
-}"
- [(set_attr "type" "darith")
- (set_attr "mode" "DI")
- (set (attr "length")
- (if_then_else (ge (symbol_ref "mips_isa") (const_int 3))
- (const_int 1)
- (const_int 2)))])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (not:DI (ior:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" ""))))]
- "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE
- && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
- && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
- && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
-
- [(set (subreg:SI (match_dup 0) 0) (not:SI (ior:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))))
- (set (subreg:SI (match_dup 0) 1) (not:SI (ior:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1))))]
- "")
-
;;
;; ....................
@@ -1857,8 +2086,8 @@ move\\t%0,%z4\\n\\
(define_insn "anddi3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (and:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))]
+ (and:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
"*
{
@@ -1869,7 +2098,7 @@ move\\t%0,%z4\\n\\
[(set_attr "type" "darith")
(set_attr "mode" "DI")
(set (attr "length")
- (if_then_else (ge (symbol_ref "mips_isa") (const_int 3))
+ (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0))
(const_int 1)
(const_int 2)))])
@@ -1888,8 +2117,8 @@ move\\t%0,%z4\\n\\
(define_insn "anddi3_internal1"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (and:DI (match_operand:DI 1 "register_operand" "%d,d")
- (match_operand:DI 2 "uns_arith_operand" "d,K")))]
+ (and:DI (match_operand:DI 1 "se_register_operand" "%d,d")
+ (match_operand:DI 2 "se_uns_arith_operand" "d,K")))]
"TARGET_64BIT"
"@
and\\t%0,%1,%2
@@ -1915,8 +2144,8 @@ move\\t%0,%z4\\n\\
(define_insn "iordi3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ior:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))]
+ (ior:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
"*
{
@@ -1927,7 +2156,7 @@ move\\t%0,%z4\\n\\
[(set_attr "type" "darith")
(set_attr "mode" "DI")
(set (attr "length")
- (if_then_else (ge (symbol_ref "mips_isa") (const_int 3))
+ (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0))
(const_int 1)
(const_int 2)))])
@@ -1960,8 +2189,8 @@ move\\t%0,%z4\\n\\
;; the following xordi3_internal pattern.
(define_insn "xordi3"
[(set (match_operand:DI 0 "register_operand" "=d")
- (xor:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))]
+ (xor:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
"*
{
@@ -1972,7 +2201,7 @@ move\\t%0,%z4\\n\\
[(set_attr "type" "darith")
(set_attr "mode" "DI")
(set (attr "length")
- (if_then_else (ge (symbol_ref "mips_isa") (const_int 3))
+ (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0))
(const_int 1)
(const_int 2)))])
@@ -1991,14 +2220,54 @@ move\\t%0,%z4\\n\\
(define_insn "xordi3_immed"
[(set (match_operand:DI 0 "register_operand" "d")
- (xor:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "uns_arith_operand" "K")))]
+ (xor:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_uns_arith_operand" "K")))]
"TARGET_64BIT"
"xori\\t%0,%1,%x2"
[(set_attr "type" "arith")
(set_attr "mode" "DI")
(set_attr "length" "1")])
+(define_insn "*norsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "d"))
+ (not:SI (match_operand:SI 2 "register_operand" "d"))))]
+ ""
+ "nor\\t%0,%z1,%z2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
+(define_insn "*nordi3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (and:DI (not:DI (match_operand:DI 1 "se_register_operand" "d"))
+ (not:DI (match_operand:DI 2 "se_register_operand" "d"))))]
+ ""
+ "*
+{
+ if (TARGET_64BIT)
+ return \"nor\\t%0,%z1,%z2\";
+ return \"nor\\t%M0,%M1,%M2\;nor\\t%L0,%L1,%L2\";
+}"
+ [(set_attr "type" "darith")
+ (set_attr "mode" "DI")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_64BIT") (const_int 0))
+ (const_int 1)
+ (const_int 2)))])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (and:DI (not:DI (match_operand:DI 1 "register_operand" ""))
+ (not:DI (match_operand:DI 2 "register_operand" ""))))]
+ "reload_completed && !TARGET_64BIT && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE
+ && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))
+ && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))"
+
+ [(set (subreg:SI (match_dup 0) 0) (and:SI (not:SI (subreg:SI (match_dup 1) 0)) (not:SI (subreg:SI (match_dup 2) 0))))
+ (set (subreg:SI (match_dup 0) 1) (and:SI (not:SI (subreg:SI (match_dup 1) 1)) (not:SI (subreg:SI (match_dup 2) 1))))]
+ "")
;;
;; ....................
@@ -2018,7 +2287,7 @@ move\\t%0,%z4\\n\\
(define_insn "truncdisi2"
[(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI (match_operand:DI 1 "register_operand" "d")))]
+ (truncate:SI (match_operand:DI 1 "se_register_operand" "d")))]
"TARGET_64BIT"
"dsll\\t%0,%1,32\;dsra\\t%0,%0,32"
[(set_attr "type" "darith")
@@ -2027,7 +2296,7 @@ move\\t%0,%z4\\n\\
(define_insn "truncdihi2"
[(set (match_operand:HI 0 "register_operand" "=d")
- (truncate:HI (match_operand:DI 1 "register_operand" "d")))]
+ (truncate:HI (match_operand:DI 1 "se_register_operand" "d")))]
"TARGET_64BIT"
"andi\\t%0,%1,0xffff"
[(set_attr "type" "darith")
@@ -2036,7 +2305,7 @@ move\\t%0,%z4\\n\\
(define_insn "truncdiqi2"
[(set (match_operand:QI 0 "register_operand" "=d")
- (truncate:QI (match_operand:DI 1 "register_operand" "d")))]
+ (truncate:QI (match_operand:DI 1 "se_register_operand" "d")))]
"TARGET_64BIT"
"andi\\t%0,%1,0x00ff"
[(set_attr "type" "darith")
@@ -2046,7 +2315,7 @@ move\\t%0,%z4\\n\\
;; Combiner patterns to optimize shift/truncate combinations.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (truncate:SI (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "small_int" "I"))))]
"TARGET_64BIT"
"*
@@ -2070,7 +2339,7 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (truncate:SI (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "small_int" "I"))))]
"TARGET_64BIT"
"*
@@ -2096,7 +2365,7 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI (ashift:DI (match_operand:DI 1 "register_operand" "d")
+ (truncate:SI (ashift:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "small_int" "I"))))]
"TARGET_64BIT"
"*
@@ -2120,7 +2389,7 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (truncate:HI
- (match_operand:DI 1 "register_operand" "d"))))]
+ (match_operand:DI 1 "se_register_operand" "d"))))]
"TARGET_64BIT"
"andi\\t%0,%1,0xffff"
[(set_attr "type" "darith")
@@ -2130,7 +2399,7 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (truncate:QI
- (match_operand:DI 1 "register_operand" "d"))))]
+ (match_operand:DI 1 "se_register_operand" "d"))))]
"TARGET_64BIT"
"andi\\t%0,%1,0xff"
[(set_attr "type" "darith")
@@ -2140,7 +2409,7 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=d")
(zero_extend:HI (truncate:QI
- (match_operand:DI 1 "register_operand" "d"))))]
+ (match_operand:DI 1 "se_register_operand" "d"))))]
"TARGET_64BIT"
"andi\\t%0,%1,0xff"
[(set_attr "type" "darith")
@@ -2262,6 +2531,36 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "DI")
(set_attr "length" "1,1,2")])
+;; These can be created when a paradoxical subreg operand with an implicit
+;; sign_extend operator is reloaded. Because of the subreg, this is really
+;; a zero extend.
+;; ??? It might be possible to eliminate the need for these patterns by adding
+;; more support to reload for implicit sign_extend operators.
+(define_insn "*paradoxical_extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (sign_extend:DI
+ (subreg:SI (match_operand:HI 1 "memory_operand" "R,m") 0)))]
+ "TARGET_64BIT"
+ "*
+{
+ return mips_move_1word (operands, insn, TRUE);
+}"
+ [(set_attr "type" "load,load")
+ (set_attr "mode" "DI")
+ (set_attr "length" "1,2")])
+
+(define_insn "*paradoxical_extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (sign_extend:DI
+ (subreg:SI (match_operand:QI 1 "memory_operand" "R,m") 0)))]
+ "TARGET_64BIT"
+ "*
+{
+ return mips_move_1word (operands, insn, TRUE);
+}"
+ [(set_attr "type" "load,load")
+ (set_attr "mode" "DI")
+ (set_attr "length" "1,2")])
;;
;; ....................
@@ -2273,35 +2572,19 @@ move\\t%0,%z4\\n\\
;; Extension insns.
;; Those for integer source operand are ordered widest source type first.
-(define_expand "extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
- "TARGET_64BIT"
- "
-{
- if (optimize && GET_CODE (operands[1]) == MEM)
- operands[1] = force_not_mem (operands[1]);
-
- if (GET_CODE (operands[1]) != MEM)
- {
- rtx op1 = gen_lowpart (DImode, operands[1]);
- rtx temp = gen_reg_rtx (DImode);
- rtx shift = gen_rtx (CONST_INT, VOIDmode, 32);
-
- emit_insn (gen_ashldi3 (temp, op1, shift));
- emit_insn (gen_ashrdi3 (operands[0], temp, shift));
- DONE;
- }
-}")
+;; In 64 bit mode, 32 bit values in general registers are always
+;; correctly sign extended. That means that if the target is a
+;; general register, we can sign extend from SImode to DImode just by
+;; doing a move.
-(define_insn "extendsidi2_internal"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (sign_extend:DI (match_operand:SI 1 "memory_operand" "R,m")))]
+(define_insn "extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d,*d,d,d")
+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,*x,R,m")))]
"TARGET_64BIT"
"* return mips_move_1word (operands, insn, FALSE);"
- [(set_attr "type" "load")
+ [(set_attr "type" "move,hilo,load,load")
(set_attr "mode" "DI")
- (set_attr "length" "1,2")])
+ (set_attr "length" "1,1,1,2")])
;; These patterns originally accepted general_operands, however, slightly
;; better code is generated by only accepting register_operands, and then
@@ -2482,11 +2765,17 @@ move\\t%0,%z4\\n\\
;; operand zero, because then the address in the move instruction will be
;; clobbered. We mark the scratch register as early clobbered to prevent this.
+;; We need the ?X in alternative 1 so that it will be choosen only if the
+;; destination is a floating point register. Otherwise, alternative 1 can
+;; have lower cost than alternative 0 (because there is one less loser), and
+;; can be choosen when it won't work (because integral reloads into FP
+;; registers are not supported).
+
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "general_operand" "=d,*f,R,o")
(fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f")))
(clobber (match_scratch:SI 2 "=d,*d,&d,&d"))
- (clobber (match_scratch:DF 3 "=f,*X,f,f"))]
+ (clobber (match_scratch:DF 3 "=f,?*X,f,f"))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
@@ -2511,7 +2800,7 @@ move\\t%0,%z4\\n\\
[(set (match_operand:SI 0 "general_operand" "=d,*f,R,o")
(fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f")))
(clobber (match_scratch:SI 2 "=d,*d,&d,&d"))
- (clobber (match_scratch:SF 3 "=f,*X,f,f"))]
+ (clobber (match_scratch:SF 3 "=f,?*X,f,f"))]
"TARGET_HARD_FLOAT"
"*
{
@@ -2544,7 +2833,7 @@ move\\t%0,%z4\\n\\
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "general_operand" "=d,*f,R,o")
(fix:DI (match_operand:DF 1 "register_operand" "f,*f,f,f")))
- (clobber (match_scratch:DF 2 "=f,*X,f,f"))]
+ (clobber (match_scratch:DF 2 "=f,?*X,f,f"))]
"TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
"*
{
@@ -2571,7 +2860,7 @@ move\\t%0,%z4\\n\\
(define_insn "fix_truncsfdi2"
[(set (match_operand:DI 0 "general_operand" "=d,*f,R,o")
(fix:DI (match_operand:SF 1 "register_operand" "f,*f,f,f")))
- (clobber (match_scratch:DF 2 "=f,*X,f,f"))]
+ (clobber (match_scratch:DF 2 "=f,?*X,f,f"))]
"TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
"*
{
@@ -2611,7 +2900,7 @@ move\\t%0,%z4\\n\\
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=f,f,f")
- (float:DF (match_operand:DI 1 "nonimmediate_operand" "d,R,m")))]
+ (float:DF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))]
"TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
"*
{
@@ -2645,7 +2934,7 @@ move\\t%0,%z4\\n\\
(define_insn "floatdisf2"
[(set (match_operand:SF 0 "register_operand" "=f,f,f")
- (float:SF (match_operand:DI 1 "nonimmediate_operand" "d,R,m")))]
+ (float:SF (match_operand:DI 1 "se_nonimmediate_operand" "d,R,m")))]
"TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
"*
{
@@ -2869,6 +3158,9 @@ move\\t%0,%z4\\n\\
if (GET_CODE (operands[1]) != MEM)
FAIL;
+ /* Change the mode to BLKmode for aliasing purposes. */
+ operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0));
+
/* Otherwise, emit a lwl/lwr pair to load the value. */
emit_insn (gen_movsi_ulw (operands[0], operands[1]));
DONE;
@@ -2893,6 +3185,9 @@ move\\t%0,%z4\\n\\
if (GET_CODE (operands[1]) != MEM)
FAIL;
+ /* Change the mode to BLKmode for aliasing purposes. */
+ operands[1] = change_address (operands[1], BLKmode, XEXP (operands[1], 0));
+
/* Otherwise, emit a lwl/lwr pair to load the value. */
emit_insn (gen_movsi_ulw (operands[0], operands[1]));
DONE;
@@ -2917,6 +3212,9 @@ move\\t%0,%z4\\n\\
if (GET_CODE (operands[0]) != MEM)
FAIL;
+ /* Change the mode to BLKmode for aliasing purposes. */
+ operands[0] = change_address (operands[0], BLKmode, XEXP (operands[0], 0));
+
/* Otherwise, emit a swl/swr pair to load the value. */
emit_insn (gen_movsi_usw (operands[0], operands[3]));
DONE;
@@ -2926,7 +3224,7 @@ move\\t%0,%z4\\n\\
(define_insn "movsi_ulw"
[(set (match_operand:SI 0 "register_operand" "=&d,&d")
- (unspec [(match_operand:QI 1 "general_operand" "R,o")] 0))]
+ (unspec:SI [(match_operand:BLK 1 "general_operand" "R,o")] 0))]
""
"*
{
@@ -2954,8 +3252,8 @@ move\\t%0,%z4\\n\\
(set_attr "length" "2,4")])
(define_insn "movsi_usw"
- [(set (match_operand:QI 0 "memory_operand" "=R,o")
- (unspec [(match_operand:SI 1 "reg_or_0_operand" "dJ,dJ")] 1))]
+ [(set (match_operand:BLK 0 "memory_operand" "=R,o")
+ (unspec:BLK [(match_operand:SI 1 "reg_or_0_operand" "dJ,dJ")] 1))]
""
"*
{
@@ -2979,6 +3277,30 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "SI")
(set_attr "length" "2,4")])
+;; These two patterns support loading addresses with two instructions instead
+;; of using the macro instruction la.
+
+;; ??? mips_move_1word has support for HIGH, so this pattern may be
+;; unnecessary.
+
+(define_insn "high"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (high:SI (match_operand:SI 1 "immediate_operand" "")))]
+ "mips_split_addresses"
+ "lui\\t%0,%%hi(%1) # high"
+ [(set_attr "type" "move")
+ (set_attr "length" "1")])
+
+(define_insn "low"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "immediate_operand" "")))]
+ "mips_split_addresses"
+ "addiu\\t%0,%1,%%lo(%2) # low"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "length" "1")])
+
;; 64-bit integer moves
;; Unlike most other insns, the move insns can't be split with
@@ -2991,6 +3313,18 @@ move\\t%0,%z4\\n\\
""
"
{
+ if (mips_split_addresses && mips_check_split (operands[1], DImode))
+ {
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx tem = ((reload_in_progress | reload_completed)
+ ? operands[0] : gen_reg_rtx (mode));
+
+ emit_insn (gen_rtx (SET, VOIDmode, tem,
+ gen_rtx (HIGH, mode, operands[1])));
+
+ operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]);
+ }
+
/* If we are generating embedded PIC code, and we are referring to a
symbol in the .text section, we must use an offset from the start
of the function. */
@@ -3035,17 +3369,17 @@ move\\t%0,%z4\\n\\
}")
(define_insn "movdi_internal"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*d,*x")
- (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,*x,*d"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*x,*d,*x")
+ (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,J,*x,*d"))]
"!TARGET_64BIT
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)
|| (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0)
|| operands[1] == CONST0_RTX (DImode))"
"* return mips_move_2words (operands, insn); "
- [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo")
+ [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo,hilo")
(set_attr "mode" "DI")
- (set_attr "length" "2,4,2,4,2,4,2,2")])
+ (set_attr "length" "2,4,2,4,2,4,2,2,2")])
(define_split
[(set (match_operand:DI 0 "register_operand" "")
@@ -3059,17 +3393,17 @@ move\\t%0,%z4\\n\\
"")
(define_insn "movdi_internal2"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*x,*a")
- (match_operand:DI 1 "general_operand" " d,S,IKL,Mnis,R,m,dJ,dJ,*x,*d,*I"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*x,*d,*x,*a")
+ (match_operand:DI 1 "movdi_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,J,*x,*d,*J"))]
"TARGET_64BIT
&& (register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode)
+ || se_register_operand (operands[1], DImode)
|| (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0)
|| operands[1] == CONST0_RTX (DImode))"
"* return mips_move_2words (operands, insn); "
- [(set_attr "type" "move,load,arith,arith,load,load,store,store,hilo,hilo,hilo")
+ [(set_attr "type" "move,load,arith,arith,load,load,store,store,hilo,hilo,hilo,hilo")
(set_attr "mode" "DI")
- (set_attr "length" "1,2,1,2,1,2,1,2,1,1,2")])
+ (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,2")])
;; Handle input reloads in DImode.
;; This is mainly to handle reloading HILO_REGNUM. Note that we may
@@ -3082,7 +3416,7 @@ move\\t%0,%z4\\n\\
(define_expand "reload_indi"
[(set (match_operand:DI 0 "register_operand" "=b")
- (match_operand:DI 1 "general_operand" "b"))
+ (match_operand:DI 1 "movdi_operand" "b"))
(clobber (match_operand:TI 2 "register_operand" "=&d"))]
"TARGET_64BIT"
"
@@ -3147,7 +3481,7 @@ move\\t%0,%z4\\n\\
(define_expand "reload_outdi"
[(set (match_operand:DI 0 "general_operand" "=b")
- (match_operand:DI 1 "register_operand" "b"))
+ (match_operand:DI 1 "se_register_operand" "b"))
(clobber (match_operand:DI 2 "register_operand" "=&d"))]
"TARGET_64BIT"
"
@@ -3230,6 +3564,18 @@ move\\t%0,%z4\\n\\
""
"
{
+ if (mips_split_addresses && mips_check_split (operands[1], SImode))
+ {
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx tem = ((reload_in_progress | reload_completed)
+ ? operands[0] : gen_reg_rtx (mode));
+
+ emit_insn (gen_rtx (SET, VOIDmode, tem,
+ gen_rtx (HIGH, mode, operands[1])));
+
+ operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]);
+ }
+
/* If we are generating embedded PIC code, and we are referring to a
symbol in the .text section, we must use an offset from the start
of the function. */
@@ -3277,7 +3623,7 @@ move\\t%0,%z4\\n\\
(define_insn "movsi_internal1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*x,*d,*d")
- (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,I,*d,*x,*a"))]
+ (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,J,*d,*x,*a"))]
"TARGET_DEBUG_H_MODE
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
@@ -3289,7 +3635,7 @@ move\\t%0,%z4\\n\\
(define_insn "movsi_internal2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d")
- (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,I,*x,*d,*a"))]
+ (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,J,*x,*d,*a"))]
"!TARGET_DEBUG_H_MODE
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
@@ -3322,6 +3668,182 @@ move\\t%0,%z4\\n\\
DONE;
}")
+;; This insn handles moving CCmode values. It's really just a
+;; slightly simplified copy of movsi_internal2, with additional cases
+;; to move a condition register to a general register and to move
+;; between the general registers and the floating point registers.
+
+(define_insn "movcc"
+ [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*d,*R,*m,*d,*f,*f,*f,*f,*R,*m")
+ (match_operand:CC 1 "general_operand" "z,*d,*R,*m,*d,*d,*f,*d,*f,*R,*m,*f,*f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "* return mips_move_1word (operands, insn, FALSE);"
+ [(set_attr "type" "move,move,load,load,store,store,xfer,xfer,move,load,load,store,store")
+ (set_attr "mode" "SI")
+ (set_attr "length" "2,1,1,2,1,2,1,1,1,1,2,1,2")])
+
+;; Reload condition code registers. These need scratch registers.
+
+(define_expand "reload_incc"
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (match_operand:CC 1 "general_operand" "z"))
+ (clobber (match_operand:TF 2 "register_operand" "=&f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "
+{
+ rtx source;
+ rtx fp1, fp2;
+
+ /* This is called when are copying some value into a condition code
+ register. Operand 0 is the condition code register. Operand 1
+ is the source. Operand 2 is a scratch register; we use TFmode
+ because we actually need two floating point registers. */
+ if (! ST_REG_P (true_regnum (operands[0]))
+ || ! FP_REG_P (true_regnum (operands[2])))
+ abort ();
+
+ /* We need to get the source in SFmode so that the insn is
+ recognized. */
+ if (GET_CODE (operands[1]) == MEM)
+ source = change_address (operands[1], SFmode, NULL_RTX);
+ else if (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG)
+ source = gen_rtx (REG, SFmode, true_regnum (operands[1]));
+ else
+ source = operands[1];
+
+ fp1 = gen_rtx (REG, SFmode, REGNO (operands[2]));
+ fp2 = gen_rtx (REG, SFmode, REGNO (operands[2]) + 1);
+
+ emit_insn (gen_move_insn (fp1, source));
+ emit_insn (gen_move_insn (fp2, gen_rtx (REG, SFmode, 0)));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0],
+ gen_rtx (LT, CCmode, fp2, fp1)));
+
+ DONE;
+}")
+
+(define_expand "reload_outcc"
+ [(set (match_operand:CC 0 "general_operand" "=z")
+ (match_operand:CC 1 "register_operand" "z"))
+ (clobber (match_operand:CC 2 "register_operand" "=&d"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "
+{
+ /* This is called when we are copying a condition code register out
+ to save it somewhere. Operand 0 should be the location we are
+ going to save it to. Operand 1 should be the condition code
+ register. Operand 2 should be a scratch general purpose register
+ created for us by reload. The mips_secondary_reload_class
+ function should have told reload that we don't need a scratch
+ register if the destination is a general purpose register anyhow. */
+ if (ST_REG_P (true_regnum (operands[0]))
+ || GP_REG_P (true_regnum (operands[0]))
+ || ! ST_REG_P (true_regnum (operands[1]))
+ || ! GP_REG_P (true_regnum (operands[2])))
+ abort ();
+
+ /* All we have to do is copy the value from the condition code to
+ the data register, which movcc can handle, and then store the
+ value into the real final destination. */
+ emit_insn (gen_move_insn (operands[2], operands[1]));
+ emit_insn (gen_move_insn (operands[0], operands[2]));
+
+ DONE;
+}")
+
+;; MIPS4 supports loading and storing a floating point register from
+;; the sum of two general registers. We use two versions for each of
+;; these four instructions: one where the two general registers are
+;; SImode, and one where they are DImode. This is because general
+;; registers will be in SImode when they hold 32 bit values, but,
+;; since the 32 bit values are always sign extended, the [ls][wd]xc1
+;; instructions will still work correctly.
+
+;; ??? Perhaps it would be better to support these instructions by
+;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since
+;; these instructions can only be used to load and store floating
+;; point registers, that would probably cause trouble in reload.
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "lwxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (mem:SF (plus:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "lwxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "ldxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (mem:DF (plus:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d"))))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "ldxc1\\t%0,%1(%2)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (match_operand:SF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "swxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:SF (plus:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))
+ (match_operand:SF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "swxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")))
+ (match_operand:DF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "sdxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
+(define_insn ""
+ [(set (mem:DF (plus:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))
+ (match_operand:DF 0 "register_operand" "=f"))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "sdxc1\\t%0,%1(%2)"
+ [(set_attr "type" "store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "1")])
+
;; 16-bit Integer moves
;; Unlike most other insns, the move insns can't be split with
@@ -3553,7 +4075,7 @@ move\\t%0,%z4\\n\\
(define_insn "loadgp"
[(set (reg:DI 28)
- (unspec_volatile [(match_operand:DI 0 "address_operand" "")] 2))
+ (unspec_volatile:DI [(match_operand:DI 0 "address_operand" "")] 2))
(clobber (reg:DI 1))]
""
"%[lui\\t$1,%%hi(%%neg(%%gp_rel(%a0)))\\n\\taddiu\\t$1,$1,%%lo(%%neg(%%gp_rel(%a0)))\\n\\tdaddu\\t$gp,$1,$25%]"
@@ -3568,8 +4090,8 @@ move\\t%0,%z4\\n\\
;; Argument 3 is the alignment
(define_expand "movstrsi"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
- (mem:BLK (match_operand:BLK 1 "general_operand" "")))
+ [(parallel [(set (match_operand:BLK 0 "general_operand" "")
+ (match_operand:BLK 1 "general_operand" ""))
(use (match_operand:SI 2 "arith32_operand" ""))
(use (match_operand:SI 3 "immediate_operand" ""))])]
""
@@ -3585,8 +4107,8 @@ move\\t%0,%z4\\n\\
;; Insn generated by block moves
(define_insn "movstrsi_internal"
- [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination
- (match_operand:BLK 1 "memory_operand" "Ro")) ;; source
+ [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination
+ (match_operand:BLK 1 "memory_operand" "o")) ;; source
(clobber (match_scratch:SI 4 "=&d")) ;; temp 1
(clobber (match_scratch:SI 5 "=&d")) ;; temp 2
(clobber (match_scratch:SI 6 "=&d")) ;; temp 3
@@ -3596,7 +4118,7 @@ move\\t%0,%z4\\n\\
(use (const_int 0))] ;; normal block move
""
"* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);"
- [(set_attr "type" "multi")
+ [(set_attr "type" "store")
(set_attr "mode" "none")
(set_attr "length" "20")])
@@ -3644,8 +4166,8 @@ move\\t%0,%z4\\n\\
"")
(define_insn "movstrsi_internal2"
- [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination
- (match_operand:BLK 1 "memory_operand" "Ro")) ;; source
+ [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination
+ (match_operand:BLK 1 "memory_operand" "o")) ;; source
(clobber (match_scratch:SI 4 "=&d")) ;; temp 1
(clobber (match_scratch:SI 5 "=&d")) ;; temp 2
(clobber (match_scratch:SI 6 "=&d")) ;; temp 3
@@ -3655,7 +4177,7 @@ move\\t%0,%z4\\n\\
(use (const_int 1))] ;; all but last store
""
"* return output_block_move (insn, operands, 4, BLOCK_MOVE_NOT_LAST);"
- [(set_attr "type" "multi")
+ [(set_attr "type" "store")
(set_attr "mode" "none")
(set_attr "length" "20")])
@@ -3702,7 +4224,7 @@ move\\t%0,%z4\\n\\
(define_expand "ashldi3"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "register_operand" "")
+ (ashift:DI (match_operand:DI 1 "se_register_operand" "")
(match_operand:SI 2 "arith_operand" "")))
(clobber (match_dup 3))])]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
@@ -3895,7 +4417,7 @@ move\\t%0,%z4\\n\\
(define_insn "ashldi3_internal4"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ashift:DI (match_operand:DI 1 "register_operand" "d")
+ (ashift:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
"TARGET_64BIT"
"*
@@ -3929,7 +4451,7 @@ move\\t%0,%z4\\n\\
(define_expand "ashrdi3"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "")
(match_operand:SI 2 "arith_operand" "")))
(clobber (match_dup 3))])]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
@@ -4120,7 +4642,7 @@ move\\t%0,%z4\\n\\
(define_insn "ashrdi3_internal4"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (ashiftrt:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
"TARGET_64BIT"
"*
@@ -4154,7 +4676,7 @@ move\\t%0,%z4\\n\\
(define_expand "lshrdi3"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "")
(match_operand:SI 2 "arith_operand" "")))
(clobber (match_dup 3))])]
"TARGET_64BIT || !TARGET_DEBUG_G_MODE"
@@ -4346,7 +4868,7 @@ move\\t%0,%z4\\n\\
(define_insn "lshrdi3_internal4"
[(set (match_operand:DI 0 "register_operand" "=d")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (lshiftrt:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:SI 2 "arith_operand" "dI")))]
"TARGET_64BIT"
"*
@@ -4417,8 +4939,8 @@ move\\t%0,%z4\\n\\
(define_expand "cmpdi"
[(set (cc0)
- (compare:CC (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "arith_operand" "")))]
+ (compare:CC (match_operand:DI 0 "se_register_operand" "")
+ (match_operand:DI 1 "se_arith_operand" "")))]
"TARGET_64BIT"
"
{
@@ -4433,7 +4955,7 @@ move\\t%0,%z4\\n\\
(define_expand "tstdi"
[(set (cc0)
- (match_operand:DI 0 "register_operand" ""))]
+ (match_operand:DI 0 "se_register_operand" ""))]
"TARGET_64BIT"
"
{
@@ -4448,8 +4970,8 @@ move\\t%0,%z4\\n\\
(define_expand "cmpdf"
[(set (cc0)
- (compare:CC_FP (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" "")))]
+ (compare:CC (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "register_operand" "")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"
{
@@ -4464,8 +4986,8 @@ move\\t%0,%z4\\n\\
(define_expand "cmpsf"
[(set (cc0)
- (compare:CC_FP (match_operand:SF 0 "register_operand" "")
- (match_operand:SF 1 "register_operand" "")))]
+ (compare:CC (match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "register_operand" "")))]
"TARGET_HARD_FLOAT"
"
{
@@ -4488,31 +5010,15 @@ move\\t%0,%z4\\n\\
(define_insn "branch_fp_ne"
[(set (pc)
- (if_then_else (ne:CC_FP (reg:CC_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\";
-}"
- [(set_attr "type" "branch")
- (set_attr "mode" "none")
- (set_attr "length" "1")])
-
-(define_insn "branch_fp_ne_rev"
- [(set (pc)
- (if_then_else (ne:CC_REV_FP (reg:CC_REV_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
+ (if_then_else (ne:CC (match_operand:CC 0 "register_operand" "z")
+ (const_int 0))
+ (match_operand 1 "pc_or_label_operand" "")
+ (match_operand 2 "pc_or_label_operand" "")))]
"TARGET_HARD_FLOAT"
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\";
+ return (operands[1] != pc_rtx) ? \"%*bc1t%?\\t%Z0%1\" : \"%*bc1f%?\\t%Z0%2\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
@@ -4520,37 +5026,20 @@ move\\t%0,%z4\\n\\
(define_insn "branch_fp_eq"
[(set (pc)
- (if_then_else (eq:CC_FP (reg:CC_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\";
-}"
- [(set_attr "type" "branch")
- (set_attr "mode" "none")
- (set_attr "length" "1")])
-
-(define_insn "branch_fp_eq_rev"
- [(set (pc)
- (if_then_else (eq:CC_REV_FP (reg:CC_REV_FP 67)
- (const_int 0))
- (match_operand 0 "pc_or_label_operand" "")
- (match_operand 1 "pc_or_label_operand" "")))]
+ (if_then_else (eq:CC (match_operand:CC 0 "register_operand" "z")
+ (const_int 0))
+ (match_operand 1 "pc_or_label_operand" "")
+ (match_operand 2 "pc_or_label_operand" "")))]
"TARGET_HARD_FLOAT"
"*
{
mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
- return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\";
+ return (operands[1] != pc_rtx) ? \"%*bc1f%?\\t%Z0%1\" : \"%*bc1t%?\\t%Z0%2\";
}"
[(set_attr "type" "branch")
(set_attr "mode" "none")
(set_attr "length" "1")])
-
(define_insn "branch_zero"
[(set (pc)
(if_then_else (match_operator:SI 0 "cmp_op"
@@ -4599,7 +5088,7 @@ move\\t%0,%z4\\n\\
(define_insn "branch_zero_di"
[(set (pc)
(if_then_else (match_operator:DI 0 "cmp_op"
- [(match_operand:DI 1 "register_operand" "d")
+ [(match_operand:DI 1 "se_register_operand" "d")
(const_int 0)])
(match_operand 2 "pc_or_label_operand" "")
(match_operand 3 "pc_or_label_operand" "")))]
@@ -4664,8 +5153,8 @@ move\\t%0,%z4\\n\\
(define_insn "branch_equality_di"
[(set (pc)
(if_then_else (match_operator:DI 0 "equality_op"
- [(match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")])
+ [(match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")])
(match_operand 3 "pc_or_label_operand" "")
(match_operand 4 "pc_or_label_operand" "")))]
""
@@ -4683,8 +5172,8 @@ move\\t%0,%z4\\n\\
(define_expand "beq"
[(set (pc)
- (if_then_else (eq:CC_EQ (cc0)
- (const_int 0))
+ (if_then_else (eq:CC (cc0)
+ (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
@@ -4699,8 +5188,8 @@ move\\t%0,%z4\\n\\
(define_expand "bne"
[(set (pc)
- (if_then_else (ne:CC_EQ (cc0)
- (const_int 0))
+ (if_then_else (ne:CC (cc0)
+ (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
@@ -4889,7 +5378,7 @@ move\\t%0,%z4\\n\\
(define_insn "seq_di_zero"
[(set (match_operand:DI 0 "register_operand" "=d")
- (eq:DI (match_operand:DI 1 "register_operand" "d")
+ (eq:DI (match_operand:DI 1 "se_register_operand" "d")
(const_int 0)))]
"TARGET_64BIT"
"sltu\\t%0,%1,1"
@@ -4925,8 +5414,8 @@ move\\t%0,%z4\\n\\
(define_insn "seq_di"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (eq:DI (match_operand:DI 1 "register_operand" "%d,d")
- (match_operand:DI 2 "uns_arith_operand" "d,K")))]
+ (eq:DI (match_operand:DI 1 "se_register_operand" "%d,d")
+ (match_operand:DI 2 "se_uns_arith_operand" "d,K")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE"
"@
xor\\t%0,%1,%2\;sltu\\t%0,%0,1
@@ -4937,8 +5426,8 @@ move\\t%0,%z4\\n\\
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (eq:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "uns_arith_operand" "")))]
+ (eq:DI (match_operand:DI 1 "se_register_operand" "")
+ (match_operand:DI 2 "se_uns_arith_operand" "")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE
&& (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)"
[(set (match_dup 0)
@@ -4987,7 +5476,7 @@ move\\t%0,%z4\\n\\
(define_insn "sne_di_zero"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ne:DI (match_operand:DI 1 "register_operand" "d")
+ (ne:DI (match_operand:DI 1 "se_register_operand" "d")
(const_int 0)))]
"TARGET_64BIT"
"sltu\\t%0,%.,%1"
@@ -5023,8 +5512,8 @@ move\\t%0,%z4\\n\\
(define_insn "sne_di"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (ne:DI (match_operand:DI 1 "register_operand" "%d,d")
- (match_operand:DI 2 "uns_arith_operand" "d,K")))]
+ (ne:DI (match_operand:DI 1 "se_register_operand" "%d,d")
+ (match_operand:DI 2 "se_uns_arith_operand" "d,K")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE"
"@
xor\\t%0,%1,%2\;sltu\\t%0,%.,%0
@@ -5035,8 +5524,8 @@ move\\t%0,%z4\\n\\
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (ne:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "uns_arith_operand" "")))]
+ (ne:DI (match_operand:DI 1 "se_register_operand" "")
+ (match_operand:DI 2 "se_uns_arith_operand" "")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE
&& (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)"
[(set (match_dup 0)
@@ -5085,8 +5574,8 @@ move\\t%0,%z4\\n\\
(define_insn "sgt_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (gt:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "reg_or_0_operand" "dJ")))]
+ (gt:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_reg_or_0_operand" "dJ")))]
"TARGET_64BIT"
"slt\\t%0,%z2,%1"
[(set_attr "type" "arith")
@@ -5141,8 +5630,8 @@ move\\t%0,%z4\\n\\
(define_insn "sge_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ge:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "arith_operand" "dI")))]
+ (ge:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_arith_operand" "dI")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE"
"slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001"
[(set_attr "type" "arith")
@@ -5151,8 +5640,8 @@ move\\t%0,%z4\\n\\
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (ge:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "arith_operand" "")))]
+ (ge:DI (match_operand:DI 1 "se_register_operand" "")
+ (match_operand:DI 2 "se_arith_operand" "")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
(lt:DI (match_dup 1)
@@ -5197,8 +5686,8 @@ move\\t%0,%z4\\n\\
(define_insn "slt_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (lt:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "arith_operand" "dI")))]
+ (lt:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_arith_operand" "dI")))]
"TARGET_64BIT"
"slt\\t%0,%1,%2"
[(set_attr "type" "arith")
@@ -5247,7 +5736,7 @@ move\\t%0,%z4\\n\\
(define_insn "sle_di_const"
[(set (match_operand:DI 0 "register_operand" "=d")
- (le:DI (match_operand:DI 1 "register_operand" "d")
+ (le:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "small_int" "I")))]
"TARGET_64BIT && INTVAL (operands[2]) < 32767"
"*
@@ -5284,8 +5773,8 @@ move\\t%0,%z4\\n\\
(define_insn "sle_di_reg"
[(set (match_operand:DI 0 "register_operand" "=d")
- (le:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))]
+ (le:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE"
"slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001"
[(set_attr "type" "arith")
@@ -5294,8 +5783,8 @@ move\\t%0,%z4\\n\\
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (le:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" "")))]
+ (le:DI (match_operand:DI 1 "se_register_operand" "")
+ (match_operand:DI 2 "se_register_operand" "")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
(lt:DI (match_dup 2)
@@ -5343,8 +5832,8 @@ move\\t%0,%z4\\n\\
(define_insn "sgtu_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (gtu:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "reg_or_0_operand" "dJ")))]
+ (gtu:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_reg_or_0_operand" "dJ")))]
"TARGET_64BIT"
"sltu\\t%0,%z2,%1"
[(set_attr "type" "arith")
@@ -5399,8 +5888,8 @@ move\\t%0,%z4\\n\\
(define_insn "sgeu_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (geu:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "arith_operand" "dI")))]
+ (geu:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_arith_operand" "dI")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE"
"sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001"
[(set_attr "type" "arith")
@@ -5409,8 +5898,8 @@ move\\t%0,%z4\\n\\
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (geu:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "arith_operand" "")))]
+ (geu:DI (match_operand:DI 1 "se_register_operand" "")
+ (match_operand:DI 2 "se_arith_operand" "")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
(ltu:DI (match_dup 1)
@@ -5455,8 +5944,8 @@ move\\t%0,%z4\\n\\
(define_insn "sltu_di"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ltu:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "arith_operand" "dI")))]
+ (ltu:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_arith_operand" "dI")))]
"TARGET_64BIT"
"sltu\\t%0,%1,%2"
[(set_attr "type" "arith")
@@ -5505,7 +5994,7 @@ move\\t%0,%z4\\n\\
(define_insn "sleu_di_const"
[(set (match_operand:DI 0 "register_operand" "=d")
- (leu:DI (match_operand:DI 1 "register_operand" "d")
+ (leu:DI (match_operand:DI 1 "se_register_operand" "d")
(match_operand:DI 2 "small_int" "I")))]
"TARGET_64BIT && INTVAL (operands[2]) < 32767"
"*
@@ -5542,8 +6031,8 @@ move\\t%0,%z4\\n\\
(define_insn "sleu_di_reg"
[(set (match_operand:DI 0 "register_operand" "=d")
- (leu:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "register_operand" "d")))]
+ (leu:DI (match_operand:DI 1 "se_register_operand" "d")
+ (match_operand:DI 2 "se_register_operand" "d")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE"
"sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001"
[(set_attr "type" "arith")
@@ -5552,8 +6041,8 @@ move\\t%0,%z4\\n\\
(define_split
[(set (match_operand:DI 0 "register_operand" "")
- (leu:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" "")))]
+ (leu:DI (match_operand:DI 1 "se_register_operand" "")
+ (match_operand:DI 2 "se_register_operand" "")))]
"TARGET_64BIT && TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE"
[(set (match_dup 0)
(ltu:DI (match_dup 2)
@@ -5572,216 +6061,130 @@ move\\t%0,%z4\\n\\
;; ....................
(define_insn "seq_df"
- [(set (reg:CC_FP 67)
- (eq:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
- "*
-{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
-}"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "FPSW")
- (set_attr "length" "1")])
-
-(define_insn "sne_df"
- [(set (reg:CC_REV_FP 67)
- (ne:CC_REV_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (eq:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.eq.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "slt_df"
- [(set (reg:CC_FP 67)
- (lt:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (lt:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.lt.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.lt.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sle_df"
- [(set (reg:CC_FP 67)
- (le:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (le:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.le.d\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.le.d\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sgt_df"
- [(set (reg:CC_FP 67)
- (gt:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (gt:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.lt.d\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.lt.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sge_df"
- [(set (reg:CC_FP 67)
- (ge:CC_FP (match_operand:DF 0 "register_operand" "f")
- (match_operand:DF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (ge:CC (match_operand:DF 1 "register_operand" "f")
+ (match_operand:DF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.le.d\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.le.d\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "seq_sf"
- [(set (reg:CC_FP 67)
- (eq:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (eq:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
-}"
- [(set_attr "type" "fcmp")
- (set_attr "mode" "FPSW")
- (set_attr "length" "1")])
-
-(define_insn "sne_sf"
- [(set (reg:CC_REV_FP 67)
- (ne:CC_REV_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "*
-{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.eq.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "slt_sf"
- [(set (reg:CC_FP 67)
- (lt:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (lt:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.lt.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.lt.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sle_sf"
- [(set (reg:CC_FP 67)
- (le:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (le:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.le.s\\t%0,%1\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.le.s\\t%Z0%1,%2\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sgt_sf"
- [(set (reg:CC_FP 67)
- (gt:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (gt:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.lt.s\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.lt.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
(set_attr "length" "1")])
(define_insn "sge_sf"
- [(set (reg:CC_FP 67)
- (ge:CC_FP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (ge:CC (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
"TARGET_HARD_FLOAT"
"*
{
- rtx xoperands[10];
- xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- xoperands[1] = operands[0];
- xoperands[2] = operands[1];
-
- return mips_fill_delay_slot (\"c.le.s\\t%1,%0\", DELAY_FCMP, xoperands, insn);
+ return mips_fill_delay_slot (\"c.le.s\\t%Z0%2,%1\", DELAY_FCMP, operands, insn);
}"
[(set_attr "type" "fcmp")
(set_attr "mode" "FPSW")
@@ -5808,7 +6211,7 @@ move\\t%0,%z4\\n\\
/* ??? I don't know why this is necessary. This works around an
assembler problem that appears when a label is defined, then referenced
in a switch table, then used in a `j' instruction. */
- else if (ABI_64BIT && mips_isa >= 3)
+ else if (mips_abi != ABI_32)
return \"%*b\\t%l0\";
else
return \"%*j\\t%l0\";
@@ -5848,7 +6251,7 @@ move\\t%0,%z4\\n\\
(set_attr "length" "1")])
(define_insn "indirect_jump_internal2"
- [(set (pc) (match_operand:DI 0 "register_operand" "d"))]
+ [(set (pc) (match_operand:DI 0 "se_register_operand" "d"))]
"TARGET_LONG64"
"%*j\\t%0"
[(set_attr "type" "jump")
@@ -5869,10 +6272,20 @@ move\\t%0,%z4\\n\\
if (GET_MODE (operands[0]) != Pmode)
abort ();
- if (!TARGET_LONG64)
- emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));
+ if (! flag_pic)
+ {
+ if (!TARGET_LONG64)
+ emit_jump_insn (gen_tablejump_internal1 (operands[0], operands[1]));
+ else
+ emit_jump_insn (gen_tablejump_internal2 (operands[0], operands[1]));
+ }
else
- emit_jump_insn (gen_tablejump_internal2 (operands[0], operands[1]));
+ {
+ if (!TARGET_LONG64)
+ emit_jump_insn (gen_tablejump_internal3 (operands[0], operands[1]));
+ else
+ emit_jump_insn (gen_tablejump_internal4 (operands[0], operands[1]));
+ }
DONE;
}
@@ -5883,58 +6296,69 @@ move\\t%0,%z4\\n\\
(match_operand:SI 0 "register_operand" "d"))
(use (label_ref (match_operand 1 "" "")))]
"!TARGET_LONG64"
- "*
-{
- /* .cpadd expands to add REG,REG,$gp when pic, and nothing when not pic. */
- if (TARGET_ABICALLS && (! ABI_64BIT || mips_isa < 3))
- output_asm_insn (\".cpadd\\t%0\", operands);
- return \"%*j\\t%0\";
-}"
+ "%*j\\t%0"
[(set_attr "type" "jump")
(set_attr "mode" "none")
- (set (attr "length")
- (if_then_else (eq_attr "abicalls" "yes")
- (const_int 2)
- (const_int 1)))])
+ (set_attr "length" "1")])
(define_insn "tablejump_internal2"
[(set (pc)
- (match_operand:DI 0 "register_operand" "d"))
+ (match_operand:DI 0 "se_register_operand" "d"))
(use (label_ref (match_operand 1 "" "")))]
"TARGET_LONG64"
+ "%*j\\t%0"
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")
+ (set_attr "length" "1")])
+
+(define_expand "tablejump_internal3"
+ [(set (pc)
+ (plus:SI (match_operand:SI 0 "register_operand" "d")
+ (label_ref:SI (match_operand:SI 1 "" ""))))]
+ ""
+ "")
+
+;;; Make sure that this only matches the insn before ADDR_DIFF_VEC. Otherwise
+;;; it is not valid.
+
+;;; ??? The length depends on the ABI. It is two for o32, and one for n32.
+;;; We just use the conservative number here.
+
+(define_insn ""
+ [(set (pc)
+ (plus:SI (match_operand:SI 0 "register_operand" "d")
+ (label_ref:SI (match_operand:SI 1 "" ""))))]
+ "!TARGET_LONG64 && next_active_insn (insn) != 0
+ && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
+ && PREV_INSN (next_active_insn (insn)) == operands[1]"
"*
{
- /* .cpdadd expands to dadd REG,REG,$gp when pic, and nothing when not pic. */
- /* ??? SGI as does not have a .cpdadd. */
- if (TARGET_ABICALLS && (! ABI_64BIT || mips_isa < 3))
+ /* .cpadd expands to add REG,REG,$gp when pic, and nothing when not pic. */
+ if (mips_abi == ABI_32)
output_asm_insn (\".cpadd\\t%0\", operands);
return \"%*j\\t%0\";
}"
[(set_attr "type" "jump")
(set_attr "mode" "none")
- (set (attr "length")
- (if_then_else (eq_attr "abicalls" "yes")
- (const_int 2)
- (const_int 1)))])
-
-;; Function return, only allow after optimization, so that we can
-;; eliminate jumps to jumps if no stack space is used.
-
-;; (define_expand "return"
-;; [(set (pc) (reg:SI 31))]
-;; "simple_epilogue_p ()"
-;; "")
-
-(define_expand "return"
- [(parallel [(return)
- (use (reg:SI 31))])]
- "simple_epilogue_p ()"
- "")
+ (set_attr "length" "2")])
-(define_insn "return_internal"
- [(parallel [(return)
- (use (match_operand:SI 0 "register_operand" "d"))])]
+(define_expand "tablejump_internal4"
+ [(set (pc)
+ (plus:DI (match_operand:DI 0 "se_register_operand" "d")
+ (label_ref:DI (match_operand:SI 1 "" ""))))]
""
+ "")
+
+;;; Make sure that this only matches the insn before ADDR_DIFF_VEC. Otherwise
+;;; it is not valid.
+
+(define_insn ""
+ [(set (pc)
+ (plus:DI (match_operand:DI 0 "se_register_operand" "d")
+ (label_ref:DI (match_operand:SI 1 "" ""))))]
+ "TARGET_LONG64 && next_active_insn (insn) != 0
+ && GET_CODE (PATTERN (next_active_insn (insn))) == ADDR_DIFF_VEC
+ && PREV_INSN (next_active_insn (insn)) == operands[1]"
"%*j\\t%0"
[(set_attr "type" "jump")
(set_attr "mode" "none")
@@ -6017,6 +6441,36 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "6")])
+;; ??? This is a hack to work around a problem with expand_builtin_setjmp.
+;; It restores the frame pointer, and then does a call to restore the global
+;; pointer (gp) register. The call insn implicitly (via the assembler) reloads
+;; gp from the stack. However, call insns do not depend on $fp, so it is
+;; possible for the instruction scheduler to move the fp restore after the
+;; call, which then causes gp to be corrupted. We fix this by emitting a
+;; scheduler barrier. A better fix is to put code here that restores the
+;; $gp, and then the call is unnecessary. This is only a problem when PIC
+;; (TARGET_ABICALLS), and only when the gp register is caller-saved
+;; (irix5/o32, but not irix6/n32/n64).
+
+(define_expand "nonlocal_goto_receiver"
+ [(const_int 0)]
+ ""
+ "
+{
+ emit_insn (gen_blockage ());
+}")
+
+;; For n32/n64, we need to restore gp after a builtin setjmp. We do this
+;; by making use of the fact that we've just called __dummy.
+
+(define_expand "builtin_setjmp_receiver"
+ [(const_int 0)]
+ "TARGET_ABICALLS && mips_abi != ABI_32"
+ "
+{
+ emit_insn (gen_loadgp (gen_rtx (SYMBOL_REF, Pmode, \"__dummy\")));
+ emit_insn (gen_blockage ());
+}")
;;
;; ....................
@@ -6050,21 +6504,38 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "0")])
-;; At present, don't expand the epilogue, reorg.c will clobber the
-;; return register in compiling gen_lowpart (emit-rtl.c).
-;;
-;; (define_expand "epilogue"
-;; [(const_int 2)]
-;; ""
-;; "
-;; {
-;; if (mips_isa >= 0) /* avoid unused code warnings */
-;; {
-;; mips_expand_epilogue ();
-;; DONE;
-;; }
-;; }")
+(define_expand "epilogue"
+ [(const_int 2)]
+ ""
+ "
+{
+ if (mips_isa >= 0) /* avoid unused code warnings */
+ {
+ mips_expand_epilogue ();
+ DONE;
+ }
+}")
+
+;; Trivial return. Make it look like a normal return insn as that
+;; allows jump optimizations to work better .
+(define_insn "return"
+ [(return)]
+ "mips_can_use_return_insn ()"
+ "%*j\\t$31"
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")
+ (set_attr "length" "1")])
+;; Normal return.
+(define_insn "return_internal"
+ [(use (reg:SI 31))
+ (return)]
+ ""
+ "%*j\\t$31"
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")
+ (set_attr "length" "1")])
+
;; When generating embedded PIC code we need to get the address of the
;; current function. This specialized instruction does just that.
@@ -6104,7 +6575,7 @@ move\\t%0,%z4\\n\\
{
addr = XEXP (operands[0], 0);
if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS))
- || ! call_insn_operand (operands[0], VOIDmode))
+ || ! call_insn_operand (addr, VOIDmode))
XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);
/* In order to pass small structures by value in registers
@@ -6124,66 +6595,61 @@ move\\t%0,%z4\\n\\
emit_insn (RTVEC_ELT (adjust, i));
}
- emit_call_insn (gen_call_internal1 (operands[0], operands[1],
+ emit_call_insn (gen_call_internal0 (operands[0], operands[1],
gen_rtx (REG, SImode, GP_REG_FIRST + 31)));
DONE;
}
}")
+(define_expand "call_internal0"
+ [(parallel [(call (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (clobber (match_operand:SI 2 "" ""))])]
+ ""
+ "")
+
(define_insn "call_internal1"
- [(call (match_operand 0 "call_insn_operand" "m")
+ [(call (mem (match_operand 0 "call_insn_operand" "ri"))
(match_operand 1 "" "i"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
"!TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
- register rtx target = XEXP (operands[0], 0);
+ register rtx target = operands[0];
if (GET_CODE (target) == SYMBOL_REF)
return \"%*jal\\t%0\";
-
else if (GET_CODE (target) == CONST_INT)
- {
- operands[0] = target;
- return \"%[li\\t%@,%0\\n\\t%*jal\\t%2,%@%]\";
- }
-
+ return \"%[li\\t%@,%0\\n\\t%*jal\\t%2,%@%]\";
else
- {
- operands[0] = target;
- return \"%*jal\\t%2,%0\";
- }
+ return \"%*jal\\t%2,%0\";
}"
[(set_attr "type" "call")
(set_attr "mode" "none")
(set_attr "length" "1")])
(define_insn "call_internal2"
- [(call (match_operand 0 "call_insn_operand" "m")
+ [(call (mem (match_operand 0 "call_insn_operand" "ri"))
(match_operand 1 "" "i"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
- register rtx target = XEXP (operands[0], 0);
+ register rtx target = operands[0];
if (GET_CODE (target) == SYMBOL_REF)
- return \"jal\\t%0\";
-
- else if (GET_CODE (target) == CONST_INT)
- {
- operands[0] = target;
- return \"li\\t%^,%0\\n\\tjal\\t%2,%^\";
- }
-
- else
{
- operands[0] = target;
- if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM)
- return \"move\\t%^,%0\\n\\tjal\\t%2,%^\";
+ if (GET_MODE (target) == SImode)
+ return \"la\\t%^,%0\\n\\tjal\\t%2,%^\";
else
- return \"jal\\t%2,%0\";
+ return \"dla\\t%^,%0\\n\\tjal\\t%2,%^\";
}
+ else if (GET_CODE (target) == CONST_INT)
+ return \"li\\t%^,%0\\n\\tjal\\t%2,%^\";
+ else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM)
+ return \"move\\t%^,%0\\n\\tjal\\t%2,%^\";
+ else
+ return \"jal\\t%2,%0\";
}"
[(set_attr "type" "call")
(set_attr "mode" "none")
@@ -6200,7 +6666,7 @@ move\\t%0,%z4\\n\\
(set_attr "length" "1")])
(define_insn "call_internal3b"
- [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
+ [(call (mem:DI (match_operand:DI 0 "se_register_operand" "r"))
(match_operand 1 "" "i"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
"TARGET_LONG64 && !TARGET_ABICALLS && TARGET_LONG_CALLS"
@@ -6226,7 +6692,7 @@ move\\t%0,%z4\\n\\
(set_attr "length" "2")])
(define_insn "call_internal4b"
- [(call (mem:DI (match_operand:DI 0 "register_operand" "r"))
+ [(call (mem:DI (match_operand:DI 0 "se_register_operand" "r"))
(match_operand 1 "" "i"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
"TARGET_LONG64 && TARGET_ABICALLS && TARGET_LONG_CALLS"
@@ -6258,7 +6724,7 @@ move\\t%0,%z4\\n\\
{
addr = XEXP (operands[1], 0);
if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS))
- || ! call_insn_operand (operands[1], VOIDmode))
+ || ! call_insn_operand (addr, VOIDmode))
XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);
/* In order to pass small structures by value in registers
@@ -6278,38 +6744,54 @@ move\\t%0,%z4\\n\\
emit_insn (RTVEC_ELT (adjust, i));
}
- emit_call_insn (gen_call_value_internal1 (operands[0], operands[1], operands[2],
+ /* Handle Irix6 function calls that have multiple non-contiguous
+ results. */
+ if (GET_CODE (operands[0]) == PARALLEL && XVECLEN (operands[0], 0) > 1)
+ {
+ emit_call_insn (gen_call_value_multiple_internal0
+ (XEXP (XVECEXP (operands[0], 0, 0), 0),
+ operands[1], operands[2],
+ XEXP (XVECEXP (operands[0], 0, 1), 0),
+ gen_rtx (REG, SImode, GP_REG_FIRST + 31)));
+ DONE;
+ }
+
+ /* We have a call returning a DImode structure in an FP reg.
+ Strip off the now unnecessary PARALLEL. */
+ if (GET_CODE (operands[0]) == PARALLEL)
+ operands[0] = XEXP (XVECEXP (operands[0], 0, 0), 0);
+
+ emit_call_insn (gen_call_value_internal0 (operands[0], operands[1], operands[2],
gen_rtx (REG, SImode, GP_REG_FIRST + 31)));
DONE;
}
-
}")
+(define_expand "call_value_internal0"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))
+ (clobber (match_operand:SI 3 "" ""))])]
+ ""
+ "")
+
(define_insn "call_value_internal1"
[(set (match_operand 0 "register_operand" "=df")
- (call (match_operand 1 "call_insn_operand" "m")
+ (call (mem (match_operand 1 "call_insn_operand" "ri"))
(match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
"!TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
- register rtx target = XEXP (operands[1], 0);
+ register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF)
return \"%*jal\\t%1\";
-
else if (GET_CODE (target) == CONST_INT)
- {
- operands[1] = target;
- return \"%[li\\t%@,%1\\n\\t%*jal\\t%3,%@%]\";
- }
-
+ return \"%[li\\t%@,%1\\n\\t%*jal\\t%3,%@%]\";
else
- {
- operands[1] = target;
- return \"%*jal\\t%3,%1\";
- }
+ return \"%*jal\\t%3,%1\";
}"
[(set_attr "type" "call")
(set_attr "mode" "none")
@@ -6317,31 +6799,27 @@ move\\t%0,%z4\\n\\
(define_insn "call_value_internal2"
[(set (match_operand 0 "register_operand" "=df")
- (call (match_operand 1 "call_insn_operand" "m")
+ (call (mem (match_operand 1 "call_insn_operand" "ri"))
(match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
- register rtx target = XEXP (operands[1], 0);
+ register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF)
- return \"jal\\t%1\";
-
- else if (GET_CODE (target) == CONST_INT)
- {
- operands[1] = target;
- return \"li\\t%^,%1\\n\\tjal\\t%3,%^\";
- }
-
- else
{
- operands[1] = target;
- if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM)
- return \"move\\t%^,%1\\n\\tjal\\t%3,%^\";
+ if (GET_MODE (target) == SImode)
+ return \"la\\t%^,%1\\n\\tjal\\t%3,%^\";
else
- return \"jal\\t%3,%1\";
+ return \"dla\\t%^,%1\\n\\tjal\\t%3,%^\";
}
+ else if (GET_CODE (target) == CONST_INT)
+ return \"li\\t%^,%1\\n\\tjal\\t%3,%^\";
+ else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM)
+ return \"move\\t%^,%1\\n\\tjal\\t%3,%^\";
+ else
+ return \"jal\\t%3,%1\";
}"
[(set_attr "type" "call")
(set_attr "mode" "none")
@@ -6360,7 +6838,7 @@ move\\t%0,%z4\\n\\
(define_insn "call_value_internal3b"
[(set (match_operand 0 "register_operand" "=df")
- (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
+ (call (mem:DI (match_operand:DI 1 "se_register_operand" "r"))
(match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
"TARGET_LONG64 && !TARGET_ABICALLS && TARGET_LONG_CALLS"
@@ -6388,7 +6866,7 @@ move\\t%0,%z4\\n\\
(define_insn "call_value_internal4b"
[(set (match_operand 0 "register_operand" "=df")
- (call (mem:DI (match_operand:DI 1 "register_operand" "r"))
+ (call (mem:DI (match_operand:DI 1 "se_register_operand" "r"))
(match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
"TARGET_LONG64 && TARGET_ABICALLS && TARGET_LONG_CALLS"
@@ -6403,6 +6881,52 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "2")])
+(define_expand "call_value_multiple_internal0"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))
+ (set (match_operand 3 "" "")
+ (call (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_operand:SI 4 "" ""))])]
+ ""
+ "")
+
+;; ??? May eventually need all 6 versions of the call patterns with multiple
+;; return values.
+
+(define_insn "call_value_multiple_internal2"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem (match_operand 1 "call_insn_operand" "ri"))
+ (match_operand 2 "" "i")))
+ (set (match_operand 3 "register_operand" "=df")
+ (call (mem (match_dup 1))
+ (match_dup 2)))
+ (clobber (match_operand:SI 4 "register_operand" "=d"))]
+ "TARGET_ABICALLS && !TARGET_LONG_CALLS"
+ "*
+{
+ register rtx target = operands[1];
+
+ if (GET_CODE (target) == SYMBOL_REF)
+ {
+ if (GET_MODE (target) == SImode)
+ return \"la\\t%^,%1\\n\\tjal\\t%4,%^\";
+ else
+ return \"la\\t%^,%1\\n\\tjal\\t%4,%^\";
+ }
+ else if (GET_CODE (target) == CONST_INT)
+ return \"li\\t%^,%1\\n\\tjal\\t%4,%^\";
+ else if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM)
+ return \"move\\t%^,%1\\n\\tjal\\t%4,%^\";
+ else
+ return \"jal\\t%4,%1\";
+}"
+ [(set_attr "type" "call")
+ (set_attr "mode" "none")
+ (set_attr "length" "2")])
+
+
;; Call subroutine returning any type.
(define_expand "untyped_call"
@@ -6446,18 +6970,21 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(set_attr "length" "1")])
-(define_expand "probe"
- [(set (match_dup 0)
- (match_dup 1))]
- ""
- "
-{
- operands[0] = gen_reg_rtx (SImode);
- operands[1] = gen_rtx (MEM, SImode, stack_pointer_rtx);
- MEM_VOLATILE_P (operands[1]) = TRUE;
-
- /* fall through and generate default code */
-}")
+;; The MIPS chip does not seem to require stack probes.
+;;
+;; (define_expand "probe"
+;; [(set (match_dup 0)
+;; (match_dup 1))]
+;; ""
+;; "
+;; {
+;; operands[0] = gen_reg_rtx (SImode);
+;; operands[1] = gen_rtx (MEM, SImode, stack_pointer_rtx);
+;; MEM_VOLATILE_P (operands[1]) = TRUE;
+;;
+;; /* fall through and generate default code */
+;; }")
+;;
;;
;; MIPS4 Conditional move instructions.
@@ -6480,13 +7007,31 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,d")
(if_then_else:SI
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
+ (match_operator 4 "equality_op"
+ [(match_operand:DI 1 "se_register_operand" "d,d")
+ (const_int 0)])
+ (match_operand:SI 2 "reg_or_0_operand" "dJ,0")
+ (match_operand:SI 3 "reg_or_0_operand" "0,dJ")))]
+ "mips_isa >= 4"
+ "@
+ mov%B4\\t%0,%z2,%1
+ mov%b4\\t%0,%z3,%1"
+ [(set_attr "type" "move")
+ (set_attr "mode" "SI")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (if_then_else:SI
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
(match_operand:SI 1 "reg_or_0_operand" "dJ,0")
(match_operand:SI 2 "reg_or_0_operand" "0,dJ")))]
- "mips_isa >= 4"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
"@
- mov%T3\\t%0,%z1,$fcc0
- mov%t3\\t%0,%z2,$fcc0"
+ mov%T3\\t%0,%z1,%4
+ mov%t3\\t%0,%z2,%4"
[(set_attr "type" "move")
(set_attr "mode" "SI")])
@@ -6494,10 +7039,10 @@ move\\t%0,%z4\\n\\
[(set (match_operand:DI 0 "register_operand" "=d,d")
(if_then_else:DI
(match_operator 4 "equality_op"
- [(match_operand:DI 1 "register_operand" "d,d")
+ [(match_operand:SI 1 "register_operand" "d,d")
(const_int 0)])
- (match_operand:DI 2 "reg_or_0_operand" "dJ,0")
- (match_operand:DI 3 "reg_or_0_operand" "0,dJ")))]
+ (match_operand:DI 2 "se_reg_or_0_operand" "dJ,0")
+ (match_operand:DI 3 "se_reg_or_0_operand" "0,dJ")))]
"mips_isa >= 4"
"@
mov%B4\\t%0,%z2,%1
@@ -6508,13 +7053,31 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d,d")
(if_then_else:DI
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
- (match_operand:DI 1 "reg_or_0_operand" "dJ,0")
- (match_operand:DI 2 "reg_or_0_operand" "0,dJ")))]
+ (match_operator 4 "equality_op"
+ [(match_operand:DI 1 "se_register_operand" "d,d")
+ (const_int 0)])
+ (match_operand:DI 2 "se_reg_or_0_operand" "dJ,0")
+ (match_operand:DI 3 "se_reg_or_0_operand" "0,dJ")))]
"mips_isa >= 4"
"@
- mov%T3\\t%0,%z1,$fcc0
- mov%t3\\t%0,%z2,$fcc0"
+ mov%B4\\t%0,%z2,%1
+ mov%b4\\t%0,%z3,%1"
+ [(set_attr "type" "move")
+ (set_attr "mode" "DI")])
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (if_then_else:DI
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
+ (match_operand:DI 1 "se_reg_or_0_operand" "dJ,0")
+ (match_operand:DI 2 "se_reg_or_0_operand" "0,dJ")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "@
+ mov%T3\\t%0,%z1,%4
+ mov%t3\\t%0,%z2,%4"
[(set_attr "type" "move")
(set_attr "mode" "DI")])
@@ -6536,13 +7099,16 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
(match_operand:SF 1 "register_operand" "f,0")
(match_operand:SF 2 "register_operand" "0,f")))]
"mips_isa >= 4 && TARGET_HARD_FLOAT"
"@
- mov%T3.s\\t%0,%1,$fcc0
- mov%t3.s\\t%0,%2,$fcc0"
+ mov%T3.s\\t%0,%1,%4
+ mov%t3.s\\t%0,%2,%4"
[(set_attr "type" "move")
(set_attr "mode" "SF")])
@@ -6554,7 +7120,7 @@ move\\t%0,%z4\\n\\
(const_int 0)])
(match_operand:DF 2 "register_operand" "f,0")
(match_operand:DF 3 "register_operand" "0,f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"@
mov%B4.d\\t%0,%2,%1
mov%b4.d\\t%0,%3,%1"
@@ -6564,13 +7130,16 @@ move\\t%0,%z4\\n\\
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f,f")
(if_then_else:DF
- (match_operator 3 "equality_op" [(reg:CC_FP 67) (const_int 0)])
+ (match_operator 3 "equality_op" [(match_operand:CC 4
+ "register_operand"
+ "z,z")
+ (const_int 0)])
(match_operand:DF 1 "register_operand" "f,0")
(match_operand:DF 2 "register_operand" "0,f")))]
- "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
"@
- mov%T3.d\\t%0,%1,$fcc0
- mov%t3.d\\t%0,%2,$fcc0"
+ mov%T3.d\\t%0,%1,%4
+ mov%t3.d\\t%0,%2,%4"
[(set_attr "type" "move")
(set_attr "mode" "DF")])
@@ -6585,90 +7154,45 @@ move\\t%0,%z4\\n\\
"mips_isa >= 4"
"
{
- rtx op0 = branch_cmp[0];
- rtx op1 = branch_cmp[1];
- enum machine_mode mode = GET_MODE (branch_cmp[0]);
- enum rtx_code compare_code = GET_CODE (operands[1]);
- enum rtx_code move_code = NE;
+ gen_conditional_move (operands);
+ DONE;
+}")
- if (GET_MODE_CLASS (mode) != MODE_FLOAT)
- {
- switch (compare_code)
- {
- case EQ:
- compare_code = XOR;
- move_code = EQ;
- break;
- case NE:
- compare_code = XOR;
- break;
- case LT:
- break;
- case GE:
- compare_code = LT;
- move_code = EQ;
- break;
- case GT:
- compare_code = LT;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- break;
- case LE:
- compare_code = LT;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- move_code = EQ;
- break;
- case LTU:
- break;
- case GEU:
- compare_code = LTU;
- move_code = EQ;
- break;
- case GTU:
- compare_code = LTU;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- break;
- case LEU:
- compare_code = LTU;
- op0 = force_reg (mode, branch_cmp[1]);
- op1 = branch_cmp[0];
- move_code = EQ;
- break;
- default:
- abort ();
- }
- }
- else
- {
- if (compare_code == NE)
- {
- /* ??? Perhaps we need to use CC_FP_REVmode here? */
- compare_code = EQ;
- move_code = EQ;
- }
- }
-
- if (mode == SImode || mode == DImode)
- {
- operands[1] = gen_rtx (compare_code, mode, op0, op1);
- operands[4] = gen_reg_rtx (mode);
- }
- else if (mode == SFmode || mode == DFmode)
- {
- operands[1] = gen_rtx (compare_code, CC_FPmode, op0, op1);
- operands[4] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM);
- }
+(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)
+ (match_operand:DI 2 "se_reg_or_0_operand" "")
+ (match_operand:DI 3 "se_reg_or_0_operand" "")))]
+ "mips_isa >= 4"
+ "
+{
+ gen_conditional_move (operands);
+ DONE;
+}")
- if (mode == DImode)
- operands[5] = gen_rtx (move_code, VOIDmode,
- gen_lowpart (SImode, operands[4]),
- CONST0_RTX (SImode));
- else
- operands[5] = gen_rtx (move_code, VOIDmode, operands[4],
- CONST0_RTX (SImode));
+(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 "register_operand" "")
+ (match_operand:SF 3 "register_operand" "")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT"
+ "
+{
+ gen_conditional_move (operands);
+ DONE;
}")
-;; ??? Need movdicc, movsfcc, and movdfcc patterns. They should be
-;; very similar to the above movsicc pattern.
+(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 "register_operand" "")
+ (match_operand:DF 3 "register_operand" "")))]
+ "mips_isa >= 4 && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "
+{
+ gen_conditional_move (operands);
+ DONE;
+}")
diff --git a/gnu/usr.bin/gcc/config/mips/netbsd.h b/gnu/usr.bin/gcc/config/mips/netbsd.h
index e191ffa5159..3fce9fb1de3 100644
--- a/gnu/usr.bin/gcc/config/mips/netbsd.h
+++ b/gnu/usr.bin/gcc/config/mips/netbsd.h
@@ -1,5 +1,5 @@
/* Definitions for DECstation running BSD as target machine for GNU compiler.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -30,11 +30,11 @@ Boston, MA 02111-1307, USA. */
#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 various *crt*.o files is the
@@ -50,7 +50,7 @@ Boston, MA 02111-1307, USA. */
#undef LINK_SPEC
#define LINK_SPEC \
"%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \
- %{!nostdlib:%{!r*:%{!e*:-e __start}}} -dc -dp %{static:-Bstatic} %{assert*}"
+ %{!nostartfiles:%{!r*:%{!e*:-e __start}}} -dc -dp %{static:-Bstatic} %{assert*}"
/* We have atexit(3). */
@@ -69,26 +69,8 @@ Boston, MA 02111-1307, USA. */
-Asystem(unix) -Asystem(NetBSD) -Amachine(mips)"
#endif
-/* Always uses gas. */
-#ifndef ASM_SPEC
-#define ASM_SPEC "\
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
-#endif
-
-#ifndef CPP_SPEC
-#define CPP_SPEC "\
-%{posix:-D_POSIX_SOURCE} \
-%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int} \
-%{mips3:-U__mips -D__mips=3 -D__mips64} \
-%{mgp32:-U__mips64} %{mgp64:-D__mips64}"
+#ifndef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
#endif
#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
@@ -101,8 +83,6 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT MASK_GAS
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#define LOCAL_LABEL_PREFIX "."
-
#include "mips/mips.h"
/*
@@ -225,7 +205,23 @@ do { \
} \
} while (0)
+/*
+ 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.
+*/
+#define ASM_OUTPUT_SECTION_NAME(F, DECL, NAME, RELOC) \
+do { \
+ extern FILE *asm_out_text_file; \
+ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
+ fprintf (asm_out_text_file, "\t.section %s,\"ax\",@progbits\n", (NAME)); \
+ else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \
+ fprintf (F, "\t.section %s,\"a\",@progbits\n", (NAME)); \
+ else \
+ fprintf (F, "\t.section %s,\"aw\",@progbits\n", (NAME)); \
+} while (0)
+
/* Since gas and gld are standard on NetBSD, we don't need these */
#undef ASM_FINAL_SPEC
#undef STARTFILE_SPEC
-
diff --git a/gnu/usr.bin/gcc/config/mips/news4.h b/gnu/usr.bin/gcc/config/mips/news4.h
index f7c464cf353..9f816c19258 100644
--- a/gnu/usr.bin/gcc/config/mips/news4.h
+++ b/gnu/usr.bin/gcc/config/mips/news4.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Sony RISC NEWS (mips)
- Copyright (C) 1991 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -33,4 +33,8 @@ Boston, MA 02111-1307, USA. */
#define MACHINE_TYPE "RISC NEWS-OS"
+/* INITIALIZE_TRAMPOLINE calls this library function to flush
+ program and data caches. */
+#define CACHE_FLUSH_FUNC "cacheflush"
+
#include "mips/mips.h"
diff --git a/gnu/usr.bin/gcc/config/mips/osfrose.h b/gnu/usr.bin/gcc/config/mips/osfrose.h
index b4b811c9ac7..f6901e85bcb 100644
--- a/gnu/usr.bin/gcc/config/mips/osfrose.h
+++ b/gnu/usr.bin/gcc/config/mips/osfrose.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
DECstation (OSF/1 reference port with OSF/rose) version.
- Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -34,57 +34,13 @@ Boston, MA 02111-1307, USA. */
-DOSF -DOSF1 -Dbsd4_2 -DMIPSEL -Dhost_mips -Dmips -Dunix -DR3000 -DSYSTYPE_BSD \
-Asystem(unix) -Asystem(xpg4) -Acpu(mips) -Amachine(mips)"
-#define ASM_SPEC "\
-%{mmips-as: \
- %{!.s:-nocpp} %{.s: %{cpp} %{nocpp}} \
- %{pipe: %e-pipe is not supported.} \
- %{K}} \
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{v} \
-%{noasmopt:-O0} \
-%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}} \
-%{g} %{g0} %{g1} %{g2} %{g3} \
-%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
-%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
-%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
-%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3}"
-
-#ifndef CROSS_COMPILE
-#define ASM_FINAL_SPEC "\
-%{mmips-as: %{!mno-mips-tfile: \
- \n mips-tfile %{v*: -v} %{d*} \
- %{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 /* CROSS_COMPILE */
-#define ASM_FINAL_SPEC "\
-%{mmips-as: %{mmips-tfile: \
- \n mips-tfile %{v*: -v} %{d*} \
- %{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 SUBTARGET_CPP_SIZE_SPEC "\
+%{mlong64:-D__PTRDIFF_TYPE__=long\\ int} \
+%{!mlong64:-D__PTRDIFF_TYPE__=int}"
-#define CPP_SPEC "\
+#define SUBTARGET_CPP_SPEC "\
%{.S: %{!ansi:%{!traditional:%{!traditional-cpp:%{!ftraditional: -traditional}}}}} \
-%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY} \
- -ULANGUAGE_C -U__LANGUAGE_C__} \
-%{.s: %{!ansi:%{!traditional:%{!traditional-cpp:%{!ftraditional: -traditional}}}}} \
-%{.s: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY} \
- -ULANGUAGE_C -U__LANGUAGE_C__} \
-%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS} \
-%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
-%{!.S:%{!.s: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}} \
-%{mlong64:-D__PTRDIFF_TYPE__=long\\ int} \
-%{!mlong64:-D__PTRDIFF_TYPE__=int} \
-%{mips3:-U__mips -D__mips=3 -D__mips64} \
-%{mgp32:-U__mips64} %{mgp64:-D__mips64} \
-%{EB:-UMIPSEL -U_MIPSEL -U__MIPSEL -U__MIPSEL__ -D_MIPSEB -D__MIPSEB -D__MIPSEB__ %{!ansi:-DMIPSEB}} \
-%{EL:-UMIPSEB -U_MIPSEB -U__MIPSEB -U__MIPSEB__ -D_MIPSEL -D__MIPSEL -D__MIPSEL__ %{!ansi:-DMIPSEL}}"
+%{.s: %{!ansi:%{!traditional:%{!traditional-cpp:%{!ftraditional: -traditional}}}}}"
/* ??? This assumes that GNU as is always used with GNU ld, and MIPS as is
always used with MIPS ld. */
@@ -119,7 +75,7 @@ Boston, MA 02111-1307, USA. */
/* Turn on -mpic-extern by default. */
#define CC1_SPEC "\
%{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \
-%{mips1:-mfp32 -mgp32}%{mips2:-mfp32 -mgp32}%{mips3:-mfp64 -mgp64} \
+%{mips1:-mfp32 -mgp32} %{mips2:-mfp32 -mgp32} %{mips3:-mfp64 -mgp64} \
%{G*} \
%{pic-none: -mno-half-pic} \
%{pic-lib: -mhalf-pic} \
diff --git a/gnu/usr.bin/gcc/config/mips/t-ecoff b/gnu/usr.bin/gcc/config/mips/t-ecoff
index eab1c7399d9..067a0558c8a 100644
--- a/gnu/usr.bin/gcc/config/mips/t-ecoff
+++ b/gnu/usr.bin/gcc/config/mips/t-ecoff
@@ -11,7 +11,7 @@ CROSS_LIBGCC1 =
# We must build libgcc2.a with -G 0, in case the user wants to link
# without the $gp register.
-LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -g1 -G 0
+TARGET_LIBGCC2_CFLAGS = -G 0
# These are really part of libgcc1, but this will cause them to be
# built correctly, so... [taken from t-sparclite]
@@ -34,9 +34,9 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
# Build the libraries for both hard and soft floating point
-MULTILIB_OPTIONS = msoft-float EL/EB mips1/mips3
-MULTILIB_DIRNAMES = soft-float el eb mips1 mips3
-MULTILIB_MATCHES =
+MULTILIB_OPTIONS = msoft-float/msingle-float EL/EB mips1/mips3
+MULTILIB_DIRNAMES = soft-float single el eb mips1 mips3
+MULTILIB_MATCHES = msingle-float=m4650
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/mips/t-iris6 b/gnu/usr.bin/gcc/config/mips/t-iris6
index e1a4d50ce41..85a63f06e2e 100644
--- a/gnu/usr.bin/gcc/config/mips/t-iris6
+++ b/gnu/usr.bin/gcc/config/mips/t-iris6
@@ -3,9 +3,18 @@
LIBGCC1 =
CROSS_LIBGCC1 =
-MULTILIB_OPTIONS=mips1/mips2/mips3/mips4
+# ??? If no mabi=X option given, but a mipsX option is, then should deal
+# with that.
+# ??? mabi=32 is deliberately left off the list because it doesn't work yet.
+MULTILIB_OPTIONS=mabi=n32/mabi=64
MULTILIB_DIRNAMES=
MULTILIB_MATCHES=
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
+
+# For svr4 we build crtbegin.o and crtend.o which serve to add begin and
+# end labels to the .ctors and .dtors section when we link using gcc.
+
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o
+CRTSTUFF_T_CFLAGS=-g1
diff --git a/gnu/usr.bin/gcc/config/mips/ultrix.h b/gnu/usr.bin/gcc/config/mips/ultrix.h
index cb18a5d4eba..7fb101a9151 100644
--- a/gnu/usr.bin/gcc/config/mips/ultrix.h
+++ b/gnu/usr.bin/gcc/config/mips/ultrix.h
@@ -1,5 +1,5 @@
-/* Definitions of target machine for GNU compiler. DECstation (ultrix) version.
- Copyright (C) 1991 Free Software Foundation, Inc.
+/* Definitions of target machine for GNU compiler; DECstation (Ultrix) version.
+ Copyright (C) 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -46,4 +46,12 @@ Boston, MA 02111-1307, USA. */
/* Generate calls to memcpy, etc., not bcopy, etc. */
#define TARGET_MEM_FUNCTIONS
+/* Work around assembler forward label references generated in exception
+ handling code. */
+#define DWARF2_UNWIND_INFO 0
+
+/* INITIALIZE_TRAMPOLINE calls this library function to flush
+ program and data caches. */
+#define CACHE_FLUSH_FUNC "cacheflush"
+
#include "mips/mips.h"
diff --git a/gnu/usr.bin/gcc/config/mips/x-iris b/gnu/usr.bin/gcc/config/mips/x-iris
index 3d49e4c7467..0f04f099f16 100644
--- a/gnu/usr.bin/gcc/config/mips/x-iris
+++ b/gnu/usr.bin/gcc/config/mips/x-iris
@@ -9,9 +9,11 @@
# can use -O2. Down with fixed size tables!
# The -cckr is to turn off strict ANSI checking.
-CC = $(OLDCC)
-OPT = -O1
-OLDCC = cc -Wf,-XNh2000,-XNg1500 -Olimit 3000 -cckr $(OPT)
+# These definitions are commented out because they cause trouble with
+# autoconf. It is believed that they aren't needed anymore.
+#CC = $(OLDCC)
+#OPT = -O1
+#OLDCC = cc -Wf,-XNh2000,-XNg1500 -Olimit 3000 -cckr $(OPT)
# The bison output files are machine-indep,
# so different flags for a particular machine are not useful.
diff --git a/gnu/usr.bin/gcc/config/mips/x-iris3 b/gnu/usr.bin/gcc/config/mips/x-iris3
index d4b55dde20a..2743ab743d9 100644
--- a/gnu/usr.bin/gcc/config/mips/x-iris3
+++ b/gnu/usr.bin/gcc/config/mips/x-iris3
@@ -12,9 +12,11 @@
# the -cckr option, so, lets try without it for all versions of Irix 3.x.
# The -cckr is to turn off strict ANSI checking.
-CC = $(OLDCC)
-OPT = -O1
-OLDCC = cc -Wf,-XNh2000,-XNg1500 -Olimit 3000 $(OPT)
+# These definitions are commented out because they cause trouble with
+# autoconf. It is believed that they aren't needed anymore.
+#CC = $(OLDCC)
+#OPT = -O1
+#OLDCC = cc -Wf,-XNh2000,-XNg1500 -Olimit 3000 $(OPT)
# The bison output files are machine-indep,
# so different flags for a particular machine are not useful.
diff --git a/gnu/usr.bin/gcc/config/mips/x-iris6 b/gnu/usr.bin/gcc/config/mips/x-iris6
index 3f775fd583b..88c41f4dfe4 100644
--- a/gnu/usr.bin/gcc/config/mips/x-iris6
+++ b/gnu/usr.bin/gcc/config/mips/x-iris6
@@ -1,2 +1,11 @@
+# We force the use of the O32 ABI for two reasons.
+# 1) For consistency, because some versions of Irix 6 default to the O32 ABI
+# and some versions default to the N64 ABI.
+# 2) To avoid SGI compiler bugs. The v6.x and v7.0 compilers from SGI have
+# bugs that cause gcc to be miscompiled when the N32 or N64 ABIs are used.
+# The O32 ABI is known to be OK.
+CC = $(OLDCC)
+OLDCC = cc -32
+
# Find all of the declarations from the header files
-FIXPROTO_DEFINES= -D__EXTENSIONS__ -D_LANGUAGE_C_PLUS_PLUS
+FIXPROTO_DEFINES= -D__EXTENSIONS__ -D_SGI_SOURCE -D_LANGUAGE_C_PLUS_PLUS
diff --git a/gnu/usr.bin/gcc/config/mips/x-netbsd b/gnu/usr.bin/gcc/config/mips/x-netbsd
index ed1709cc044..49a89f35d1b 100644
--- a/gnu/usr.bin/gcc/config/mips/x-netbsd
+++ b/gnu/usr.bin/gcc/config/mips/x-netbsd
@@ -3,7 +3,8 @@ STMP_FIXPROTO =
# We don't need GCC's own include files.
USER_H = $(srcdir)/ginclude/stdarg.h $(srcdir)/ginclude/varargs.h \
- $(srcdir)/ginclude/va-mips.h
+ $(srcdir)/ginclude/va-mips.h $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)
+
XLIMITS_H =
# We don't need even the files GCC insists we need.
diff --git a/gnu/usr.bin/gcc/config/mips/xm-iris3.h b/gnu/usr.bin/gcc/config/mips/xm-iris3.h
index 3d2a59a1447..448b7ac80bb 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-iris3.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-iris3.h
@@ -1,8 +1,3 @@
#include "mips/xm-mips.h"
#define USG
-
-#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/gnu/usr.bin/gcc/config/mips/xm-iris4.h b/gnu/usr.bin/gcc/config/mips/xm-iris4.h
index e12c226614e..c01d3f48a78 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-iris4.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-iris4.h
@@ -1,11 +1,6 @@
#include "mips/xm-mips.h"
#define USG
-#define HAVE_VPRINTF
-
-#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 0
#ifdef __GNUC__
diff --git a/gnu/usr.bin/gcc/config/mips/xm-iris5.h b/gnu/usr.bin/gcc/config/mips/xm-iris5.h
index 72387b29ccc..f3eb9cdb753 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-iris5.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-iris5.h
@@ -1,9 +1,11 @@
#include "mips/xm-mips.h"
#define USG
-#define HAVE_VPRINTF
-#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)
+/* On SGI IRIX 5.3, inttypes.h clashes with sys/types.h, but the clash
+ (when compiled with GCC) is a warning, so configure.in thinks it's OK
+ to use it. Work around this problem. */
+#ifdef HAVE_INTTYPES_H
+#undef HAVE_INTTYPES_H
+#endif
diff --git a/gnu/usr.bin/gcc/config/mips/xm-iris6.h b/gnu/usr.bin/gcc/config/mips/xm-iris6.h
index 775497cc80f..4d429c72edc 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-iris6.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-iris6.h
@@ -5,16 +5,12 @@
extern void *alloca ();
#endif
-#include "mips/xm-iris5.h"
+#include "mips/xm-mips.h"
-#undef HOST_BITS_PER_LONG
-#define HOST_BITS_PER_LONG 64
-
-/* Declare some functions needed for this machine. We don't want to
- include these in the sources since other machines might define them
- differently. */
+#define USG
-extern void *malloc (), *realloc (), *calloc ();
+#undef HOST_BITS_PER_LONG
+#define HOST_BITS_PER_LONG _MIPS_SZLONG
#ifndef inhibit_libc
#include "string.h"
diff --git a/gnu/usr.bin/gcc/config/mips/xm-mips.h b/gnu/usr.bin/gcc/config/mips/xm-mips.h
index 6c9df7c0f28..e10f78e5fca 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-mips.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-mips.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for MIPS Rx000 family
- Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1993, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -64,7 +64,11 @@ Boston, MA 02111-1307, USA. */
#ifndef __GNUC__
#define USE_C_ALLOCA
+#ifdef __STDC__
+extern void * alloca ();
+#else
extern char * alloca ();
+#endif
/* for the emacs version of alloca */
#define STACK_DIRECTION -1
@@ -73,8 +77,6 @@ extern char * alloca ();
/* Say if we have vprintf. BSD Mips targets probably don't have vfprintf. */
#if defined(__OSF1__) || defined(__OSF__) || defined(__osf__) || defined(bsd4_4)
-#define HAVE_VPRINTF
-#define HAVE_PUTENV
#else
#define NO_STAB_H /* mips doesn't typically have stab.h */
diff --git a/gnu/usr.bin/gcc/config/mips/xm-news.h b/gnu/usr.bin/gcc/config/mips/xm-news.h
index 9409d7fe0a6..e3eda9db141 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-news.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-news.h
@@ -4,3 +4,5 @@
/* Sony has a funny name for this symbol. */
#define sys_siglist _sys_siglist
+#undef SYS_SIGLIST_DECLARED
+#define SYS_SIGLIST_DECLARED
diff --git a/gnu/usr.bin/gcc/config/mips/xm-sysv.h b/gnu/usr.bin/gcc/config/mips/xm-sysv.h
index 170538fb682..05a8d6c1154 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-sysv.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-sysv.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for UMIPS operating system
- Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -28,11 +28,3 @@ Boston, MA 02111-1307, USA. */
#define USG
#include "mips/xm-mips.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 rindex strrchr
-#define index strchr
-
diff --git a/gnu/usr.bin/gcc/config/mips/xm-sysv4.h b/gnu/usr.bin/gcc/config/mips/xm-sysv4.h
index 490a7722995..b79664bf1fb 100644
--- a/gnu/usr.bin/gcc/config/mips/xm-sysv4.h
+++ b/gnu/usr.bin/gcc/config/mips/xm-sysv4.h
@@ -3,9 +3,5 @@
/* SVR4 provides no sys_siglist,
but does offer the same data under another name. */
#define sys_siglist _sys_siglist
-
-/* There is a declaration in /usr/include/signal.h that conflicts with the
- declarations in collect2.c and mips-tfile.c, so disable gcc's declarations.
- This is at least true for CDC's EP/IX 2.1.1. It is suspected to be true
- for RISC/OS 5.x also. */
-#define DONT_DECLARE_SYS_SIGLIST
+#undef SYS_SIGLIST_DECLARED
+#define SYS_SIGLIST_DECLARED
diff --git a/gnu/usr.bin/gcc/config/msdos/configur.bat b/gnu/usr.bin/gcc/config/msdos/configur.bat
index 7d479f7af4d..03e41091686 100644
--- a/gnu/usr.bin/gcc/config/msdos/configur.bat
+++ b/gnu/usr.bin/gcc/config/msdos/configur.bat
@@ -17,6 +17,12 @@ sed -f config/msdos/top.sed Makefile.in >> Makefile
set LANG=
+if not exist ada\make-lang.in goto no_ada
+sed -f config/msdos/top.sed ada\make-lang.in >> Makefile
+sed -f config/msdos/top.sed ada\makefile.in > ada\Makefile
+set LANG=%LANG% ada.&
+:no_ada
+
if not exist cp\make-lang.in goto no_cp
sed -f config/msdos/top.sed cp\make-lang.in >> Makefile
sed -f config/msdos/top.sed cp\makefile.in > cp\Makefile
diff --git a/gnu/usr.bin/gcc/config/nextstep.c b/gnu/usr.bin/gcc/config/nextstep.c
index 823bceeffe3..e909a948cda 100644
--- a/gnu/usr.bin/gcc/config/nextstep.c
+++ b/gnu/usr.bin/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 <stdio.h>
+#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/gnu/usr.bin/gcc/config/nextstep.h b/gnu/usr.bin/gcc/config/nextstep.h
index 6e2e986713e..96435fc67ea 100644
--- a/gnu/usr.bin/gcc/config/nextstep.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/ns32k/ns32k.c b/gnu/usr.bin/gcc/config/ns32k/ns32k.c
index 045800bb3cb..187a6fbd071 100644
--- a/gnu/usr.bin/gcc/config/ns32k/ns32k.c
+++ b/gnu/usr.bin/gcc/config/ns32k/ns32k.c
@@ -1,5 +1,5 @@
/* Subroutines for assembler code output on the NS32000.
- Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,8 +19,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Some output-actions in ns32k.md need these. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -227,6 +227,39 @@ reg_or_mem_operand (op, mode)
|| GET_CODE (op) == MEM));
}
+/* Split one or more DImode RTL references into pairs of SImode
+ references. The RTL can be REG, offsettable MEM, integer constant, or
+ CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
+ split and "num" is its length. lo_half and hi_half are output arrays
+ that parallel "operands". */
+
+void
+split_di (operands, num, lo_half, hi_half)
+ rtx operands[];
+ int num;
+ rtx 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]))
+ {
+ split_double (operands[num], &lo_half[num], &hi_half[num]);
+ }
+ else if (offsettable_memref_p (operands[num]))
+ {
+ lo_half[num] = operands[num];
+ hi_half[num] = adj_offsettable_operand (operands[num], 4);
+ }
+ else
+ abort();
+ }
+}
+
/* Return the best assembler insn template
for moving operands[1] into operands[0] as a fullword. */
diff --git a/gnu/usr.bin/gcc/config/ns32k/ns32k.h b/gnu/usr.bin/gcc/config/ns32k/ns32k.h
index 18a01c3573d..70cd9f201ae 100644
--- a/gnu/usr.bin/gcc/config/ns32k/ns32k.h
+++ b/gnu/usr.bin/gcc/config/ns32k/ns32k.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. NS32000 version.
- Copyright (C) 1988, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -405,7 +405,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, GEN_AND_FP_REGS,
the caller must always pop the args. */
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \
- ((TARGET_RTD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ ((TARGET_RTD && (!(FUNDECL) || TREE_CODE (FUNDECL) != IDENTIFIER_NODE) \
&& (TYPE_ARG_TYPES (FUNTYPE) == 0 \
|| (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \
== void_type_node))) \
@@ -467,7 +467,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, GEN_AND_FP_REGS,
On the ns32k, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
@@ -1364,11 +1364,9 @@ do { \
} while (0)
#endif
-/* 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. */
diff --git a/gnu/usr.bin/gcc/config/ns32k/ns32k.md b/gnu/usr.bin/gcc/config/ns32k/ns32k.md
index 679ca9a6ca5..28e65e6df91 100644
--- a/gnu/usr.bin/gcc/config/ns32k/ns32k.md
+++ b/gnu/usr.bin/gcc/config/ns32k/ns32k.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU compiler, ns32000 Version
-;; Copyright (C) 1988, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1994, 1996 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
;; This file is part of GNU CC.
@@ -858,6 +858,47 @@
"GET_CODE (operands[1]) == CONST_INT"
"addr %c1(sp),%0")
+(define_insn "adddi3"
+ [(set (match_operand:DI 0 "general_operand" "=ro")
+ (plus:DI (match_operand:DI 1 "general_operand" "%0")
+ (match_operand:DI 2 "general_operand" "ron")))]
+ ""
+ "*
+{
+ rtx low[3], high[3], xops[4];
+ split_di (operands, 3, low, high);
+ xops[0] = low[0];
+ xops[1] = high[0];
+ xops[2] = low[2];
+ xops[3] = high[2];
+
+ if (GET_CODE (xops[2]) == CONST_INT)
+ {
+ int i = INTVAL (xops[2]);
+
+ if (i <= 7 && i >= -8)
+ {
+ if (i == 0)
+ {
+ i = INTVAL (xops[3]);
+ if (i <= 7 && i >= -8)
+ output_asm_insn (\"addqd %$%3,%1\", xops);
+ else
+ output_asm_insn (\"addd %$%3,%1\", xops);
+ }
+ else
+ {
+ output_asm_insn (\"addqd %$%2,%0\", xops);
+ output_asm_insn (\"addcd %$%3,%1\", xops);
+ }
+ return \"\";
+ }
+ }
+ output_asm_insn (\"addd %2,%0\", xops);
+ output_asm_insn (\"addcd %3,%1\", xops);
+ return \"\";
+}")
+
(define_insn "addsi3"
[(set (match_operand:SI 0 "general_operand" "=g,=g&<")
(plus:SI (match_operand:SI 1 "general_operand" "%0,r")
@@ -971,6 +1012,47 @@
return \"adjspd %$%0\";
}")
+(define_insn "subdi3"
+ [(set (match_operand:DI 0 "general_operand" "=ro")
+ (minus:DI (match_operand:DI 1 "general_operand" "0")
+ (match_operand:DI 2 "general_operand" "ron")))]
+ ""
+ "*
+{
+ rtx low[3], high[3], xops[4];
+ split_di (operands, 3, low, high);
+ xops[0] = low[0];
+ xops[1] = high[0];
+ xops[2] = low[2];
+ xops[3] = high[2];
+
+ if (GET_CODE (xops[2]) == CONST_INT)
+ {
+ int i = INTVAL (xops[2]);
+
+ if (i <= 8 && i >= -7)
+ {
+ if (i == 0)
+ {
+ i = INTVAL (xops[3]);
+ if (i <= 8 && i >= -7)
+ output_asm_insn (\"addqd %$%n3,%1\", xops);
+ else
+ output_asm_insn (\"subd %$%3,%1\", xops);
+ }
+ else
+ {
+ output_asm_insn (\"addqd %$%n2,%0\", xops);
+ output_asm_insn (\"subcd %$%3,%1\", xops);
+ }
+ return \"\";
+ }
+ }
+ output_asm_insn (\"subd %2,%0\", xops);
+ output_asm_insn (\"subcd %3,%1\", xops);
+ return \"\";
+}")
+
(define_insn "subsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(minus:SI (match_operand:SI 1 "general_operand" "0")
@@ -1390,6 +1472,34 @@
"TARGET_32081"
"negf %1,%0")
+(define_insn "negdi2"
+ [(set (match_operand:DI 0 "general_operand" "=ro")
+ (neg:DI (match_operand:DI 1 "general_operand" "ro")))]
+ ""
+ "*
+{
+ rtx low[2], high[2], xops[4];
+ split_di (operands, 2, low, high);
+ xops[0] = low[0];
+ xops[1] = high[0];
+ xops[2] = low[1];
+ xops[3] = high[1];
+
+ if (rtx_equal_p (operands[0], operands[1]))
+ {
+ output_asm_insn (\"negd %3,%1\", xops);
+ output_asm_insn (\"negd %2,%0\", xops);
+ output_asm_insn (\"subcd %$0,%1\", xops);
+ }
+ else
+ {
+ output_asm_insn (\"negd %2,%0\", xops);
+ output_asm_insn (\"movqd %$0,%1\", xops);
+ output_asm_insn (\"subcd %3,%1\", xops);
+ }
+ return \"\";
+}")
+
(define_insn "negsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(neg:SI (match_operand:SI 1 "general_operand" "rmn")))]
@@ -2607,32 +2717,33 @@
;; ffs instructions
-(define_insn "ffsqi2"
- [(set (match_operand:QI 0 "general_operand" "=g")
- (ffs:QI (match_operand:SI 1 "general_operand" "g")))]
- ""
- "*
-{
- return \"movqb 0,%0; ffsd %1,%0; bfs 1f; addqb 1,%0; 1:\";
-}")
-
-(define_insn "ffshi2"
- [(set (match_operand:HI 0 "general_operand" "=g")
- (ffs:HI (match_operand:SI 1 "general_operand" "g")))]
- ""
- "*
-{
- return \"movqw 0,%0; ffsd %1,%0; bfs 1f; addqw 1,%0; 1:\";
-}")
-
-(define_insn "ffssi2"
- [(set (match_operand:SI 0 "general_operand" "=g")
- (ffs:SI (match_operand:SI 1 "general_operand" "g")))]
- ""
- "*
-{
- return \"movqd 0,%0; ffsd %1,%0; bfs 1f; addqd 1,%0; 1:\";
-}")
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "ro")
+ (minus:SI
+ (plus:SI (ffs:SI (zero_extract:SI
+ (match_operand:SI 1 "general_operand" "g")
+ (minus:SI (const_int 32) (match_dup 0))
+ (match_dup 0)))
+ (match_dup 0))
+ (const_int 1)))]
+ ""
+ "ffsd %1,%0; bfc 1f; addqd %$-1,%0; 1:")
+
+(define_expand "ffssi2"
+ [(set (match_operand:SI 0 "general_operand" "=g") (const_int 0))
+ (set (match_dup 0)
+ (minus:SI
+ (plus:SI (ffs:SI (zero_extract:SI
+ (match_operand:SI 1 "general_operand" "g")
+ (minus:SI (const_int 32) (match_dup 0))
+ (match_dup 0)))
+ (match_dup 0))
+ (const_int 1)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int 1)))]
+ ""
+ "operands[1] = make_safe_from(operands[1], operands[0]);")
;; Speed up stack adjust followed by a HI fixedpoint push.
diff --git a/gnu/usr.bin/gcc/config/ns32k/tek6000.h b/gnu/usr.bin/gcc/config/ns32k/tek6000.h
index 00ddc96498b..5b84bcb7640 100644
--- a/gnu/usr.bin/gcc/config/ns32k/tek6000.h
+++ b/gnu/usr.bin/gcc/config/ns32k/tek6000.h
@@ -72,8 +72,10 @@ Boston, MA 02111-1307, USA. */
/* Act the same as the UTek complier: -g for dbx, -go for sdb.
* This is used in toplev.c.
*/
-#define PREFERRED_DEBUGGING_TYPE \
- ((len > 1 && !strncmp(str, "go", len)) ? SDB_DEBUG : DBX_DEBUG )
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#define CC1_SPEC "{go:-gcoff}"
+#define CC1PLUS_SPEC "{go:-gcoff}"
/* Sequent has some changes in the format of DBX symbols. */
#define DBX_NO_XREFS 1
diff --git a/gnu/usr.bin/gcc/config/ns32k/xm-genix.h b/gnu/usr.bin/gcc/config/ns32k/xm-genix.h
index 76be3b76fc8..15ff46fc6b1 100644
--- a/gnu/usr.bin/gcc/config/ns32k/xm-genix.h
+++ b/gnu/usr.bin/gcc/config/ns32k/xm-genix.h
@@ -3,7 +3,3 @@
#include "ns32k/xm-ns32k.h"
#define USG
-
-#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/gnu/usr.bin/gcc/config/pa/lib2funcs.asm b/gnu/usr.bin/gcc/config/pa/lib2funcs.asm
index ea964d3af6f..cf57cbb9b92 100644
--- a/gnu/usr.bin/gcc/config/pa/lib2funcs.asm
+++ b/gnu/usr.bin/gcc/config/pa/lib2funcs.asm
@@ -1,5 +1,6 @@
; Subroutines for calling unbound dynamic functions from within GDB for HPPA.
-; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+; Subroutines for out of line prologues and epilogues on for the HPPA
+; Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
; This file is part of GNU CC.
@@ -13,6 +14,14 @@
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
+; 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.)
+
; 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,
@@ -24,6 +33,8 @@
.SPACE $TEXT$
.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44
.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY
+ .SUBSPA $MILLICODE$,QUAD=0,ALIGN=8,ACCESS=44,SORT=8
+
.IMPORT $$dyncall,MILLICODE
; gcc_compiled.:
.SPACE $TEXT$
diff --git a/gnu/usr.bin/gcc/config/pa/pa-hiux.h b/gnu/usr.bin/gcc/config/pa/pa-hiux.h
index e387891ab1b..f4be95b8830 100644
--- a/gnu/usr.bin/gcc/config/pa/pa-hiux.h
+++ b/gnu/usr.bin/gcc/config/pa/pa-hiux.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for HI-UX.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,8 +20,7 @@ Boston, MA 02111-1307, USA. */
/* HIUX is just a HPUX variant. We can simply use the HPUX configuration
for just about everything. */
-#include "pa/pa-hpux.h"
/* Predefines are the one noteworthy difference between HPUX and HIUX. */
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dhppa -DPWB -Dunix -D_HIUX_SOURCE -D__H3050R -D__H3050RX -Asystem(unix) -Asystem(hiux) -Acpu(hppa) -Amachine(hppa)"
+#define CPP_PREDEFINES "-Dhppa -DPWB -Dunix -D__H3050R -D__H3050RX -Asystem(unix) -Asystem(hiux) -Acpu(hppa) -Amachine(hppa)"
diff --git a/gnu/usr.bin/gcc/config/pa/pa-hpux.h b/gnu/usr.bin/gcc/config/pa/pa-hpux.h
index 44c9236adb2..e001ebe438c 100644
--- a/gnu/usr.bin/gcc/config/pa/pa-hpux.h
+++ b/gnu/usr.bin/gcc/config/pa/pa-hpux.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for HP-UX.
- Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,11 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#ifndef TARGET_DEFAULT
+#undef TARGET_DEFAULT
#define TARGET_DEFAULT 0
-#endif
-
-#include "pa/pa.h"
/* Make GCC agree with types.h. */
#undef SIZE_TYPE
@@ -31,21 +28,21 @@ Boston, MA 02111-1307, USA. */
#define SIZE_TYPE "unsigned int"
#define PTRDIFF_TYPE "int"
-/* HPUX doesn't use any debugging format that GCC knows about. */
-#undef DBX_DEBUGGING_INFO
-#undef DEFAULT_GDB_EXTENSIONS
-#define DEFAULT_GDB_EXTENSIONS 0
-
/* Like the default, except no -lg. */
#undef LIB_SPEC
#define LIB_SPEC "%{!shared:%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}}"
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa)"
+#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa)"
#undef LINK_SPEC
+#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1)
#define LINK_SPEC \
- "%{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
+ "%{!mpa-risc-1-0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
+#else
+#define LINK_SPEC \
+ "%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
+#endif
/* hpux8 and later have C++ compatible include files, so do not
pretend they are `extern "C"'. */
diff --git a/gnu/usr.bin/gcc/config/pa/pa-hpux7.h b/gnu/usr.bin/gcc/config/pa/pa-hpux7.h
index 05d0241dbd1..dc75ec28b10 100644
--- a/gnu/usr.bin/gcc/config/pa/pa-hpux7.h
+++ b/gnu/usr.bin/gcc/config/pa/pa-hpux7.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for HP-UX.
- Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA. */
#define TARGET_DEFAULT 0
#endif
-/* HPUX 7 has the old assembler. */
-#define HP_FP_ARG_DESCRIPTOR_REVERSED
-
-#include "pa/pa.h"
-
/* Make GCC agree with types.h. */
#undef SIZE_TYPE
#undef PTRDIFF_TYPE
@@ -34,14 +29,9 @@ Boston, MA 02111-1307, USA. */
#define SIZE_TYPE "unsigned int"
#define PTRDIFF_TYPE "int"
-/* HPUX doesn't use any debugging format that GCC knows about. */
-#undef DBX_DEBUGGING_INFO
-#undef DEFAULT_GDB_EXTENSIONS
-#define DEFAULT_GDB_EXTENSIONS 0
-
/* Like the default, except no -lg. */
#undef LIB_SPEC
#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p: -L/lib/libp/ -lc}%{pg: -L/lib/libp/ -lc}"
#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -D_HPUX_SOURCE -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa)"
+#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -DPWB -Dhpux -Dunix -Asystem(unix) -Asystem(hpux) -Acpu(hppa) -Amachine(hppa)"
diff --git a/gnu/usr.bin/gcc/config/pa/pa-hpux9.h b/gnu/usr.bin/gcc/config/pa/pa-hpux9.h
index 93faccfe087..8d039d2637e 100644
--- a/gnu/usr.bin/gcc/config/pa/pa-hpux9.h
+++ b/gnu/usr.bin/gcc/config/pa/pa-hpux9.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Tim Moore (moore@defmacro.cs.utah.edu)
This file is part of GNU CC.
@@ -19,11 +19,13 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#define TARGET_DEFAULT 0
-
-#include "pa/pa-hpux.h"
-
-/* We can debug dynamically linked executables on hpux9. */
+/* We can debug dynamically linked executables on hpux9; we also want
+ dereferencing of a NULL pointer to cause a SEGV. */
#undef LINK_SPEC
+#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1)
+#define LINK_SPEC \
+ "%{!mpa-risc-1-0:%{!shared:-L/lib/pa1.1 -L/usr/lib/pa1.1 }} -z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}"
+#else
#define LINK_SPEC \
- "%{!shared:-u main} %{static:-a archive} %{shared:-b}"
+ "-z %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{shared:-b}"
+#endif
diff --git a/gnu/usr.bin/gcc/config/pa/pa-oldas.h b/gnu/usr.bin/gcc/config/pa/pa-oldas.h
index 0c469a5e946..8ff741f1435 100644
--- a/gnu/usr.bin/gcc/config/pa/pa-oldas.h
+++ b/gnu/usr.bin/gcc/config/pa/pa-oldas.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1
- Copyright (C) 1991 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1996 Free Software Foundation, Inc.
Contributed by Tim Moore (moore@defmacro.cs.utah.edu)
This file is part of GNU CC.
@@ -19,12 +19,4 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This is the same as pa-hpux.h, except that we generate snake code by
- default and emits assembly code accepted by the 8.02 assembler. */
-
-
-#define TARGET_DEFAULT 0
#define HP_FP_ARG_DESCRIPTOR_REVERSED
-
-#include "pa/pa-hpux.h"
-
diff --git a/gnu/usr.bin/gcc/config/pa/pa-osf.h b/gnu/usr.bin/gcc/config/pa/pa-osf.h
index 641790a40ef..047d20e34ff 100644
--- a/gnu/usr.bin/gcc/config/pa/pa-osf.h
+++ b/gnu/usr.bin/gcc/config/pa/pa-osf.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for HP PA-RISC 1.1
- Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
Contributed by Tim Moore (moore@defmacro.cs.utah.edu)
This file is part of GNU CC.
@@ -19,13 +19,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. */
-#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT 0x88 /* TARGET_GAS + TARGET_JUMP_IN_DELAY */
-#endif
-
-#include "pa/pa.h"
#undef CPP_PREDEFINES
+#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & 1)
+#define CPP_PREDEFINES "-Dhppa -Dunix -Dhp9000 -Dspectrum -DREVARGV -Dhp700 -DHP700 -Dparisc -D__pa_risc -DPARISC -DBYTE_MSF -DBIT_MSF -Asystem(unix) -Asystem(mach) -Acpu(hppa) -Amachine(hppa)"
+#else
#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Dparisc -D__pa_risc -DPARISC -DBYTE_MSF -DBIT_MSF -Asystem(unix) -Asystem(mach) -Acpu(hppa) -Amachine(hppa)"
+#endif
/* 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/gnu/usr.bin/gcc/config/pa/pa.c b/gnu/usr.bin/gcc/config/pa/pa.c
index 3bd15e1e4f6..d32195f23a7 100644
--- a/gnu/usr.bin/gcc/config/pa/pa.c
+++ b/gnu/usr.bin/gcc/config/pa/pa.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for HPPA.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Tim Moore (moore@cs.utah.edu), based on sparc.c
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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -32,10 +32,14 @@ Boston, MA 02111-1307, USA. */
#include "insn-attr.h"
#include "flags.h"
#include "tree.h"
+#include "reload.h"
#include "c-tree.h"
#include "expr.h"
#include "obstack.h"
+static void restore_unscaled_index_insn_codes PROTO((rtx));
+static void record_unscaled_index_insn_codes PROTO((rtx));
+
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
@@ -55,6 +59,10 @@ int hp_profile_labelno;
registers which were saved by the current function's prologue. */
static int gr_saved, fr_saved;
+/* Whether or not the current function uses an out-of-line prologue
+ and epilogue. */
+static int out_of_line_prologue_epilogue;
+
static rtx find_addr_reg ();
/* Keep track of the number of bytes we have output in the CODE subspaces
@@ -65,29 +73,37 @@ unsigned int total_code_bytes;
/* Variables to handle plabels that we discover are necessary at assembly
output time. They are output after the current function. */
-struct defer_plab
+struct deferred_plabel
{
rtx internal_label;
- rtx symbol;
+ char *name;
} *deferred_plabels = 0;
int n_deferred_plabels = 0;
+/* Array indexed by INSN_UIDs holding the INSN_CODE of an insn which
+ uses an unscaled indexed address before delay slot scheduling. */
+static int *unscaled_index_insn_codes;
+
+/* Upper bound for the array. */
+static int max_unscaled_index_insn_codes_uid;
+
void
override_options ()
{
- /* Default to 700 scheduling which is reasonable for older 800 processors
- correct for the 700s, and not too bad for the 7100s and 7100LCs. */
+ /* Default to 7100 scheduling. If the 7100LC scheduling ever
+ gets reasonably tuned, it should be the default since that
+ what most PAs sold now are. */
if (pa_cpu_string == NULL
- || ! strcmp (pa_cpu_string, "700"))
- {
- pa_cpu_string = "700";
- pa_cpu = PROCESSOR_700;
- }
- else if (! strcmp (pa_cpu_string, "7100"))
+ || ! strcmp (pa_cpu_string, "7100"))
{
pa_cpu_string = "7100";
pa_cpu = PROCESSOR_7100;
}
+ else if (! strcmp (pa_cpu_string, "700"))
+ {
+ pa_cpu_string = "700";
+ pa_cpu = PROCESSOR_700;
+ }
else if (! strcmp (pa_cpu_string, "7100LC"))
{
pa_cpu_string = "7100LC";
@@ -97,6 +113,34 @@ override_options ()
{
warning ("Unknown -mschedule= option (%s).\nValid options are 700, 7100 and 7100LC\n", pa_cpu_string);
}
+
+ if (flag_pic && TARGET_PORTABLE_RUNTIME)
+ {
+ warning ("PIC code generation is not supported in the portable runtime model\n");
+ }
+
+ if (flag_pic && (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS))
+ {
+ warning ("PIC code generation is not compatible with fast indirect calls\n");
+ }
+
+ if (flag_pic && profile_flag)
+ {
+ warning ("PIC code generation is not compatible with profiling\n");
+ }
+
+ if (TARGET_SPACE && (flag_pic || profile_flag))
+ {
+ warning ("Out of line entry/exit sequences are not compatible\n");
+ warning ("with PIC or profiling\n");
+ }
+
+ if (! TARGET_GAS && write_symbols != NO_DEBUG)
+ {
+ warning ("-g is only supported when using GAS on this processor,");
+ warning ("-g option disabled.");
+ write_symbols = NO_DEBUG;
+ }
}
@@ -236,8 +280,6 @@ move_operand (op, mode)
if (GET_CODE (op) == CONST_INT)
return cint_ok_for_move (INTVAL (op));
- if (GET_MODE (op) != mode)
- return 0;
if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
if (GET_CODE (op) != MEM)
@@ -247,6 +289,23 @@ move_operand (op, mode)
if (GET_CODE (op) == LO_SUM)
return (register_operand (XEXP (op, 0), Pmode)
&& CONSTANT_P (XEXP (op, 1)));
+
+ /* Since move_operand is only used for source operands, we can always
+ allow scaled indexing! */
+ if (! TARGET_DISABLE_INDEXING
+ && GET_CODE (op) == PLUS
+ && ((GET_CODE (XEXP (op, 0)) == MULT
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
+ && INTVAL (XEXP (XEXP (op, 0), 1)) == GET_MODE_SIZE (mode)
+ && GET_CODE (XEXP (op, 1)) == REG)
+ || (GET_CODE (XEXP (op, 1)) == MULT
+ &&GET_CODE (XEXP (XEXP (op, 1), 0)) == REG
+ && GET_CODE (XEXP (XEXP (op, 1), 1)) == CONST_INT
+ && INTVAL (XEXP (XEXP (op, 1), 1)) == GET_MODE_SIZE (mode)
+ && GET_CODE (XEXP (op, 0)) == REG)))
+ return 1;
+
return memory_address_p (mode, op);
}
@@ -357,6 +416,19 @@ arith_double_operand (op, mode)
}
/* Return truth value of whether OP is a integer which fits the
+ range constraining immediate operands in three-address insns, or
+ is an integer register. */
+
+int
+ireg_or_int5_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ return ((GET_CODE (op) == CONST_INT && INT_5_BITS (op))
+ || (GET_CODE (op) == REG && REGNO (op) > 0 && REGNO (op) < 32));
+}
+
+/* Return truth value of whether OP is a integer which fits the
range constraining immediate operands in three-address insns. */
int
@@ -637,6 +709,16 @@ hppa_legitimize_address (x, oldx, mode)
if (GET_CODE (x) == CONST)
x = XEXP (x, 0);
+ /* Special case. Get the SYMBOL_REF into a register and use indexing.
+ That should always be safe. */
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == REG
+ && GET_CODE (XEXP (x, 1)) == SYMBOL_REF)
+ {
+ rtx reg = force_reg (SImode, XEXP (x, 1));
+ return force_reg (SImode, gen_rtx (PLUS, SImode, reg, XEXP (x, 0)));
+ }
+
/* Note we must reject symbols which represent function addresses
since the assembler/linker can't handle arithmetic on plabels. */
if (GET_CODE (x) == PLUS
@@ -693,14 +775,8 @@ hppa_legitimize_address (x, oldx, mode)
return plus_constant (ptr_reg, offset - newoffset);
}
- /* Try to arrange things so that indexing modes can be used, but
- only do so if indexing is safe.
+ /* Handle (plus (mult (a) (shadd_constant)) (b)). */
- Indexing is safe when the second operand for the outer PLUS
- is a REG, SUBREG, SYMBOL_REF or the like.
-
- For 2.5, indexing is also safe for (plus (symbol_ref) (const_int))
- if the integer is > 0. */
if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
&& shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1)))
@@ -710,33 +786,160 @@ hppa_legitimize_address (x, oldx, mode)
{
int val = INTVAL (XEXP (XEXP (x, 0), 1));
rtx reg1, reg2;
- reg1 = force_reg (Pmode, force_operand (XEXP (x, 1), 0));
- reg2 = force_reg (Pmode,
- force_operand (XEXP (XEXP (x, 0), 0), 0));
- return force_reg (Pmode,
- gen_rtx (PLUS, Pmode,
- gen_rtx (MULT, Pmode, reg2,
- GEN_INT (val)),
- reg1));
+
+ reg1 = XEXP (x, 1);
+ if (GET_CODE (reg1) != REG)
+ reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+ reg2 = XEXP (XEXP (x, 0), 0);
+ if (GET_CODE (reg2) != REG)
+ reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+ return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode,
+ reg2, GEN_INT (val)),
+ reg1));
+ }
+
+ /* Similarly for (plus (plus (mult (a) (shadd_constant)) (b)) (c)).
+
+ Only do so for floating point modes since this is more speculative
+ and we lose if it's an integer store. */
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT
+ && shadd_constant_p (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)))
+ && (mode == SFmode || mode == DFmode))
+ {
+
+ /* First, try and figure out what to use as a base register. */
+ rtx reg1, reg2, base, idx, orig_base;
+
+ reg1 = XEXP (XEXP (x, 0), 1);
+ reg2 = XEXP (x, 1);
+ base = NULL_RTX;
+ idx = NULL_RTX;
+
+ /* Make sure they're both regs. If one was a SYMBOL_REF [+ const],
+ then emit_move_sequence will turn on REGNO_POINTER_FLAG so we'll
+ know it's a base register below. */
+ if (GET_CODE (reg1) != REG)
+ reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+ if (GET_CODE (reg2) != REG)
+ reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+ /* Figure out what the base and index are. */
+
+ if (GET_CODE (reg1) == REG
+ && REGNO_POINTER_FLAG (REGNO (reg1)))
+ {
+ base = reg1;
+ orig_base = XEXP (XEXP (x, 0), 1);
+ idx = gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode,
+ XEXP (XEXP (XEXP (x, 0), 0), 0),
+ XEXP (XEXP (XEXP (x, 0), 0), 1)),
+ XEXP (x, 1));
+ }
+ else if (GET_CODE (reg2) == REG
+ && REGNO_POINTER_FLAG (REGNO (reg2)))
+ {
+ base = reg2;
+ orig_base = XEXP (x, 1);
+ idx = XEXP (x, 0);
+ }
+
+ if (base == 0)
+ return orig;
+
+ /* If the index adds a large constant, try to scale the
+ constant so that it can be loaded with only one insn. */
+ if (GET_CODE (XEXP (idx, 1)) == CONST_INT
+ && VAL_14_BITS_P (INTVAL (XEXP (idx, 1))
+ / INTVAL (XEXP (XEXP (idx, 0), 1)))
+ && INTVAL (XEXP (idx, 1)) % INTVAL (XEXP (XEXP (idx, 0), 1)) == 0)
+ {
+ /* Divide the CONST_INT by the scale factor, then add it to A. */
+ int val = INTVAL (XEXP (idx, 1));
+
+ val /= INTVAL (XEXP (XEXP (idx, 0), 1));
+ reg1 = XEXP (XEXP (idx, 0), 0);
+ if (GET_CODE (reg1) != REG)
+ reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+ reg1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, reg1, GEN_INT (val)));
+
+ /* We can now generate a simple scaled indexed address. */
+ return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode, reg1,
+ XEXP (XEXP (idx, 0), 1)),
+ base));
+ }
+
+ /* If B + C is still a valid base register, then add them. */
+ if (GET_CODE (XEXP (idx, 1)) == CONST_INT
+ && INTVAL (XEXP (idx, 1)) <= 4096
+ && INTVAL (XEXP (idx, 1)) >= -4096)
+ {
+ int val = INTVAL (XEXP (XEXP (idx, 0), 1));
+ rtx reg1, reg2;
+
+ reg1 = force_reg (Pmode, gen_rtx (PLUS, Pmode, base, XEXP (idx, 1)));
+
+ reg2 = XEXP (XEXP (idx, 0), 0);
+ if (GET_CODE (reg2) != CONST_INT)
+ reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+ return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode,
+ reg2, GEN_INT (val)),
+ reg1));
+ }
+
+ /* Get the index into a register, then add the base + index and
+ return a register holding the result. */
+
+ /* First get A into a register. */
+ reg1 = XEXP (XEXP (idx, 0), 0);
+ if (GET_CODE (reg1) != REG)
+ reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+ /* And get B into a register. */
+ reg2 = XEXP (idx, 1);
+ if (GET_CODE (reg2) != REG)
+ reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+ reg1 = force_reg (Pmode, gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode, reg1,
+ XEXP (XEXP (idx, 0), 1)),
+ reg2));
+
+ /* Add the result to our base register and return. */
+ return force_reg (Pmode, gen_rtx (PLUS, Pmode, base, reg1));
+
}
/* Uh-oh. We might have an address for x[n-100000]. This needs
- special handling. */
+ special handling to avoid creating an indexed memory address
+ with x-100000 as the base.
+
+ If the constant part is small enough, then it's still safe because
+ there is a guard page at the beginning and end of the data segment.
- if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == MULT
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+ Scaled references are common enough that we want to try and rearrange the
+ terms so that we can use indexing for these addresses too. Only
+ do the optimization for floatint point modes. */
+
+ if (GET_CODE (x) == PLUS
+ && symbolic_expression_p (XEXP (x, 1)))
{
/* Ugly. We modify things here so that the address offset specified
by the index expression is computed first, then added to x to form
- the entire address.
+ the entire address. */
- For 2.5, it might be profitable to set things up so that we
- compute the raw (unscaled) index first, then use scaled indexing
- to access memory, or better yet have the MI parts of the compiler
- handle this. */
-
- rtx regx1, regy1, regy2, y;
+ rtx regx1, regx2, regy1, regy2, y;
/* Strip off any CONST. */
y = XEXP (x, 1);
@@ -745,11 +948,80 @@ hppa_legitimize_address (x, oldx, mode)
if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
{
- regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
- regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
- regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
- regx1 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
- return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
+ /* See if this looks like
+ (plus (mult (reg) (shadd_const))
+ (const (plus (symbol_ref) (const_int))))
+
+ Where const_int is small. In that case the const
+ expression is a valid pointer for indexing.
+
+ If const_int is big, but can be divided evenly by shadd_const
+ and added to (reg). This allows more scaled indexed addresses. */
+ if (GET_CODE (XEXP (y, 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (x, 0)) == MULT
+ && GET_CODE (XEXP (y, 1)) == CONST_INT
+ && INTVAL (XEXP (y, 1)) >= -4096
+ && INTVAL (XEXP (y, 1)) <= 4095
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+ && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+ {
+ int val = INTVAL (XEXP (XEXP (x, 0), 1));
+ rtx reg1, reg2;
+
+ reg1 = XEXP (x, 1);
+ if (GET_CODE (reg1) != REG)
+ reg1 = force_reg (Pmode, force_operand (reg1, 0));
+
+ reg2 = XEXP (XEXP (x, 0), 0);
+ if (GET_CODE (reg2) != REG)
+ reg2 = force_reg (Pmode, force_operand (reg2, 0));
+
+ return force_reg (Pmode, gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode,
+ reg2, GEN_INT (val)),
+ reg1));
+ }
+ else if ((mode == DFmode || mode == SFmode)
+ && GET_CODE (XEXP (y, 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (x, 0)) == MULT
+ && GET_CODE (XEXP (y, 1)) == CONST_INT
+ && INTVAL (XEXP (y, 1)) % INTVAL (XEXP (XEXP (x, 0), 1)) == 0
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+ && shadd_constant_p (INTVAL (XEXP (XEXP (x, 0), 1))))
+ {
+ regx1
+ = force_reg (Pmode, GEN_INT (INTVAL (XEXP (y, 1))
+ / INTVAL (XEXP (XEXP (x, 0), 1))));
+ regx2 = XEXP (XEXP (x, 0), 0);
+ if (GET_CODE (regx2) != REG)
+ regx2 = force_reg (Pmode, force_operand (regx2, 0));
+ regx2 = force_reg (Pmode, gen_rtx (GET_CODE (y), Pmode,
+ regx2, regx1));
+ return force_reg (Pmode,
+ gen_rtx (PLUS, Pmode,
+ gen_rtx (MULT, Pmode, regx2,
+ XEXP (XEXP (x, 0), 1)),
+ force_reg (Pmode, XEXP (y, 0))));
+ }
+ else if (GET_CODE (XEXP (y, 1)) == CONST_INT
+ && INTVAL (XEXP (y, 1)) >= -4096
+ && INTVAL (XEXP (y, 1)) <= 4095)
+ {
+ /* This is safe because of the guard page at the
+ beginning and end of the data space. Just
+ return the original address. */
+ return orig;
+ }
+ else
+ {
+ /* Doesn't look like one we can optimize. */
+ regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
+ regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
+ regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
+ regx1 = force_reg (Pmode,
+ gen_rtx (GET_CODE (y), Pmode, regx1, regy2));
+ return force_reg (Pmode, gen_rtx (PLUS, Pmode, regx1, regy1));
+ }
}
}
@@ -791,9 +1063,31 @@ emit_move_sequence (operands, mode, scratch_reg)
register rtx operand0 = operands[0];
register rtx operand1 = operands[1];
+ if (reload_in_progress && GET_CODE (operand0) == REG
+ && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
+ operand0 = reg_equiv_mem[REGNO (operand0)];
+ else if (reload_in_progress && GET_CODE (operand0) == SUBREG
+ && GET_CODE (SUBREG_REG (operand0)) == REG
+ && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER)
+ {
+ SUBREG_REG (operand0) = reg_equiv_mem[REGNO (SUBREG_REG (operand0))];
+ operand0 = alter_subreg (operand0);
+ }
+
+ if (reload_in_progress && GET_CODE (operand1) == REG
+ && REGNO (operand1) >= FIRST_PSEUDO_REGISTER)
+ operand1 = reg_equiv_mem[REGNO (operand1)];
+ else if (reload_in_progress && GET_CODE (operand1) == SUBREG
+ && GET_CODE (SUBREG_REG (operand1)) == REG
+ && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER)
+ {
+ SUBREG_REG (operand1) = reg_equiv_mem[REGNO (SUBREG_REG (operand1))];
+ operand1 = alter_subreg (operand1);
+ }
+
/* Handle secondary reloads for loads/stores of FP registers from
REG+D addresses where D does not fit in 5 bits, including
- (subreg (mem (addr)) cases. */
+ (subreg (mem (addr))) cases. */
if (fp_reg_operand (operand0, mode)
&& ((GET_CODE (operand1) == MEM
&& ! memory_address_p (DFmode, XEXP (operand1, 0)))
@@ -887,7 +1181,21 @@ emit_move_sequence (operands, mode, scratch_reg)
&& FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1)))))
&& scratch_reg)
{
- emit_move_insn (scratch_reg, operand1);
+ /* D might not fit in 14 bits either; for such cases load D into
+ scratch reg. */
+ if (GET_CODE (operand1) == MEM
+ && !memory_address_p (SImode, XEXP (operand1, 0)))
+ {
+ emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1));
+ emit_move_insn (scratch_reg, gen_rtx (GET_CODE (XEXP (operand1, 0)),
+ SImode,
+ XEXP (XEXP (operand1, 0), 0),
+ scratch_reg));
+ emit_move_insn (scratch_reg, gen_rtx (MEM, GET_MODE (operand1),
+ scratch_reg));
+ }
+ else
+ emit_move_insn (scratch_reg, operand1);
emit_move_insn (operand0, scratch_reg);
return 1;
}
@@ -909,6 +1217,15 @@ emit_move_sequence (operands, mode, scratch_reg)
}
else if (GET_CODE (operand0) == MEM)
{
+ if (mode == DFmode && operand1 == CONST0_RTX (mode)
+ && !(reload_in_progress || reload_completed))
+ {
+ rtx temp = gen_reg_rtx (DFmode);
+
+ emit_insn (gen_rtx (SET, VOIDmode, temp, operand1));
+ emit_insn (gen_rtx (SET, VOIDmode, operand0, temp));
+ return 1;
+ }
if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode))
{
/* Run this case quickly. */
@@ -936,27 +1253,51 @@ emit_move_sequence (operands, mode, scratch_reg)
}
if (symbolic_operand (operand1, mode))
{
- rtx const_part = NULL;
-
/* Argh. The assembler and linker can't handle arithmetic
- involving plabels. We'll have to split up operand1 here
- if it's a function label involved in an arithmetic
- expression. Luckily, this only happens with addition
- of constants to plabels, which simplifies the test.
+ involving plabels.
- We add the constant back in just before returning to
- our caller. */
+ So we force the plabel into memory, load operand0 from
+ the memory location, then add in the constant part. */
if (GET_CODE (operand1) == CONST
&& GET_CODE (XEXP (operand1, 0)) == PLUS
&& function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode))
{
+ rtx temp, const_part;
+
+ /* Figure out what (if any) scratch register to use. */
+ if (reload_in_progress || reload_completed)
+ scratch_reg = scratch_reg ? scratch_reg : operand0;
+ else if (flag_pic)
+ scratch_reg = gen_reg_rtx (Pmode);
+
/* Save away the constant part of the expression. */
const_part = XEXP (XEXP (operand1, 0), 1);
if (GET_CODE (const_part) != CONST_INT)
abort ();
- /* Set operand1 to just the SYMBOL_REF. */
- operand1 = XEXP (XEXP (operand1, 0), 0);
+ /* Force the function label into memory. */
+ temp = force_const_mem (mode, XEXP (XEXP (operand1, 0), 0));
+
+ /* Get the address of the memory location. PIC-ify it if
+ necessary. */
+ temp = XEXP (temp, 0);
+ if (flag_pic)
+ temp = legitimize_pic_address (temp, mode, scratch_reg);
+
+ /* Put the address of the memory location into our destination
+ register. */
+ operands[1] = temp;
+ emit_move_sequence (operands, mode, scratch_reg);
+
+ /* Now load from the memory location into our destination
+ register. */
+ operands[1] = gen_rtx (MEM, Pmode, operands[0]);
+ emit_move_sequence (operands, mode, scratch_reg);
+
+ /* And add back in the constant part. */
+ expand_inc (operand0, const_part);
+
+ return 1;
}
if (flag_pic)
@@ -968,17 +1309,10 @@ emit_move_sequence (operands, mode, scratch_reg)
else
temp = gen_reg_rtx (Pmode);
- /* If operand1 is a function label, then we've got to
- force it to memory, then load op0 from memory. */
- if (function_label_operand (operand1, mode))
- {
- operands[1] = force_const_mem (mode, operand1);
- emit_move_sequence (operands, mode, temp);
- }
- /* Likewise for (const (plus (symbol) (const_int)) when generating
- pic code during or after reload and const_int will not fit
+ /* (const (plus (symbol) (const_int))) must be forced to
+ memory during/after reload if the const_int will not fit
in 14 bits. */
- else if (GET_CODE (operand1) == CONST
+ if (GET_CODE (operand1) == CONST
&& GET_CODE (XEXP (operand1, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT
&& !INT_14_BITS (XEXP (XEXP (operand1, 0), 1))
@@ -1008,6 +1342,15 @@ emit_move_sequence (operands, mode, scratch_reg)
else
temp = gen_reg_rtx (mode);
+ /* Loading a SYMBOL_REF into a register makes that register
+ safe to be used as the base in an indexed address.
+
+ Don't mark hard registers though. That loses. */
+ if (GET_CODE (operand0) == REG
+ && REGNO (operand0) >= FIRST_PSEUDO_REGISTER)
+ REGNO_POINTER_FLAG (REGNO (operand0)) = 1;
+ if (REGNO (temp) >= FIRST_PSEUDO_REGISTER)
+ REGNO_POINTER_FLAG (REGNO (temp)) = 1;
if (ishighonly)
set = gen_rtx (SET, mode, operand0, temp);
else
@@ -1021,10 +1364,6 @@ emit_move_sequence (operands, mode, scratch_reg)
emit_insn (set);
}
-
- /* Add back in the constant part if needed. */
- if (const_part != NULL)
- expand_inc (operand0, const_part);
return 1;
}
else if (GET_CODE (operand1) != CONST_INT
@@ -1046,6 +1385,47 @@ emit_move_sequence (operands, mode, scratch_reg)
return 0;
}
+/* Examine EXP and return nonzero if it contains an ADDR_EXPR (meaning
+ it will need a link/runtime reloc). */
+
+int
+reloc_needed (exp)
+ tree exp;
+{
+ int reloc = 0;
+
+ switch (TREE_CODE (exp))
+ {
+ case ADDR_EXPR:
+ return 1;
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ reloc = reloc_needed (TREE_OPERAND (exp, 0));
+ reloc |= reloc_needed (TREE_OPERAND (exp, 1));
+ break;
+
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ reloc = reloc_needed (TREE_OPERAND (exp, 0));
+ break;
+
+ case CONSTRUCTOR:
+ {
+ register tree link;
+ for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+ if (TREE_VALUE (link) != 0)
+ reloc |= reloc_needed (TREE_VALUE (link));
+ }
+ break;
+
+ case ERROR_MARK:
+ break;
+ }
+ return reloc;
+}
+
/* Does operand (which is a symbolic_operand) live in text space? If
so SYMBOL_REF_FLAG, which is set by ENCODE_SECTION_INFO, will be true. */
@@ -1306,6 +1686,35 @@ output_move_double (operands)
return "ldw -4(0,%1),%R0\n\tldws,mb -8(0,%1),%0";
}
}
+ else if (GET_CODE (addr) == PLUS
+ && GET_CODE (XEXP (addr, 0)) == MULT)
+ {
+ rtx high_reg = gen_rtx (SUBREG, SImode, operands[0], 0);
+
+ if (!reg_overlap_mentioned_p (high_reg, addr))
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = high_reg;
+ xoperands[1] = XEXP (addr, 1);
+ xoperands[2] = XEXP (XEXP (addr, 0), 0);
+ xoperands[3] = XEXP (XEXP (addr, 0), 1);
+ output_asm_insn ("sh%O3addl %2,%1,%0", xoperands);
+ return "ldw 4(0,%0),%R0\n\tldw 0(0,%0),%0";
+ }
+ else
+ {
+ rtx xoperands[3];
+
+ xoperands[0] = high_reg;
+ xoperands[1] = XEXP (addr, 1);
+ xoperands[2] = XEXP (XEXP (addr, 0), 0);
+ xoperands[3] = XEXP (XEXP (addr, 0), 1);
+ output_asm_insn ("sh%O3addl %2,%1,%R0", xoperands);
+ return "ldw 0(0,%R0),%0\n\tldw 4(0,%R0),%R0";
+ }
+
+ }
}
/* If an operand is an unoffsettable memory ref, find a register
@@ -1343,28 +1752,36 @@ output_move_double (operands)
/* If the first move would clobber the source of the second one,
do them in the other order.
- RMS says "This happens only for registers;
- such overlap can't happen in memory unless the user explicitly
- sets it up, and that is an undefined circumstance."
+ This can happen in two cases:
+
+ mem -> register where the first half of the destination register
+ is the same register used in the memory's address. Reload
+ can create such insns.
- but it happens on the HP-PA when loading parameter registers,
- so I am going to define that circumstance, and make it work
- as expected. */
+ mem in this case will be either register indirect or register
+ indirect plus a valid offset.
- if (optype0 == REGOP && (optype1 == MEMOP || optype1 == OFFSOP)
- && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
+ register -> register move where REGNO(dst) == REGNO(src + 1)
+ someone (Tim/Tege?) claimed this can happen for parameter loads.
+
+ Handle mem -> register case first. */
+ if (optype0 == REGOP
+ && (optype1 == MEMOP || optype1 == OFFSOP)
+ && refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+ operands[1], 0))
{
- /* XXX THIS PROBABLY DOESN'T WORK. */
/* Do the late half first. */
if (addreg1)
output_asm_insn ("ldo 4(%0),%0", &addreg1);
output_asm_insn (singlemove_string (latehalf), latehalf);
+
+ /* Then clobber. */
if (addreg1)
output_asm_insn ("ldo -4(%0),%0", &addreg1);
- /* Then clobber. */
return singlemove_string (operands);
}
+ /* Now handle register -> register case. */
if (optype0 == REGOP && optype1 == REGOP
&& REGNO (operands[0]) == REGNO (operands[1]) + 1)
{
@@ -1404,11 +1821,11 @@ output_fp_move_double (operands)
|| operands[1] == CONST0_RTX (GET_MODE (operands[0])))
output_asm_insn ("fcpy,dbl %r1,%0", operands);
else
- output_asm_insn ("fldds%F1 %1,%0", operands);
+ output_asm_insn ("fldd%F1 %1,%0", operands);
}
else if (FP_REG_P (operands[1]))
{
- output_asm_insn ("fstds%F0 %1,%0", operands);
+ output_asm_insn ("fstd%F0 %1,%0", operands);
}
else if (operands[1] == CONST0_RTX (GET_MODE (operands[0])))
{
@@ -1457,18 +1874,13 @@ find_addr_reg (addr)
/* Emit code to perform a block move.
- Restriction: If the length argument is non-constant, alignment
- must be 4.
-
OPERANDS[0] is the destination pointer as a REG, clobbered.
OPERANDS[1] is the source pointer as a REG, clobbered.
- if SIZE_IS_CONSTANT
- OPERANDS[2] is a register for temporary storage.
- OPERANDS[4] is the size as a CONST_INT
- else
- OPERANDS[2] is a REG which will contain the size, clobbered.
+ OPERANDS[2] is a register for temporary storage.
+ OPERANDS[4] is the size as a CONST_INT
OPERANDS[3] is a register for temporary storage.
- OPERANDS[5] is the alignment safe to use, as a CONST_INT. */
+ OPERANDS[5] is the alignment safe to use, as a CONST_INT.
+ OPERANDS[6] is another temporary register. */
char *
output_block_move (operands, size_is_constant)
@@ -1476,153 +1888,94 @@ output_block_move (operands, size_is_constant)
int size_is_constant;
{
int align = INTVAL (operands[5]);
- unsigned long n_bytes;
+ unsigned long n_bytes = INTVAL (operands[4]);
/* We can't move more than four bytes at a time because the PA
has no longer integer move insns. (Could use fp mem ops?) */
if (align > 4)
align = 4;
- if (size_is_constant)
+ /* Note that we know each loop below will execute at least twice
+ (else we would have open-coded the copy). */
+ switch (align)
{
- unsigned long offset;
- rtx temp;
-
- n_bytes = INTVAL (operands[4]);
- if (n_bytes == 0)
+ case 4:
+ /* Pre-adjust the loop counter. */
+ operands[4] = GEN_INT (n_bytes - 8);
+ output_asm_insn ("ldi %4,%2", operands);
+
+ /* Copying loop. */
+ output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
+ output_asm_insn ("ldws,ma 4(0,%1),%6", operands);
+ output_asm_insn ("stws,ma %3,4(0,%0)", operands);
+ output_asm_insn ("addib,>= -8,%2,.-12", operands);
+ output_asm_insn ("stws,ma %6,4(0,%0)", operands);
+
+ /* Handle the residual. There could be up to 7 bytes of
+ residual to copy! */
+ if (n_bytes % 8 != 0)
+ {
+ operands[4] = GEN_INT (n_bytes % 4);
+ if (n_bytes % 8 >= 4)
+ output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
+ if (n_bytes % 4 != 0)
+ output_asm_insn ("ldw 0(0,%1),%6", operands);
+ if (n_bytes % 8 >= 4)
+ output_asm_insn ("stws,ma %3,4(0,%0)", operands);
+ if (n_bytes % 4 != 0)
+ output_asm_insn ("stbys,e %6,%4(0,%0)", operands);
+ }
return "";
- if (align >= 4)
- {
- /* Don't unroll too large blocks. */
- if (n_bytes > 32)
- goto copy_with_loop;
-
- /* Read and store using two registers, and hide latency
- by deferring the stores until three instructions after
- the corresponding load. The last load insn will read
- the entire word were the last bytes are, possibly past
- the end of the source block, but since loads are aligned,
- this is harmless. */
+ case 2:
+ /* Pre-adjust the loop counter. */
+ operands[4] = GEN_INT (n_bytes - 4);
+ output_asm_insn ("ldi %4,%2", operands);
- output_asm_insn ("ldws,ma 4(0,%1),%2", operands);
+ /* Copying loop. */
+ output_asm_insn ("ldhs,ma 2(0,%1),%3", operands);
+ output_asm_insn ("ldhs,ma 2(0,%1),%6", operands);
+ output_asm_insn ("sths,ma %3,2(0,%0)", operands);
+ output_asm_insn ("addib,>= -4,%2,.-12", operands);
+ output_asm_insn ("sths,ma %6,2(0,%0)", operands);
- for (offset = 4; offset < n_bytes; offset += 4)
- {
- output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
- output_asm_insn ("stws,ma %2,4(0,%0)", operands);
-
- temp = operands[2];
- operands[2] = operands[3];
- operands[3] = temp;
- }
- if (n_bytes % 4 == 0)
- /* Store the last word. */
- output_asm_insn ("stw %2,0(0,%0)", operands);
- else
- {
- /* Store the last, partial word. */
- operands[4] = GEN_INT (n_bytes % 4);
- output_asm_insn ("stbys,e %2,%4(0,%0)", operands);
- }
- return "";
- }
-
- if (align >= 2 && n_bytes >= 2)
- {
- output_asm_insn ("ldhs,ma 2(0,%1),%2", operands);
-
- for (offset = 2; offset + 2 <= n_bytes; offset += 2)
- {
+ /* Handle the residual. */
+ if (n_bytes % 4 != 0)
+ {
+ if (n_bytes % 4 >= 2)
output_asm_insn ("ldhs,ma 2(0,%1),%3", operands);
- output_asm_insn ("sths,ma %2,2(0,%0)", operands);
+ if (n_bytes % 2 != 0)
+ output_asm_insn ("ldb 0(0,%1),%6", operands);
+ if (n_bytes % 4 >= 2)
+ output_asm_insn ("sths,ma %3,2(0,%0)", operands);
+ if (n_bytes % 2 != 0)
+ output_asm_insn ("stb %6,0(0,%0)", operands);
+ }
+ return "";
- temp = operands[2];
- operands[2] = operands[3];
- operands[3] = temp;
- }
- if (n_bytes % 2 != 0)
- output_asm_insn ("ldb 0(0,%1),%3", operands);
+ case 1:
+ /* Pre-adjust the loop counter. */
+ operands[4] = GEN_INT (n_bytes - 2);
+ output_asm_insn ("ldi %4,%2", operands);
- output_asm_insn ("sths,ma %2,2(0,%0)", operands);
+ /* Copying loop. */
+ output_asm_insn ("ldbs,ma 1(0,%1),%3", operands);
+ output_asm_insn ("ldbs,ma 1(0,%1),%6", operands);
+ output_asm_insn ("stbs,ma %3,1(0,%0)", operands);
+ output_asm_insn ("addib,>= -2,%2,.-12", operands);
+ output_asm_insn ("stbs,ma %6,1(0,%0)", operands);
- if (n_bytes % 2 != 0)
+ /* Handle the residual. */
+ if (n_bytes % 2 != 0)
+ {
+ output_asm_insn ("ldb 0(0,%1),%3", operands);
output_asm_insn ("stb %3,0(0,%0)", operands);
+ }
+ return "";
- return "";
- }
-
- output_asm_insn ("ldbs,ma 1(0,%1),%2", operands);
-
- for (offset = 1; offset + 1 <= n_bytes; offset += 1)
- {
- output_asm_insn ("ldbs,ma 1(0,%1),%3", operands);
- output_asm_insn ("stbs,ma %2,1(0,%0)", operands);
-
- temp = operands[2];
- operands[2] = operands[3];
- operands[3] = temp;
- }
- output_asm_insn ("stb %2,0(0,%0)", operands);
-
- return "";
- }
-
- if (align != 4)
- abort();
-
- copy_with_loop:
-
- if (size_is_constant)
- {
- /* Size is compile-time determined, and also not
- very small (such small cases are handled above). */
- operands[4] = GEN_INT (n_bytes - 4);
- output_asm_insn ("ldo %4(0),%2", operands);
- }
- else
- {
- /* Decrement counter by 4, and if it becomes negative, jump past the
- word copying loop. */
- output_asm_insn ("addib,<,n -4,%2,.+16", operands);
- }
-
- /* Copying loop. Note that the first load is in the annulled delay slot
- of addib. Is it OK on PA to have a load in a delay slot, i.e. is a
- possible page fault stopped in time? */
- output_asm_insn ("ldws,ma 4(0,%1),%3", operands);
- output_asm_insn ("addib,>= -4,%2,.-4", operands);
- output_asm_insn ("stws,ma %3,4(0,%0)", operands);
-
- /* The counter is negative, >= -4. The remaining number of bytes are
- determined by the two least significant bits. */
-
- if (size_is_constant)
- {
- if (n_bytes % 4 != 0)
- {
- /* Read the entire word of the source block tail. */
- output_asm_insn ("ldw 0(0,%1),%3", operands);
- operands[4] = GEN_INT (n_bytes % 4);
- output_asm_insn ("stbys,e %3,%4(0,%0)", operands);
- }
- }
- else
- {
- /* Add 4 to counter. If it becomes zero, we're done. */
- output_asm_insn ("addib,=,n 4,%2,.+16", operands);
-
- /* Read the entire word of the source block tail. (Also this
- load is in an annulled delay slot.) */
- output_asm_insn ("ldw 0(0,%1),%3", operands);
-
- /* Make %0 point at the first byte after the destination block. */
- output_asm_insn ("addl %2,%0,%0", operands);
- /* Store the leftmost bytes, up to, but not including, the address
- in %0. */
- output_asm_insn ("stbys,e %3,0(0,%0)", operands);
+ default:
+ abort ();
}
- return "";
}
/* Count the number of insns necessary to handle this block move.
@@ -1635,106 +1988,30 @@ compute_movstrsi_length (insn)
rtx insn;
{
rtx pat = PATTERN (insn);
- int size_is_constant;
int align = INTVAL (XEXP (XVECEXP (pat, 0, 6), 0));
- unsigned long n_bytes;
- int insn_count = 0;
-
- if (GET_CODE (XEXP (XVECEXP (pat, 0, 5), 0)) == CONST_INT)
- {
- size_is_constant = 1;
- n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 5), 0));
- }
- else
- {
- size_is_constant = 0;
- n_bytes = 0;
- }
+ unsigned long n_bytes = INTVAL (XEXP (XVECEXP (pat, 0, 5), 0));
+ unsigned int n_insns = 0;
/* We can't move more than four bytes at a time because the PA
has no longer integer move insns. (Could use fp mem ops?) */
if (align > 4)
align = 4;
- if (size_is_constant)
- {
- unsigned long offset;
-
- if (n_bytes == 0)
- return 0;
-
- if (align >= 4)
- {
- /* Don't unroll too large blocks. */
- if (n_bytes > 32)
- goto copy_with_loop;
-
- /* first load */
- insn_count = 1;
-
- /* Count the unrolled insns. */
- for (offset = 4; offset < n_bytes; offset += 4)
- insn_count += 2;
-
- /* Count last store or partial store. */
- insn_count += 1;
- return insn_count * 4;
- }
-
- if (align >= 2 && n_bytes >= 2)
- {
- /* initial load. */
- insn_count = 1;
-
- /* Unrolled loop. */
- for (offset = 2; offset + 2 <= n_bytes; offset += 2)
- insn_count += 2;
-
- /* ??? odd load/store */
- if (n_bytes % 2 != 0)
- insn_count += 2;
-
- /* ??? final store from loop. */
- insn_count += 1;
-
- return insn_count * 4;
- }
-
- /* First load. */
- insn_count = 1;
+ /* The basic copying loop. */
+ n_insns = 6;
- /* The unrolled loop. */
- for (offset = 1; offset + 1 <= n_bytes; offset += 1)
- insn_count += 2;
-
- /* Final store. */
- insn_count += 1;
+ /* Residuals. */
+ if (n_bytes % (2 * align) != 0)
+ {
+ if ((n_bytes % (2 * align)) >= align)
+ n_insns += 2;
- return insn_count * 4;
+ if ((n_bytes % align) != 0)
+ n_insns += 2;
}
- if (align != 4)
- abort();
-
- copy_with_loop:
-
- /* setup for constant and non-constant case. */
- insn_count = 1;
-
- /* The copying loop. */
- insn_count += 3;
-
- /* The counter is negative, >= -4. The remaining number of bytes are
- determined by the two least significant bits. */
-
- if (size_is_constant)
- {
- if (n_bytes % 4 != 0)
- insn_count += 2;
- }
- else
- insn_count += 4;
- return insn_count * 4;
+ /* Lengths are expressed in bytes now; each insn is 4 bytes. */
+ return n_insns * 4;
}
@@ -1835,7 +2112,7 @@ output_ascii (file, p, size)
restriction is in number of input characters (see \xnn &
\whatever). So we have to do this very carefully. */
- fprintf (file, "\t.STRING \"");
+ fputs ("\t.STRING \"", file);
chars_output = 0;
for (i = 0; i < size; i += 4)
@@ -1867,14 +2144,165 @@ output_ascii (file, p, size)
}
if (chars_output + co > 243)
{
- fprintf (file, "\"\n\t.STRING \"");
+ fputs ("\"\n\t.STRING \"", file);
chars_output = 0;
}
fwrite (partial_output, 1, co, file);
chars_output += co;
co = 0;
}
- fprintf (file, "\"\n");
+ fputs ("\"\n", file);
+}
+
+/* Try to rewrite floating point comparisons & branches to avoid
+ useless add,tr insns.
+
+ CHECK_NOTES is nonzero if we should examine REG_DEAD notes
+ to see if FPCC is dead. CHECK_NOTES is nonzero for the
+ first attempt to remove useless add,tr insns. It is zero
+ for the second pass as reorg sometimes leaves bogus REG_DEAD
+ notes lying around.
+
+ When CHECK_NOTES is zero we can only eliminate add,tr insns
+ when there's a 1:1 correspondence between fcmp and ftest/fbranch
+ instructions. */
+void
+remove_useless_addtr_insns (insns, check_notes)
+ rtx insns;
+ int check_notes;
+{
+ rtx insn;
+ int all;
+ static int pass = 0;
+
+ /* This is fairly cheap, so always run it when optimizing. */
+ if (optimize > 0)
+ {
+ int fcmp_count = 0;
+ int fbranch_count = 0;
+
+ /* Walk all the insns in this function looking for fcmp & fbranch
+ instructions. Keep track of how many of each we find. */
+ insns = get_insns ();
+ for (insn = insns; insn; insn = next_insn (insn))
+ {
+ rtx tmp;
+
+ /* Ignore anything that isn't an INSN or a JUMP_INSN. */
+ if (GET_CODE (insn) != INSN && GET_CODE (insn) != JUMP_INSN)
+ continue;
+
+ tmp = PATTERN (insn);
+
+ /* It must be a set. */
+ if (GET_CODE (tmp) != SET)
+ continue;
+
+ /* If the destination is CCFP, then we've found an fcmp insn. */
+ tmp = SET_DEST (tmp);
+ if (GET_CODE (tmp) == REG && REGNO (tmp) == 0)
+ {
+ fcmp_count++;
+ continue;
+ }
+
+ tmp = PATTERN (insn);
+ /* If this is an fbranch instruction, bump the fbranch counter. */
+ if (GET_CODE (tmp) == SET
+ && SET_DEST (tmp) == pc_rtx
+ && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
+ && GET_CODE (XEXP (SET_SRC (tmp), 0)) == NE
+ && GET_CODE (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == REG
+ && REGNO (XEXP (XEXP (SET_SRC (tmp), 0), 0)) == 0)
+ {
+ fbranch_count++;
+ continue;
+ }
+ }
+
+
+ /* Find all floating point compare + branch insns. If possible,
+ reverse the comparison & the branch to avoid add,tr insns. */
+ for (insn = insns; insn; insn = next_insn (insn))
+ {
+ rtx tmp, next;
+
+ /* Ignore anything that isn't an INSN. */
+ if (GET_CODE (insn) != INSN)
+ continue;
+
+ tmp = PATTERN (insn);
+
+ /* It must be a set. */
+ if (GET_CODE (tmp) != SET)
+ continue;
+
+ /* The destination must be CCFP, which is register zero. */
+ tmp = SET_DEST (tmp);
+ if (GET_CODE (tmp) != REG || REGNO (tmp) != 0)
+ continue;
+
+ /* INSN should be a set of CCFP.
+
+ See if the result of this insn is used in a reversed FP
+ conditional branch. If so, reverse our condition and
+ the branch. Doing so avoids useless add,tr insns. */
+ next = next_insn (insn);
+ while (next)
+ {
+ /* Jumps, calls and labels stop our search. */
+ if (GET_CODE (next) == JUMP_INSN
+ || GET_CODE (next) == CALL_INSN
+ || GET_CODE (next) == CODE_LABEL)
+ break;
+
+ /* As does another fcmp insn. */
+ if (GET_CODE (next) == INSN
+ && GET_CODE (PATTERN (next)) == SET
+ && GET_CODE (SET_DEST (PATTERN (next))) == REG
+ && REGNO (SET_DEST (PATTERN (next))) == 0)
+ break;
+
+ next = next_insn (next);
+ }
+
+ /* Is NEXT_INSN a branch? */
+ if (next
+ && GET_CODE (next) == JUMP_INSN)
+ {
+ rtx pattern = PATTERN (next);
+
+ /* If it a reversed fp conditional branch (eg uses add,tr)
+ and CCFP dies, then reverse our conditional and the branch
+ to avoid the add,tr. */
+ if (GET_CODE (pattern) == SET
+ && SET_DEST (pattern) == pc_rtx
+ && GET_CODE (SET_SRC (pattern)) == IF_THEN_ELSE
+ && GET_CODE (XEXP (SET_SRC (pattern), 0)) == NE
+ && GET_CODE (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == REG
+ && REGNO (XEXP (XEXP (SET_SRC (pattern), 0), 0)) == 0
+ && GET_CODE (XEXP (SET_SRC (pattern), 1)) == PC
+ && (fcmp_count == fbranch_count
+ || (check_notes
+ && find_regno_note (next, REG_DEAD, 0))))
+ {
+ /* Reverse the branch. */
+ tmp = XEXP (SET_SRC (pattern), 1);
+ XEXP (SET_SRC (pattern), 1) = XEXP (SET_SRC (pattern), 2);
+ XEXP (SET_SRC (pattern), 2) = tmp;
+ INSN_CODE (next) = -1;
+
+ /* Reverse our condition. */
+ tmp = PATTERN (insn);
+ PUT_CODE (XEXP (tmp, 1),
+ reverse_condition (GET_CODE (XEXP (tmp, 1))));
+ }
+ }
+ }
+ }
+
+ pass = !pass;
+
}
/* You may have trouble believing this, but this is the HP-PA stack
@@ -2046,26 +2474,32 @@ compute_frame_size (size, fregs_live)
we need to add this in because of STARTING_FRAME_OFFSET. */
fsize = size + (size || frame_pointer_needed ? 8 : 0);
- for (i = 18; i >= 4; i--)
- {
- if (regs_ever_live[i])
- fsize += 4;
- }
- /* If we don't have a frame pointer, the register normally used for that
- purpose is saved just like other registers, not in the "frame marker". */
- if (! frame_pointer_needed)
- {
- if (regs_ever_live[FRAME_POINTER_REGNUM])
- fsize += 4;
- }
+ /* We must leave enough space for all the callee saved registers
+ from 3 .. highest used callee save register since we don't
+ know if we're going to have an inline or out of line prologue
+ and epilogue. */
+ for (i = 18; i >= 3; i--)
+ if (regs_ever_live[i])
+ {
+ fsize += 4 * (i - 2);
+ break;
+ }
+
+ /* Round the stack. */
fsize = (fsize + 7) & ~7;
+ /* We must leave enough space for all the callee saved registers
+ from 3 .. highest used callee save register since we don't
+ know if we're going to have an inline or out of line prologue
+ and epilogue. */
for (i = 66; i >= 48; i -= 2)
if (regs_ever_live[i] || regs_ever_live[i + 1])
{
- fsize += 8;
if (fregs_live)
*fregs_live = 1;
+
+ fsize += 4 * (i - 46);
+ break;
}
fsize += current_function_outgoing_args_size;
@@ -2092,12 +2526,12 @@ output_function_prologue (file, size)
of a function. */
fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);
if (regs_ever_live[2] || profile_flag)
- fprintf (file, ",CALLS,SAVE_RP");
+ fputs (",CALLS,SAVE_RP", file);
else
- fprintf (file, ",NO_CALLS");
+ fputs (",NO_CALLS", file);
if (frame_pointer_needed)
- fprintf (file, ",SAVE_SP");
+ fputs (",SAVE_SP", file);
/* Pass on information about the number of callee register saves
performed in the prologue.
@@ -2113,7 +2547,7 @@ output_function_prologue (file, size)
if (fr_saved)
fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);
- fprintf (file, "\n\t.ENTRY\n");
+ fputs ("\n\t.ENTRY\n", file);
/* Horrid hack. emit_function_prologue will modify this RTL in
place to get the expected results. */
@@ -2121,18 +2555,27 @@ output_function_prologue (file, size)
ASM_GENERATE_INTERNAL_LABEL (hp_profile_label_name, "LP",
hp_profile_labelno);
- if (insn_addresses)
+ /* If we're using GAS and not using the portable runtime model, then
+ we don't need to accumulate the total number of code bytes. */
+ if (TARGET_GAS && ! TARGET_PORTABLE_RUNTIME)
+ total_code_bytes = 0;
+ else if (insn_addresses)
{
unsigned int old_total = total_code_bytes;
total_code_bytes += insn_addresses[INSN_UID (get_last_insn())];
- total_code_bytes += FUNCTION_BOUNDARY /BITS_PER_UNIT;
+ total_code_bytes += FUNCTION_BOUNDARY / BITS_PER_UNIT;
/* Be prepared to handle overflows. */
total_code_bytes = old_total > total_code_bytes ? -1 : total_code_bytes;
}
else
total_code_bytes = -1;
+
+ remove_useless_addtr_insns (get_insns (), 0);
+
+ /* Restore INSN_CODEs for insn which use unscaled indexed addresses. */
+ restore_unscaled_index_insn_codes (get_insns ());
}
void
@@ -2154,6 +2597,91 @@ hppa_expand_prologue()
tmpreg = gen_rtx (REG, SImode, 1);
size_rtx = GEN_INT (actual_fsize);
+ /* Handle out of line prologues and epilogues. */
+ if (TARGET_SPACE)
+ {
+ rtx operands[2];
+ int saves = 0;
+ int outline_insn_count = 0;
+ int inline_insn_count = 0;
+
+ /* Count the number of insns for the inline and out of line
+ variants so we can choose one appropriately.
+
+ No need to screw with counting actual_fsize operations -- they're
+ done for both inline and out of line prologues. */
+ if (regs_ever_live[2])
+ inline_insn_count += 1;
+
+ if (! cint_ok_for_move (local_fsize))
+ outline_insn_count += 2;
+ else
+ outline_insn_count += 1;
+
+ /* Put the register save info into %r22. */
+ for (i = 18; i >= 3; i--)
+ if (regs_ever_live[i] && ! call_used_regs[i])
+ {
+ /* -1 because the stack adjustment is normally done in
+ the same insn as a register save. */
+ inline_insn_count += (i - 2) - 1;
+ saves = i;
+ break;
+ }
+
+ for (i = 66; i >= 48; i -= 2)
+ if (regs_ever_live[i] || regs_ever_live[i + 1])
+ {
+ /* +1 needed as we load %r1 with the start of the freg
+ save area. */
+ inline_insn_count += (i/2 - 23) + 1;
+ saves |= ((i/2 - 12 ) << 16);
+ break;
+ }
+
+ if (frame_pointer_needed)
+ inline_insn_count += 3;
+
+ if (! cint_ok_for_move (saves))
+ outline_insn_count += 2;
+ else
+ outline_insn_count += 1;
+
+ if (TARGET_PORTABLE_RUNTIME)
+ outline_insn_count += 2;
+ else
+ outline_insn_count += 1;
+
+ /* If there's a lot of insns in the prologue, then do it as
+ an out-of-line sequence. */
+ if (inline_insn_count > outline_insn_count)
+ {
+ /* Put the local_fisze into %r19. */
+ operands[0] = gen_rtx (REG, SImode, 19);
+ operands[1] = GEN_INT (local_fsize);
+ emit_move_insn (operands[0], operands[1]);
+
+ /* Put the stack size into %r21. */
+ operands[0] = gen_rtx (REG, SImode, 21);
+ operands[1] = size_rtx;
+ emit_move_insn (operands[0], operands[1]);
+
+ operands[0] = gen_rtx (REG, SImode, 22);
+ operands[1] = GEN_INT (saves);
+ emit_move_insn (operands[0], operands[1]);
+
+ /* Now call the out-of-line prologue. */
+ emit_insn (gen_outline_prologue_call ());
+ emit_insn (gen_blockage ());
+
+ /* Note that we're using an out-of-line prologue. */
+ out_of_line_prologue_epilogue = 1;
+ return;
+ }
+ }
+
+ out_of_line_prologue_epilogue = 0;
+
/* Save RP first. The calling conventions manual states RP will
always be stored into the caller's frame at sp-20. */
if (regs_ever_live[2] || profile_flag)
@@ -2172,9 +2700,7 @@ hppa_expand_prologue()
emit_move_insn (tmpreg, frame_pointer_rtx);
emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
if (VAL_14_BITS_P (actual_fsize))
- emit_insn (gen_post_stwm (stack_pointer_rtx,
- stack_pointer_rtx,
- size_rtx, tmpreg));
+ emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, size_rtx));
else
{
/* It is incorrect to store the saved frame pointer at *sp,
@@ -2183,9 +2709,7 @@ hppa_expand_prologue()
So instead use stwm to store at *sp and post-increment the
stack pointer as an atomic operation. Then increment sp to
finish allocating the new frame. */
- emit_insn (gen_post_stwm (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (64), tmpreg));
+ emit_insn (gen_post_stwm (stack_pointer_rtx, tmpreg, GEN_INT (64)));
set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM,
actual_fsize - 64);
@@ -2289,7 +2813,7 @@ hppa_expand_prologue()
offset += 4;
gr_saved++;
}
- /* Account for %r4 which is saved in a special place. */
+ /* Account for %r3 which is saved in a special place. */
gr_saved++;
}
/* No frame pointer needed. */
@@ -2304,9 +2828,8 @@ hppa_expand_prologue()
{
merge_sp_adjust_with_store = 0;
emit_insn (gen_post_stwm (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (-offset),
- gen_rtx (REG, SImode, i)));
+ gen_rtx (REG, SImode, i),
+ GEN_INT (-offset)));
}
else
store_reg (i, offset, STACK_POINTER_REGNUM);
@@ -2328,7 +2851,6 @@ hppa_expand_prologue()
/* Floating point register store. */
if (save_fregs)
{
-
/* First get the frame or stack pointer to the start of the FP register
save area. */
if (frame_pointer_needed)
@@ -2338,13 +2860,15 @@ hppa_expand_prologue()
/* Now actually save the FP registers. */
for (i = 66; i >= 48; i -= 2)
- if (regs_ever_live[i] || regs_ever_live[i + 1])
- {
- emit_move_insn (gen_rtx (MEM, DFmode,
- gen_rtx (POST_INC, DFmode, tmpreg)),
- gen_rtx (REG, DFmode, i));
- fr_saved++;
- }
+ {
+ if (regs_ever_live[i] || regs_ever_live[i + 1])
+ {
+ emit_move_insn (gen_rtx (MEM, DFmode,
+ gen_rtx (POST_INC, DFmode, tmpreg)),
+ gen_rtx (REG, DFmode, i));
+ fr_saved++;
+ }
+ }
}
/* When generating PIC code it is necessary to save/restore the
@@ -2363,7 +2887,7 @@ hppa_expand_prologue()
even be more efficient.
Avoid this if the callee saved register wasn't used (these are
- leaf functions. */
+ leaf functions). */
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM_SAVED])
emit_move_insn (gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM_SAVED),
gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM));
@@ -2398,26 +2922,14 @@ output_function_epilogue (file, size)
/* If insn is a CALL_INSN, then it must be a call to a volatile
function (otherwise there would be epilogue insns). */
if (insn && GET_CODE (insn) == CALL_INSN)
- fprintf (file, "\tnop\n");
-
- fprintf (file, "\t.EXIT\n\t.PROCEND\n");
+ fputs ("\tnop\n", file);
- /* If we have deferred plabels, then we need to switch into the data
- section and align it to a 4 byte boundary before we output the
- deferred plabels. */
- if (n_deferred_plabels)
- {
- data_section ();
- ASM_OUTPUT_ALIGN (file, 2);
- }
+ fputs ("\t.EXIT\n\t.PROCEND\n", file);
- /* Now output the deferred plabels. */
- for (i = 0; i < n_deferred_plabels; i++)
- {
- ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
- ASM_OUTPUT_INT (file, deferred_plabels[i].symbol);
- }
- n_deferred_plabels = 0;
+ /* Free up stuff we don't need anymore. */
+ if (unscaled_index_insn_codes)
+ free (unscaled_index_insn_codes);
+ max_unscaled_index_insn_codes_uid = 0;
}
void
@@ -2427,6 +2939,48 @@ hppa_expand_epilogue ()
int offset,i;
int merge_sp_adjust_with_load = 0;
+ /* Handle out of line prologues and epilogues. */
+ if (TARGET_SPACE && out_of_line_prologue_epilogue)
+ {
+ int saves = 0;
+ rtx operands[2];
+
+ /* Put the register save info into %r22. */
+ for (i = 18; i >= 3; i--)
+ if (regs_ever_live[i] && ! call_used_regs[i])
+ {
+ saves = i;
+ break;
+ }
+
+ for (i = 66; i >= 48; i -= 2)
+ if (regs_ever_live[i] || regs_ever_live[i + 1])
+ {
+ saves |= ((i/2 - 12 ) << 16);
+ break;
+ }
+
+ emit_insn (gen_blockage ());
+
+ /* Put the local_fisze into %r19. */
+ operands[0] = gen_rtx (REG, SImode, 19);
+ operands[1] = GEN_INT (local_fsize);
+ emit_move_insn (operands[0], operands[1]);
+
+ /* Put the stack size into %r21. */
+ operands[0] = gen_rtx (REG, SImode, 21);
+ operands[1] = GEN_INT (actual_fsize);
+ emit_move_insn (operands[0], operands[1]);
+
+ operands[0] = gen_rtx (REG, SImode, 22);
+ operands[1] = GEN_INT (saves);
+ emit_move_insn (operands[0], operands[1]);
+
+ /* Now call the out-of-line epilogue. */
+ emit_insn (gen_outline_epilogue_call ());
+ return;
+ }
+
/* We will use this often. */
tmpreg = gen_rtx (REG, SImode, 1);
@@ -2456,19 +3010,21 @@ hppa_expand_epilogue ()
else
{
for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)
- if (regs_ever_live[i] && ! call_used_regs[i])
- {
- /* Only for the first load.
- merge_sp_adjust_with_load holds the register load
- with which we will merge the sp adjustment. */
- if (VAL_14_BITS_P (actual_fsize + 20)
- && local_fsize == 0
- && ! merge_sp_adjust_with_load)
- merge_sp_adjust_with_load = i;
- else
- load_reg (i, offset, STACK_POINTER_REGNUM);
- offset += 4;
- }
+ {
+ if (regs_ever_live[i] && ! call_used_regs[i])
+ {
+ /* Only for the first load.
+ merge_sp_adjust_with_load holds the register load
+ with which we will merge the sp adjustment. */
+ if (VAL_14_BITS_P (actual_fsize + 20)
+ && local_fsize == 0
+ && ! merge_sp_adjust_with_load)
+ merge_sp_adjust_with_load = i;
+ else
+ load_reg (i, offset, STACK_POINTER_REGNUM);
+ offset += 4;
+ }
+ }
}
/* Align pointer properly (doubleword boundary). */
@@ -2485,12 +3041,22 @@ hppa_expand_epilogue ()
/* Actually do the restores now. */
for (i = 66; i >= 48; i -= 2)
- if (regs_ever_live[i] || regs_ever_live[i + 1])
- emit_move_insn (gen_rtx (REG, DFmode, i),
- gen_rtx (MEM, DFmode,
- gen_rtx (POST_INC, DFmode, tmpreg)));
+ {
+ if (regs_ever_live[i] || regs_ever_live[i + 1])
+ {
+ emit_move_insn (gen_rtx (REG, DFmode, i),
+ gen_rtx (MEM, DFmode,
+ gen_rtx (POST_INC, DFmode, tmpreg)));
+ }
+ }
}
+ /* Emit a blockage insn here to keep these insns from being moved to
+ an earlier spot in the epilogue, or into the main instruction stream.
+
+ This is necessary as we must not cut the stack back before all the
+ restores are finished. */
+ emit_insn (gen_blockage ());
/* No frame pointer, but we have a stack greater than 8k. We restore
%r2 very late in this case. (All other cases are restored as early
as possible.) */
@@ -2511,32 +3077,125 @@ hppa_expand_epilogue ()
load_reg (2, - 20, STACK_POINTER_REGNUM);
}
- /* Reset stack pointer (and possibly frame pointer). The stack */
- /* pointer is initially set to fp + 64 to avoid a race condition.
- ??? What race condition?!? */
+ /* Reset stack pointer (and possibly frame pointer). The stack
+ pointer is initially set to fp + 64 to avoid a race condition. */
else if (frame_pointer_needed)
{
- /* Emit a blockage insn here to keep these insns from being moved
- to the beginning of the prologue or into the main instruction
- stream, doing so avoids some very obscure problems. */
- emit_insn (gen_blockage ());
set_reg_plus_d (STACK_POINTER_REGNUM, FRAME_POINTER_REGNUM, 64);
- emit_insn (gen_pre_ldwm (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-64), frame_pointer_rtx));
+ emit_insn (gen_pre_ldwm (frame_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-64)));
}
/* If we were deferring a callee register restore, do it now. */
else if (! frame_pointer_needed && merge_sp_adjust_with_load)
- emit_insn (gen_pre_ldwm (stack_pointer_rtx,
+ emit_insn (gen_pre_ldwm (gen_rtx (REG, SImode,
+ merge_sp_adjust_with_load),
stack_pointer_rtx,
- GEN_INT (- actual_fsize),
- gen_rtx (REG, SImode,
- merge_sp_adjust_with_load)));
+ GEN_INT (- actual_fsize)));
else if (actual_fsize != 0)
set_reg_plus_d (STACK_POINTER_REGNUM,
STACK_POINTER_REGNUM,
- actual_fsize);
}
+/* Fetch the return address for the frame COUNT steps up from
+ the current frame, after the prologue. FRAMEADDR is the
+ frame pointer of the COUNT frame.
+
+ We want to ignore any export stub remnants here.
+
+ The value returned is used in two different ways:
+
+ 1. To find a function's caller.
+
+ 2. To change the return address for a function.
+
+ This function handles most instances of case 1; however, it will
+ fail if there are two levels of stubs to execute on the return
+ path. The only way I believe that can happen is if the return value
+ needs a parameter relocation, which never happens for C code.
+
+ This function handles most instances of case 2; however, it will
+ fail if we did not originally have stub code on the return path
+ but will need code on the new return path. This can happen if
+ the caller & callee are both in the main program, but the new
+ return location is in a shared library.
+
+ To handle this correctly we need to set the return pointer at
+ frame-20 to point to a return stub frame-24 to point to the
+ location we wish to return to. */
+
+rtx
+return_addr_rtx (count, frameaddr)
+ int count;
+ rtx frameaddr;
+{
+ rtx label;
+ rtx saved_rp;
+ rtx ins;
+
+ saved_rp = gen_reg_rtx (Pmode);
+
+ /* First, we start off with the normal return address pointer from
+ -20[frameaddr]. */
+
+ emit_move_insn (saved_rp, plus_constant (frameaddr, -5 * UNITS_PER_WORD));
+
+ /* Get pointer to the instruction stream. We have to mask out the
+ privilege level from the two low order bits of the return address
+ pointer here so that ins will point to the start of the first
+ instruction that would have been executed if we returned. */
+ ins = copy_to_reg (gen_rtx (AND, Pmode,
+ copy_to_reg (gen_rtx (MEM, Pmode, saved_rp)),
+ MASK_RETURN_ADDR));
+ label = gen_label_rtx ();
+
+ /* Check the instruction stream at the normal return address for the
+ export stub:
+
+ 0x4bc23fd1 | stub+8: ldw -18(sr0,sp),rp
+ 0x004010a1 | stub+12: ldsid (sr0,rp),r1
+ 0x00011820 | stub+16: mtsp r1,sr0
+ 0xe0400002 | stub+20: be,n 0(sr0,rp)
+
+ If it is an export stub, than our return address is really in
+ -24[frameaddr]. */
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, ins),
+ GEN_INT (0x4bc23fd1),
+ NE, NULL_RTX, SImode, 1, 0);
+ emit_jump_insn (gen_bne (label));
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, plus_constant (ins, 4)),
+ GEN_INT (0x004010a1),
+ NE, NULL_RTX, SImode, 1, 0);
+ emit_jump_insn (gen_bne (label));
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, plus_constant (ins, 8)),
+ GEN_INT (0x00011820),
+ NE, NULL_RTX, SImode, 1, 0);
+ emit_jump_insn (gen_bne (label));
+
+ emit_cmp_insn (gen_rtx (MEM, SImode, plus_constant (ins, 12)),
+ GEN_INT (0xe0400002),
+ NE, NULL_RTX, SImode, 1, 0);
+
+ /* If there is no export stub then just use our initial guess of
+ -20[frameaddr]. */
+
+ emit_jump_insn (gen_bne (label));
+
+ /* Here we know that our return address pointer points to an export
+ stub. We don't want to return the address of the export stub,
+ but rather the return address that leads back into user code.
+ That return address is stored at -24[frameaddr]. */
+
+ emit_move_insn (saved_rp, plus_constant (frameaddr, -6 * UNITS_PER_WORD));
+
+ emit_label (label);
+ return gen_rtx (MEM, Pmode, memory_address (Pmode, saved_rp));
+}
+
/* This is only valid once reload has completed because it depends on
knowing exactly how much (if any) frame there is and...
@@ -2870,6 +3529,10 @@ pa_adjust_insn_length (insn, length)
&& length == 4
&& ! forward_branch_p (insn))
return 4;
+ else if (GET_CODE (pat) == PARALLEL
+ && get_attr_type (insn) == TYPE_PARALLEL_BRANCH
+ && length == 4)
+ return 4;
/* Adjust dbra insn with short backwards conditional branch with
unfilled delay slot -- only for case where counter is in a
general register register. */
@@ -2883,8 +3546,7 @@ pa_adjust_insn_length (insn, length)
else
return 0;
}
- else
- return 0;
+ return 0;
}
/* Print operand X (an rtx) in assembler syntax to file FILE.
@@ -2933,25 +3595,25 @@ print_operand (file, x, code)
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case NE:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case GT:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case GE:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case GEU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
case GTU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
case LT:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case LE:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case LEU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
case LTU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
default:
abort ();
}
@@ -2960,25 +3622,25 @@ print_operand (file, x, code)
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case NE:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case GT:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case GE:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case GEU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
case GTU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
case LT:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case LE:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case LEU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
case LTU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
default:
abort ();
}
@@ -2989,17 +3651,17 @@ print_operand (file, x, code)
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "!="); break;
+ fputs ("!=", file); break;
case NE:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case GT:
- fprintf (file, "!>"); break;
+ fputs ("<=", file); break;
case GE:
- fprintf (file, "!>="); break;
+ fputs ("<", file); break;
case LT:
- fprintf (file, "!<"); break;
+ fputs (">=", file); break;
case LE:
- fprintf (file, "!<="); break;
+ fputs (">", file); break;
default:
abort ();
}
@@ -3008,25 +3670,25 @@ print_operand (file, x, code)
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case NE:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case GT:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case GE:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case GEU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
case GTU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
case LT:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case LE:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case LEU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
case LTU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
default:
abort ();
}
@@ -3035,25 +3697,25 @@ print_operand (file, x, code)
switch (GET_CODE (x))
{
case EQ:
- fprintf (file, "<>"); break;
+ fputs ("<>", file); break;
case NE:
- fprintf (file, "="); break;
+ fputs ("=", file); break;
case GT:
- fprintf (file, ">="); break;
+ fputs (">=", file); break;
case GE:
- fprintf (file, ">"); break;
+ fputs (">", file); break;
case GEU:
- fprintf (file, ">>"); break;
+ fputs (">>", file); break;
case GTU:
- fprintf (file, ">>="); break;
+ fputs (">>=", file); break;
case LT:
- fprintf (file, "<="); break;
+ fputs ("<=", file); break;
case LE:
- fprintf (file, "<"); break;
+ fputs ("<", file); break;
case LEU:
- fprintf (file, "<<"); break;
+ fputs ("<<", file); break;
case LTU:
- fprintf (file, "<<="); break;
+ fputs ("<<=", file); break;
default:
abort ();
}
@@ -3091,37 +3753,35 @@ print_operand (file, x, code)
fputs ("i", file);
return;
case 'M':
- switch (GET_CODE (XEXP (x, 0)))
- {
- case PRE_DEC:
- case PRE_INC:
- fprintf (file, "s,mb");
- break;
- case POST_DEC:
- case POST_INC:
- fprintf (file, "s,ma");
- break;
- default:
- break;
- }
- return;
case 'F':
switch (GET_CODE (XEXP (x, 0)))
{
case PRE_DEC:
case PRE_INC:
- fprintf (file, ",mb");
+ fputs ("s,mb", file);
break;
case POST_DEC:
case POST_INC:
- fprintf (file, ",ma");
+ fputs ("s,ma", file);
+ break;
+ case PLUS:
+ if (GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
+ || GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
+ fputs ("x,s", file);
+ else if (code == 'F')
+ fputs ("s", file);
break;
default:
+ if (code == 'F')
+ fputs ("s", file);
break;
}
return;
case 'G':
- output_global_address (file, x);
+ output_global_address (file, x, 0);
+ return;
+ case 'H':
+ output_global_address (file, x, 1);
return;
case 0: /* Don't do anything special */
break;
@@ -3137,10 +3797,9 @@ print_operand (file, x, code)
}
if (GET_CODE (x) == REG)
{
+ fputs (reg_names [REGNO (x)], file);
if (FP_REG_P (x) && GET_MODE_SIZE (GET_MODE (x)) <= 4 && (REGNO (x) & 1) == 0)
- fprintf (file, "%sL", reg_names [REGNO (x)]);
- else
- fprintf (file, "%s", reg_names [REGNO (x)]);
+ fputs ("L", file);
}
else if (GET_CODE (x) == MEM)
{
@@ -3157,34 +3816,21 @@ print_operand (file, x, code)
fprintf (file, "%d(0,%s)", size, reg_names [REGNO (base)]);
break;
default:
- output_address (XEXP (x, 0));
+ if (GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT)
+ fprintf (file, "%s(0,%s)",
+ reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0))],
+ reg_names [REGNO (XEXP (XEXP (x, 0), 1))]);
+ else if (GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == MULT)
+ fprintf (file, "%s(0,%s)",
+ reg_names [REGNO (XEXP (XEXP (XEXP (x, 0), 1), 0))],
+ reg_names [REGNO (XEXP (XEXP (x, 0), 0))]);
+ else
+ output_address (XEXP (x, 0));
break;
}
}
-#if 0
- /* The code here is completely wrong. It attempts to extract parts of
- a CONST_DOUBLE which is wrong since REAL_ARITHMETIC is defined, and it
- extracts the wrong indices (0 instead of 2 and 1 instead of 3) using
- the wrong macro (XINT instead of XWINT).
- Just disable it for now, since the code will never be used anyway! */
- else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
- {
- union { double d; int i[2]; } u;
- union { float f; int i; } u1;
- u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
- u1.f = u.d;
- if (code == 'f')
- fprintf (file, "0r%.9g", u1.f);
- else
- fprintf (file, "0x%x", u1.i);
- }
- else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) != VOIDmode)
- {
- union { double d; int i[2]; } u;
- u.i[0] = XINT (x, 0); u.i[1] = XINT (x, 1);
- fprintf (file, "0r%.20g", u.d);
- }
-#endif
else
output_addr_const (file, x);
}
@@ -3192,9 +3838,10 @@ print_operand (file, x, code)
/* output a SYMBOL_REF or a CONST expression involving a SYMBOL_REF. */
void
-output_global_address (file, x)
+output_global_address (file, x, round_constant)
FILE *file;
rtx x;
+ int round_constant;
{
/* Imagine (high (const (plus ...))). */
@@ -3206,7 +3853,7 @@ output_global_address (file, x)
else if (GET_CODE (x) == SYMBOL_REF && !flag_pic)
{
assemble_name (file, XSTR (x, 0));
- fprintf (file, "-$global$");
+ fputs ("-$global$", file);
}
else if (GET_CODE (x) == CONST)
{
@@ -3232,6 +3879,18 @@ output_global_address (file, x)
offset = INTVAL (XEXP (XEXP (x, 0),1));
else abort ();
+ /* How bogus. The compiler is apparently responsible for
+ rounding the constant if it uses an LR field selector.
+
+ The linker and/or assembler seem a better place since
+ they have to do this kind of thing already.
+
+ If we fail to do this, HP's optimizing linker may eliminate
+ an addil, but not update the ldw/stw/ldo instruction that
+ uses the result of the addil. */
+ if (round_constant)
+ offset = ((offset + 0x1000) & ~0x1fff);
+
if (GET_CODE (XEXP (x, 0)) == PLUS)
{
if (offset < 0)
@@ -3248,14 +3907,37 @@ output_global_address (file, x)
else abort ();
if (!read_only_operand (base) && !flag_pic)
- fprintf (file, "-$global$");
- fprintf (file, "%s", sep);
- if (offset) fprintf (file,"%d", offset);
+ fputs ("-$global$", file);
+ if (offset)
+ fprintf (file,"%s%d", sep, offset);
}
else
output_addr_const (file, x);
}
+void
+output_deferred_plabels (file)
+ FILE *file;
+{
+ int i;
+ /* If we have deferred plabels, then we need to switch into the data
+ section and align it to a 4 byte boundary before we output the
+ deferred plabels. */
+ if (n_deferred_plabels)
+ {
+ data_section ();
+ ASM_OUTPUT_ALIGN (file, 2);
+ }
+
+ /* Now output the deferred plabels. */
+ for (i = 0; i < n_deferred_plabels; i++)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (deferred_plabels[i].internal_label));
+ assemble_integer (gen_rtx (SYMBOL_REF, VOIDmode,
+ deferred_plabels[i].name), 4, 1);
+ }
+}
+
/* HP's millicode routines mean something special to the assembler.
Keep track of which ones we have used. */
@@ -3289,8 +3971,7 @@ output_mul_insn (unsignedp, insn)
rtx insn;
{
import_milli (mulI);
- return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$mulI"),
- gen_rtx (REG, SImode, 31));
+ return output_millicode_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$mulI"));
}
/* Emit the rtl for doing a division by a constant. */
@@ -3369,14 +4050,14 @@ output_div_insn (operands, unsignedp, insn)
if (unsignedp)
{
sprintf (buf, "$$divU_%d", INTVAL (operands[0]));
- return output_call (insn, gen_rtx (SYMBOL_REF, SImode, buf),
- gen_rtx (REG, SImode, 31));
+ return output_millicode_call (insn,
+ gen_rtx (SYMBOL_REF, SImode, buf));
}
else
{
sprintf (buf, "$$divI_%d", INTVAL (operands[0]));
- return output_call (insn, gen_rtx (SYMBOL_REF, SImode, buf),
- gen_rtx (REG, SImode, 31));
+ return output_millicode_call (insn,
+ gen_rtx (SYMBOL_REF, SImode, buf));
}
}
/* Divisor isn't a special constant. */
@@ -3385,14 +4066,14 @@ output_div_insn (operands, unsignedp, insn)
if (unsignedp)
{
import_milli (divU);
- return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$divU"),
- gen_rtx (REG, SImode, 31));
+ return output_millicode_call (insn,
+ gen_rtx (SYMBOL_REF, SImode, "$$divU"));
}
else
{
import_milli (divI);
- return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$divI"),
- gen_rtx (REG, SImode, 31));
+ return output_millicode_call (insn,
+ gen_rtx (SYMBOL_REF, SImode, "$$divI"));
}
}
}
@@ -3407,14 +4088,14 @@ output_mod_insn (unsignedp, insn)
if (unsignedp)
{
import_milli (remU);
- return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$remU"),
- gen_rtx (REG, SImode, 31));
+ return output_millicode_call (insn,
+ gen_rtx (SYMBOL_REF, SImode, "$$remU"));
}
else
{
import_milli (remI);
- return output_call (insn, gen_rtx (SYMBOL_REF, SImode, "$$remI"),
- gen_rtx (REG, SImode, 31));
+ return output_millicode_call (insn,
+ gen_rtx (SYMBOL_REF, SImode, "$$remI"));
}
}
@@ -3435,8 +4116,8 @@ output_arg_descriptor (call_insn)
if using the portable runtime calling conventions. */
if (TARGET_PORTABLE_RUNTIME)
{
- fprintf (asm_out_file,
- "\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n");
+ fputs ("\t.CALL ARGW0=NO,ARGW1=NO,ARGW2=NO,ARGW3=NO,RETVAL=NO\n",
+ asm_out_file);
return;
}
@@ -3488,8 +4169,15 @@ output_arg_descriptor (call_insn)
fputc ('\n', asm_out_file);
}
-/* Memory loads/stores to/from the shift need to go through
- the general registers. */
+/* Return the class of any secondary reload register that is needed to
+ move IN into a register in class CLASS using mode MODE.
+
+ Profiling has showed this routine and its descendants account for
+ a significant amount of compile time (~7%). So it has been
+ optimized to reduce redundant computations and eliminate useless
+ function calls.
+
+ It might be worthwhile to try and make this a leaf function too. */
enum reg_class
secondary_reload_class (class, mode, in)
@@ -3497,7 +4185,7 @@ secondary_reload_class (class, mode, in)
enum machine_mode mode;
rtx in;
{
- int regno = true_regnum (in);
+ int regno, is_symbolic;
/* Trying to load a constant into a FP register during PIC code
generation will require %r1 as a scratch register. */
@@ -3507,6 +4195,29 @@ secondary_reload_class (class, mode, in)
&& (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
return R1_REGS;
+ /* Profiling showed the PA port spends about 1.3% of its compilation
+ time in true_regnum from calls inside secondary_reload_class. */
+
+ if (GET_CODE (in) == REG)
+ {
+ regno = REGNO (in);
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ regno = true_regnum (in);
+ }
+ else if (GET_CODE (in) == SUBREG)
+ regno = true_regnum (in);
+ else
+ regno = -1;
+
+ /* If we have something like (mem (mem (...)), we can safely assume the
+ inner MEM will end up in a general register after reloading, so there's
+ no need for a secondary reload. */
+ if (GET_CODE (in) == MEM
+ && GET_CODE (XEXP (in, 0)) == MEM)
+ return NO_REGS;
+
+ /* Handle out of range displacement for integer mode loads/stores of
+ FP registers. */
if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
&& GET_MODE_CLASS (mode) == MODE_INT
&& FP_REG_CLASS_P (class))
@@ -3516,23 +4227,39 @@ secondary_reload_class (class, mode, in)
if (GET_CODE (in) == HIGH)
in = XEXP (in, 0);
+ /* Profiling has showed GCC spends about 2.6% of its compilation
+ time in symbolic_operand from calls inside secondary_reload_class.
+
+ We use an inline copy and only compute its return value once to avoid
+ useless work. */
+ switch (GET_CODE (in))
+ {
+ rtx tmp;
+
+ case SYMBOL_REF:
+ case LABEL_REF:
+ is_symbolic = 1;
+ break;
+ case CONST:
+ tmp = XEXP (in, 0);
+ is_symbolic = ((GET_CODE (XEXP (tmp, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (tmp, 1)) == CONST_INT);
+ break;
+
+ default:
+ is_symbolic = 0;
+ break;
+ }
+
if (!flag_pic
- && symbolic_operand (in, VOIDmode)
+ && is_symbolic
&& read_only_operand (in))
return NO_REGS;
- if (class != R1_REGS && symbolic_operand (in, VOIDmode))
+ if (class != R1_REGS && is_symbolic)
return R1_REGS;
- if (GET_CODE (in) == SUBREG)
- in = SUBREG_REG (in);
-
- if (FP_REG_CLASS_P (class)
- && GET_CODE (in) == MEM
- && !memory_address_p (DFmode, XEXP (in, 0))
- && memory_address_p (SImode, XEXP (in, 0)))
- return GENERAL_REGS;
-
return NO_REGS;
}
@@ -3571,7 +4298,7 @@ struct rtx_def *
hppa_builtin_saveregs (arglist)
tree arglist;
{
- rtx offset;
+ rtx offset, dest;
tree fntype = TREE_TYPE (current_function_decl);
int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
@@ -3584,11 +4311,28 @@ hppa_builtin_saveregs (arglist)
offset = current_function_arg_offset_rtx;
/* Store general registers on the stack. */
- move_block_from_reg (23,
- gen_rtx (MEM, BLKmode,
- plus_constant
- (current_function_internal_arg_pointer, -16)),
- 4, 4 * UNITS_PER_WORD);
+ dest = gen_rtx (MEM, BLKmode,
+ plus_constant (current_function_internal_arg_pointer, -16));
+ move_block_from_reg (23, dest, 4, 4 * UNITS_PER_WORD);
+
+ /* move_block_from_reg will emit code to store the argument registers
+ individually as scalar stores.
+
+ However, other insns may later load from the same addresses for
+ a structure load (passing a struct to a varargs routine).
+
+ The alias code assumes that such aliasing can never happen, so we
+ have to keep memory referencing insns from moving up beyond the
+ last argument register store. So we emit a blockage insn here. */
+ emit_insn (gen_blockage ());
+
+ if (flag_check_memory_usage)
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ dest, ptr_mode,
+ GEN_INT (4 * UNITS_PER_WORD), TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+
return copy_to_reg (expand_binop (Pmode, add_optab,
current_function_internal_arg_pointer,
offset, 0, 0, OPTAB_LIB_WIDEN));
@@ -3683,7 +4427,7 @@ output_cbranch (operands, nullify, length, negated, insn)
&& ! forward_branch_p (insn)
&& insn_addresses
&& VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))]
- - insn_addresses[INSN_UID (insn)]))
+ - insn_addresses[INSN_UID (insn)] - 8))
{
strcpy (buf, "com%I2b,");
if (negated)
@@ -3705,6 +4449,68 @@ output_cbranch (operands, nullify, length, negated, insn)
}
break;
+ case 20:
+ /* Very long branch. Right now we only handle these when not
+ optimizing. See "jump" pattern in pa.md for details. */
+ if (optimize)
+ abort ();
+
+ /* Create a reversed conditional branch which branches around
+ the following insns. */
+ if (negated)
+ strcpy (buf, "com%I2b,%S3,n %2,%1,.+20");
+ else
+ strcpy (buf, "com%I2b,%B3,n %2,%1,.+20");
+ output_asm_insn (buf, operands);
+
+ /* Output an insn to save %r1. */
+ output_asm_insn ("stw %%r1,-16(%%r30)", operands);
+
+ /* Now output a very long branch to the original target. */
+ output_asm_insn ("ldil L'%l0,%%r1\n\tbe R'%l0(%%sr4,%%r1)", operands);
+
+ /* Now restore the value of %r1 in the delay slot. We're not
+ optimizing so we know nothing else can be in the delay slot. */
+ return "ldw -16(%%r30),%%r1";
+
+ case 28:
+ /* Very long branch when generating PIC code. Right now we only
+ handle these when not optimizing. See "jump" pattern in pa.md
+ for details. */
+ if (optimize)
+ abort ();
+
+ /* Create a reversed conditional branch which branches around
+ the following insns. */
+ if (negated)
+ strcpy (buf, "com%I2b,%S3,n %2,%1,.+28");
+ else
+ strcpy (buf, "com%I2b,%B3,n %2,%1,.+28");
+ output_asm_insn (buf, operands);
+
+ /* Output an insn to save %r1. */
+ output_asm_insn ("stw %%r1,-16(%%r30)", operands);
+
+ /* Now output a very long PIC branch to the original target. */
+ {
+ rtx xoperands[5];
+
+ xoperands[0] = operands[0];
+ xoperands[1] = operands[1];
+ xoperands[2] = operands[2];
+ xoperands[3] = operands[3];
+ xoperands[4] = gen_label_rtx ();
+
+ output_asm_insn ("bl .+8,%%r1\n\taddil L'%l0-%l4,%%r1", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (xoperands[4]));
+ output_asm_insn ("ldo R'%l0-%l4(%%r1),%%r1\n\tbv 0(%%r1)", xoperands);
+ }
+
+ /* Now restore the value of %r1 in the delay slot. We're not
+ optimizing so we know nothing else can be in the delay slot. */
+ return "ldw -16(%%r30),%%r1";
+
default:
abort();
}
@@ -3810,7 +4616,7 @@ output_bb (operands, nullify, length, negated, insn, which)
&& ! forward_branch_p (insn)
&& insn_addresses
&& VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))]
- - insn_addresses[INSN_UID (insn)]))
+ - insn_addresses[INSN_UID (insn)] - 8))
{
strcpy (buf, "bb,");
if ((which == 0 && negated)
@@ -3848,6 +4654,144 @@ output_bb (operands, nullify, length, negated, insn, which)
return buf;
}
+/* This routine handles all the branch-on-variable-bit conditional branch
+ sequences we might need to generate. It handles nullification of delay
+ slots, varying length branches, negated branches and all combinations
+ of the above. it returns the appropriate output template to emit the
+ branch. */
+
+char *
+output_bvb (operands, nullify, length, negated, insn, which)
+ rtx *operands;
+ int nullify, length, negated;
+ rtx insn;
+ int which;
+{
+ static char buf[100];
+ int useskip = 0;
+
+ /* A conditional branch to the following instruction (eg the delay slot) is
+ asking for a disaster. I do not think this can happen as this pattern
+ is only used when optimizing; jump optimization should eliminate the
+ jump. But be prepared just in case. */
+
+ if (next_active_insn (JUMP_LABEL (insn)) == next_active_insn (insn))
+ return "";
+
+ /* If this is a long branch with its delay slot unfilled, set `nullify'
+ as it can nullify the delay slot and save a nop. */
+ if (length == 8 && dbr_sequence_length () == 0)
+ nullify = 1;
+
+ /* If this is a short forward conditional branch which did not get
+ its delay slot filled, the delay slot can still be nullified. */
+ if (! nullify && length == 4 && dbr_sequence_length () == 0)
+ nullify = forward_branch_p (insn);
+
+ /* A forward branch over a single nullified insn can be done with a
+ extrs instruction. This avoids a single cycle penalty due to
+ mis-predicted branch if we fall through (branch not taken). */
+
+ if (length == 4
+ && next_real_insn (insn) != 0
+ && get_attr_length (next_real_insn (insn)) == 4
+ && JUMP_LABEL (insn) == next_nonnote_insn (next_real_insn (insn))
+ && nullify)
+ useskip = 1;
+
+ switch (length)
+ {
+
+ /* All short conditional branches except backwards with an unfilled
+ delay slot. */
+ case 4:
+ if (useskip)
+ strcpy (buf, "vextrs,");
+ else
+ strcpy (buf, "bvb,");
+ if ((which == 0 && negated)
+ || (which == 1 && ! negated))
+ strcat (buf, ">=");
+ else
+ strcat (buf, "<");
+ if (useskip)
+ strcat (buf, " %0,1,0");
+ else if (nullify && negated)
+ strcat (buf, ",n %0,%3");
+ else if (nullify && ! negated)
+ strcat (buf, ",n %0,%2");
+ else if (! nullify && negated)
+ strcat (buf, "%0,%3");
+ else if (! nullify && ! negated)
+ strcat (buf, " %0,%2");
+ break;
+
+ /* All long conditionals. Note an short backward branch with an
+ unfilled delay slot is treated just like a long backward branch
+ with an unfilled delay slot. */
+ case 8:
+ /* Handle weird backwards branch with a filled delay slot
+ with is nullified. */
+ if (dbr_sequence_length () != 0
+ && ! forward_branch_p (insn)
+ && nullify)
+ {
+ strcpy (buf, "bvb,");
+ if ((which == 0 && negated)
+ || (which == 1 && ! negated))
+ strcat (buf, "<");
+ else
+ strcat (buf, ">=");
+ if (negated)
+ strcat (buf, ",n %0,.+12\n\tbl %3,0");
+ else
+ strcat (buf, ",n %0,.+12\n\tbl %2,0");
+ }
+ /* Handle short backwards branch with an unfilled delay slot.
+ Using a bb;nop rather than extrs;bl saves 1 cycle for both
+ taken and untaken branches. */
+ else if (dbr_sequence_length () == 0
+ && ! forward_branch_p (insn)
+ && insn_addresses
+ && VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))]
+ - insn_addresses[INSN_UID (insn)] - 8))
+ {
+ strcpy (buf, "bvb,");
+ if ((which == 0 && negated)
+ || (which == 1 && ! negated))
+ strcat (buf, ">=");
+ else
+ strcat (buf, "<");
+ if (negated)
+ strcat (buf, " %0,%3%#");
+ else
+ strcat (buf, " %0,%2%#");
+ }
+ else
+ {
+ strcpy (buf, "vextrs,");
+ if ((which == 0 && negated)
+ || (which == 1 && ! negated))
+ strcat (buf, "<");
+ else
+ strcat (buf, ">=");
+ if (nullify && negated)
+ strcat (buf, " %0,1,0\n\tbl,n %3,0");
+ else if (nullify && ! negated)
+ strcat (buf, " %0,1,0\n\tbl,n %2,0");
+ else if (negated)
+ strcat (buf, " %0,1,0\n\tbl %3,0");
+ else
+ strcat (buf, " %0,1,0\n\tbl %2,0");
+ }
+ break;
+
+ default:
+ abort();
+ }
+ return buf;
+}
+
/* Return the output template for emitting a dbra type insn.
Note it may perform some output operations on its own before
@@ -3915,7 +4859,7 @@ output_dbra (operands, insn, which_alternative)
&& ! forward_branch_p (insn)
&& insn_addresses
&& VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))]
- - insn_addresses[INSN_UID (insn)]))
+ - insn_addresses[INSN_UID (insn)] - 8))
return "addib,%C2 %1,%0,%3%#";
/* Handle normal cases. */
@@ -3977,8 +4921,10 @@ output_movb (operands, insn, which_alternative, reverse_comparison)
output_asm_insn ("stw %1,-16(0,%%r30)",operands);
return "fldws -16(0,%%r30),%0";
}
- else
+ else if (which_alternative == 2)
return "stw %1,%0";
+ else
+ return "mtsar %r1";
}
/* Support the second variant. */
@@ -4021,7 +4967,7 @@ output_movb (operands, insn, which_alternative, reverse_comparison)
&& ! forward_branch_p (insn)
&& insn_addresses
&& VAL_14_BITS_P (insn_addresses[INSN_UID (JUMP_LABEL (insn))]
- - insn_addresses[INSN_UID (insn)]))
+ - insn_addresses[INSN_UID (insn)] - 8))
return "movb,%C2 %1,%0,%3%#";
/* Handle normal cases. */
if (nullify)
@@ -4045,7 +4991,7 @@ output_movb (operands, insn, which_alternative, reverse_comparison)
return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tfldws -16(0,%%r30),%0";
}
/* Deal with gross reload from memory case. */
- else
+ else if (which_alternative == 2)
{
/* Reload loop counter from memory, the store back to memory
happens in the branch's delay slot. */
@@ -4054,44 +5000,191 @@ output_movb (operands, insn, which_alternative, reverse_comparison)
else
return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tstw %1,%0";
}
+ /* Handle SAR as a destination. */
+ else
+ {
+ if (get_attr_length (insn) == 8)
+ return "comb,%S2 0,%1,%3\n\tmtsar %r1";
+ else
+ return "comclr,%B2 0,%1,0\n\tbl %3,0\n\tmtsar %r1";
+ }
}
-/* INSN is either a function call or a millicode call. It may have an
- unconditional jump in its delay slot.
-
- CALL_DEST is the routine we are calling.
+/* INSN is a millicode call. It may have an unconditional jump in its delay
+ slot.
- RETURN_POINTER is the register which will hold the return address.
- %r2 for most calls, %r31 for millicode calls.
-
- When TARGET_MILLICODE_LONG_CALLS is true, then we have to assume
- that two instruction sequences must be used to reach the millicode
- routines (including dyncall!). */
+ CALL_DEST is the routine we are calling. */
char *
-output_call (insn, call_dest, return_pointer)
+output_millicode_call (insn, call_dest)
rtx insn;
rtx call_dest;
- rtx return_pointer;
-
{
int distance;
rtx xoperands[4];
rtx seq_insn;
- /* Handle long millicode calls for mod, div, and mul. */
- if (TARGET_PORTABLE_RUNTIME
- || (TARGET_MILLICODE_LONG_CALLS && REGNO (return_pointer) == 31))
+ /* Handle common case -- empty delay slot or no jump in the delay slot,
+ and we're sure that the branch will reach the beginning of the $CODE$
+ subspace. */
+ if ((dbr_sequence_length () == 0
+ && (get_attr_length (insn) == 8 || get_attr_length (insn) == 28))
+ || (dbr_sequence_length () != 0
+ && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
+ && get_attr_length (insn) == 4))
{
xoperands[0] = call_dest;
- xoperands[1] = return_pointer;
- output_asm_insn ("ldil L%%%0,%%r29", xoperands);
- output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands);
- output_asm_insn ("blr 0,%r1\n\tbv,n 0(%%r29)\n\tnop", xoperands);
+ output_asm_insn ("bl %0,%%r31%#", xoperands);
return "";
}
+ /* This call may not reach the beginning of the $CODE$ subspace. */
+ if (get_attr_length (insn) > 4)
+ {
+ int delay_insn_deleted = 0;
+ rtx xoperands[2];
+ rtx link;
+
+ /* We need to emit an inline long-call branch. */
+ if (dbr_sequence_length () != 0
+ && GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
+ {
+ /* A non-jump insn in the delay slot. By definition we can
+ emit this insn before the call. */
+ final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0);
+
+ /* Now delete the delay insn. */
+ PUT_CODE (NEXT_INSN (insn), NOTE);
+ NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+ delay_insn_deleted = 1;
+ }
+
+ /* If we're allowed to use be/ble instructions, then this is the
+ best sequence to use for a long millicode call. */
+ if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS
+ || ! (flag_pic || TARGET_PORTABLE_RUNTIME))
+ {
+ xoperands[0] = call_dest;
+ output_asm_insn ("ldil L%%%0,%%r31", xoperands);
+ output_asm_insn ("ble R%%%0(%%sr4,%%r31)", xoperands);
+ output_asm_insn ("nop", xoperands);
+ }
+ /* Pure portable runtime doesn't allow be/ble; we also don't have
+ PIC support int he assembler/linker, so this sequence is needed. */
+ else if (TARGET_PORTABLE_RUNTIME)
+ {
+ xoperands[0] = call_dest;
+ /* Get the address of our target into %r29. */
+ output_asm_insn ("ldil L%%%0,%%r29", xoperands);
+ output_asm_insn ("ldo R%%%0(%%r29),%%r29", xoperands);
+
+ /* Get our return address into %r31. */
+ output_asm_insn ("blr 0,%%r31", xoperands);
+
+ /* Jump to our target address in %r29. */
+ output_asm_insn ("bv,n 0(%%r29)", xoperands);
+
+ /* Empty delay slot. Note this insn gets fetched twice and
+ executed once. To be safe we use a nop. */
+ output_asm_insn ("nop", xoperands);
+ return "";
+ }
+ /* PIC long millicode call sequence. */
+ else
+ {
+ xoperands[0] = call_dest;
+ xoperands[1] = gen_label_rtx ();
+ /* Get our address + 8 into %r1. */
+ output_asm_insn ("bl .+8,%%r1", xoperands);
+
+ /* Add %r1 to the offset of our target from the next insn. */
+ output_asm_insn ("addil L%%%0-%1,%%r1", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (xoperands[1]));
+ output_asm_insn ("ldo R%%%0-%1(%%r1),%%r1", xoperands);
+
+ /* Get the return address into %r31. */
+ output_asm_insn ("blr 0,%%r31", xoperands);
+
+ /* Branch to our target which is in %r1. */
+ output_asm_insn ("bv,n 0(%%r1)", xoperands);
+
+ /* Empty delay slot. Note this insn gets fetched twice and
+ executed once. To be safe we use a nop. */
+ output_asm_insn ("nop", xoperands);
+ }
+
+ /* If we had a jump in the call's delay slot, output it now. */
+ if (dbr_sequence_length () != 0
+ && !delay_insn_deleted)
+ {
+ xoperands[0] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
+ output_asm_insn ("b,n %0", xoperands);
+
+ /* Now delete the delay insn. */
+ PUT_CODE (NEXT_INSN (insn), NOTE);
+ NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+ }
+ return "";
+ }
+
+ /* This call has an unconditional jump in its delay slot and the
+ call is known to reach its target or the beginning of the current
+ subspace. */
+
+ /* Use the containing sequence insn's address. */
+ seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
+
+ distance = insn_addresses[INSN_UID (JUMP_LABEL (NEXT_INSN (insn)))]
+ - insn_addresses[INSN_UID (seq_insn)] - 8;
+
+ /* If the branch was too far away, emit a normal call followed
+ by a nop, followed by the unconditional branch.
+
+ If the branch is close, then adjust %r2 from within the
+ call's delay slot. */
+
+ xoperands[0] = call_dest;
+ xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
+ if (! VAL_14_BITS_P (distance))
+ output_asm_insn ("bl %0,%%r31\n\tnop\n\tbl,n %1,%%r0", xoperands);
+ else
+ {
+ xoperands[3] = gen_label_rtx ();
+ output_asm_insn ("\n\tbl %0,%%r31\n\tldo %1-%3(%%r31),%%r31", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (xoperands[3]));
+ }
+
+ /* Delete the jump. */
+ PUT_CODE (NEXT_INSN (insn), NOTE);
+ NOTE_LINE_NUMBER (NEXT_INSN (insn)) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (NEXT_INSN (insn)) = 0;
+ return "";
+}
+
+extern struct obstack permanent_obstack;
+extern struct obstack *saveable_obstack;
+extern struct obstack *rtl_obstack;
+extern struct obstack *current_obstack;
+
+/* INSN is either a function call. It may have an unconditional jump
+ in its delay slot.
+
+ CALL_DEST is the routine we are calling. */
+
+char *
+output_call (insn, call_dest)
+ rtx insn;
+ rtx call_dest;
+{
+ int distance;
+ rtx xoperands[4];
+ rtx seq_insn;
+
/* Handle common case -- empty delay slot or no jump in the delay slot,
and we're sure that the branch will reach the beginning of the $CODE$
subspace. */
@@ -4102,8 +5195,7 @@ output_call (insn, call_dest, return_pointer)
&& get_attr_length (insn) == 4))
{
xoperands[0] = call_dest;
- xoperands[1] = return_pointer;
- output_asm_insn ("bl %0,%r1%#", xoperands);
+ output_asm_insn ("bl %0,%%r2%#", xoperands);
return "";
}
@@ -4119,13 +5211,14 @@ output_call (insn, call_dest, return_pointer)
function call well after the parameters have been set up, we
need to make sure any FP args appear in both the integer
and FP registers. Also, we need move any delay slot insn
- out of the delay slot -- Yuk! */
+ out of the delay slot. And finally, we can't rely on the linker
+ being able to fix the call to $$dyncall! -- Yuk!. */
if (dbr_sequence_length () != 0
&& GET_CODE (NEXT_INSN (insn)) != JUMP_INSN)
{
/* A non-jump insn in the delay slot. By definition we can
- emit this insn before the call (and in fact before argument
- relocating. */
+ emit this insn before the call (and in fact before argument
+ relocating. */
final_scan_insn (NEXT_INSN (insn), asm_out_file, optimize, 0, 0);
/* Now delete the delay insn. */
@@ -4167,51 +5260,110 @@ output_call (insn, call_dest, return_pointer)
output_asm_insn ("ldw -12(%%sr0,%%r30),%R1", xoperands);
output_asm_insn ("ldw -16(%%sr0,%%r30),%1", xoperands);
}
-
}
}
- if (flag_pic)
+ /* Don't have to worry about TARGET_PORTABLE_RUNTIME here since
+ we don't have any direct calls in that case. */
{
+ int i;
+ char *name = XSTR (call_dest, 0);
+
+ /* See if we have already put this function on the list
+ of deferred plabels. This list is generally small,
+ so a liner search is not too ugly. If it proves too
+ slow replace it with something faster. */
+ for (i = 0; i < n_deferred_plabels; i++)
+ if (strcmp (name, deferred_plabels[i].name) == 0)
+ break;
+
+ /* If the deferred plabel list is empty, or this entry was
+ not found on the list, create a new entry on the list. */
+ if (deferred_plabels == NULL || i == n_deferred_plabels)
+ {
+ struct obstack *ambient_obstack = current_obstack;
+ struct obstack *ambient_rtl_obstack = rtl_obstack;
+ char *real_name;
+
+ /* Any RTL we create here needs to live until the end of
+ the compilation unit and therefore must live on the
+ permanent obstack. */
+ current_obstack = &permanent_obstack;
+ rtl_obstack = &permanent_obstack;
+
+ if (deferred_plabels == 0)
+ deferred_plabels = (struct deferred_plabel *)
+ xmalloc (1 * sizeof (struct deferred_plabel));
+ else
+ deferred_plabels = (struct deferred_plabel *)
+ xrealloc (deferred_plabels,
+ ((n_deferred_plabels + 1)
+ * sizeof (struct deferred_plabel)));
+
+ i = n_deferred_plabels++;
+ deferred_plabels[i].internal_label = gen_label_rtx ();
+ deferred_plabels[i].name = obstack_alloc (&permanent_obstack,
+ strlen (name) + 1);
+ strcpy (deferred_plabels[i].name, name);
+
+ /* Switch back to normal obstack allocation. */
+ current_obstack = ambient_obstack;
+ rtl_obstack = ambient_rtl_obstack;
+
+ /* Gross. We have just implicitly taken the address of this
+ function, mark it as such. */
+ STRIP_NAME_ENCODING (real_name, name);
+ TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
+ }
+
/* We have to load the address of the function using a procedure
- label (plabel). The LP and RP relocs don't work reliably for PIC,
- so we make a plain 32 bit plabel in the data segment instead. We
- have to defer outputting it of course... Not pretty. */
-
- xoperands[0] = gen_label_rtx ();
- output_asm_insn ("addil LT%%%0,%%r19\n\tldw RT%%%0(%%r1),%%r22",
- xoperands);
- output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
-
- if (deferred_plabels == 0)
- deferred_plabels = (struct defer_plab *)
- xmalloc (1 * sizeof (struct defer_plab));
+ label (plabel). Inline plabels can lose for PIC and other
+ cases, so avoid them by creating a 32bit plabel in the data
+ segment. */
+ if (flag_pic)
+ {
+ xoperands[0] = deferred_plabels[i].internal_label;
+ xoperands[1] = gen_label_rtx ();
+
+ output_asm_insn ("addil LT%%%0,%%r19", xoperands);
+ output_asm_insn ("ldw RT%%%0(%%r1),%%r22", xoperands);
+ output_asm_insn ("ldw 0(0,%%r22),%%r22", xoperands);
+
+ /* Get our address + 8 into %r1. */
+ output_asm_insn ("bl .+8,%%r1", xoperands);
+
+ /* Add %r1 to the offset of dyncall from the next insn. */
+ output_asm_insn ("addil L%%$$dyncall-%1,%%r1", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (xoperands[1]));
+ output_asm_insn ("ldo R%%$$dyncall-%1(%%r1),%%r1", xoperands);
+
+ /* Get the return address into %r31. */
+ output_asm_insn ("blr 0,%%r31", xoperands);
+
+ /* Branch to our target which is in %r1. */
+ output_asm_insn ("bv 0(%%r1)", xoperands);
+
+ /* Copy the return address into %r2 also. */
+ output_asm_insn ("copy %%r31,%%r2", xoperands);
+ }
else
- deferred_plabels = (struct defer_plab *)
- xrealloc (deferred_plabels,
- (n_deferred_plabels + 1) * sizeof (struct defer_plab));
- deferred_plabels[n_deferred_plabels].internal_label = xoperands[0];
- deferred_plabels[n_deferred_plabels].symbol = call_dest;
- n_deferred_plabels++;
- }
- else
- {
- /* Now emit the inline long-call. */
- xoperands[0] = call_dest;
- output_asm_insn ("ldil LP%%%0,%%r22\n\tldo RP%%%0(%%r22),%%r22",
- xoperands);
- }
+ {
+ xoperands[0] = deferred_plabels[i].internal_label;
- /* If TARGET_MILLICODE_LONG_CALLS, then we must use a long-call sequence
- to call dyncall! */
- if (TARGET_MILLICODE_LONG_CALLS)
- {
- output_asm_insn ("ldil L%%$$dyncall,%%r31", xoperands);
- output_asm_insn ("ldo R%%$$dyncall(%%r31),%%r31", xoperands);
- output_asm_insn ("blr 0,%%r2\n\tbv,n 0(%%r31)\n\tnop", xoperands);
+ /* Get the address of our target into %r22. */
+ output_asm_insn ("addil LR%%%0-$global$,%%r27", xoperands);
+ output_asm_insn ("ldw RR%%%0-$global$(%%r1),%%r22", xoperands);
+
+ /* Get the high part of the address of $dyncall into %r2, then
+ add in the low part in the branch instruction. */
+ output_asm_insn ("ldil L%%$$dyncall,%%r2", xoperands);
+ output_asm_insn ("ble R%%$$dyncall(%%sr4,%%r2)", xoperands);
+
+ /* Copy the return pointer into both %r31 and %r2. */
+ output_asm_insn ("copy %%r31,%%r2", xoperands);
+ }
}
- else
- output_asm_insn ("bl $$dyncall,%%r31\n\tcopy %%r31,%%r2", xoperands);
/* If we had a jump in the call's delay slot, output it now. */
if (dbr_sequence_length () != 0
@@ -4228,7 +5380,9 @@ output_call (insn, call_dest, return_pointer)
return "";
}
- /* This call has an unconditional jump in its delay slot. */
+ /* This call has an unconditional jump in its delay slot and the
+ call is known to reach its target or the beginning of the current
+ subspace. */
/* Use the containing sequence insn's address. */
seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
@@ -4244,13 +5398,12 @@ output_call (insn, call_dest, return_pointer)
xoperands[0] = call_dest;
xoperands[1] = XEXP (PATTERN (NEXT_INSN (insn)), 1);
- xoperands[2] = return_pointer;
if (! VAL_14_BITS_P (distance))
- output_asm_insn ("bl %0,%r2\n\tnop\n\tbl,n %1,%%r0", xoperands);
+ output_asm_insn ("bl %0,%%r2\n\tnop\n\tbl,n %1,%%r0", xoperands);
else
{
xoperands[3] = gen_label_rtx ();
- output_asm_insn ("\n\tbl %0,%r2\n\tldo %1-%3(%r2),%r2", xoperands);
+ output_asm_insn ("\n\tbl %0,%%r2\n\tldo %1-%3(%%r2),%%r2", xoperands);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
CODE_LABEL_NUMBER (xoperands[3]));
}
@@ -4262,9 +5415,6 @@ output_call (insn, call_dest, return_pointer)
return "";
}
-extern struct obstack permanent_obstack;
-extern struct obstack *saveable_obstack;
-
/* In HPUX 8.0's shared library scheme, special relocations are needed
for function labels if they might be passed to a function
in a shared library (because shared libraries don't live in code
@@ -4326,6 +5476,10 @@ fmpyaddoperands (operands)
{
enum machine_mode mode = GET_MODE (operands[0]);
+ /* Must be a floating point mode. */
+ if (mode != SFmode && mode != DFmode)
+ return 0;
+
/* All modes must be the same. */
if (! (mode == GET_MODE (operands[1])
&& mode == GET_MODE (operands[2])
@@ -4334,9 +5488,12 @@ fmpyaddoperands (operands)
&& mode == GET_MODE (operands[5])))
return 0;
- /* Both DFmode and SFmode should work. But using SFmode makes the
- assembler complain. Just turn it off for now. */
- if (mode != DFmode)
+ /* All operands must be registers. */
+ if (! (GET_CODE (operands[1]) == REG
+ && GET_CODE (operands[2]) == REG
+ && GET_CODE (operands[3]) == REG
+ && GET_CODE (operands[4]) == REG
+ && GET_CODE (operands[5]) == REG))
return 0;
/* Only 2 real operands to the addition. One of the input operands must
@@ -4356,6 +5513,16 @@ fmpyaddoperands (operands)
|| rtx_equal_p (operands[5], operands[0]))
return 0;
+ /* SFmode limits the registers to the upper 32 of the 32bit FP regs. */
+ if (mode == SFmode
+ && (REGNO (operands[0]) < 57
+ || REGNO (operands[1]) < 57
+ || REGNO (operands[2]) < 57
+ || REGNO (operands[3]) < 57
+ || REGNO (operands[4]) < 57
+ || REGNO (operands[5]) < 57))
+ return 0;
+
/* Passed. Operands are suitable for fmpyadd. */
return 1;
}
@@ -4368,6 +5535,10 @@ fmpysuboperands (operands)
{
enum machine_mode mode = GET_MODE (operands[0]);
+ /* Must be a floating point mode. */
+ if (mode != SFmode && mode != DFmode)
+ return 0;
+
/* All modes must be the same. */
if (! (mode == GET_MODE (operands[1])
&& mode == GET_MODE (operands[2])
@@ -4376,9 +5547,12 @@ fmpysuboperands (operands)
&& mode == GET_MODE (operands[5])))
return 0;
- /* Both DFmode and SFmode should work. But using SFmode makes the
- assembler complain. Just turn it off for now. */
- if (mode != DFmode)
+ /* All operands must be registers. */
+ if (! (GET_CODE (operands[1]) == REG
+ && GET_CODE (operands[2]) == REG
+ && GET_CODE (operands[3]) == REG
+ && GET_CODE (operands[4]) == REG
+ && GET_CODE (operands[5]) == REG))
return 0;
/* Only 2 real operands to the subtraction. Subtraction is not a commutative
@@ -4396,6 +5570,16 @@ fmpysuboperands (operands)
|| rtx_equal_p (operands[3], operands[2]))
return 0;
+ /* SFmode limits the registers to the upper 32 of the 32bit FP regs. */
+ if (mode == SFmode
+ && (REGNO (operands[0]) < 57
+ || REGNO (operands[1]) < 57
+ || REGNO (operands[2]) < 57
+ || REGNO (operands[3]) < 57
+ || REGNO (operands[4]) < 57
+ || REGNO (operands[5]) < 57))
+ return 0;
+
/* Passed. Operands are suitable for fmpysub. */
return 1;
}
@@ -4431,6 +5615,50 @@ shadd_operand (op, mode)
return (GET_CODE (op) == CONST_INT && shadd_constant_p (INTVAL (op)));
}
+/* Return 1 if OP is valid as a base register in a reg + reg address. */
+
+int
+basereg_operand (op, mode)
+ rtx op;
+ enum machine_mode mode;
+{
+ /* cse will create some unscaled indexed addresses, however; it
+ generally isn't a win on the PA, so avoid creating unscaled
+ indexed addresses until after cse is finished. */
+ if (!cse_not_expected)
+ return 0;
+
+ /* Once reload has started everything is considered valid. Reload should
+ only create indexed addresses using the stack/frame pointer, and any
+ others were checked for validity when created by the combine pass.
+
+ Also allow any register when TARGET_NO_SPACE_REGS is in effect since
+ we don't have to worry about the braindamaged implicit space register
+ selection using the basereg only (rather than effective address)
+ screwing us over. */
+ if (TARGET_NO_SPACE_REGS || reload_in_progress || reload_completed)
+ return (GET_CODE (op) == REG);
+
+ /* Stack is always OK for indexing. */
+ if (op == stack_pointer_rtx)
+ return 1;
+
+ /* While it's always safe to index off the frame pointer, it's not
+ always profitable, particularly when the frame pointer is being
+ eliminated. */
+ if (! flag_omit_frame_pointer && op == frame_pointer_rtx)
+ return 1;
+
+ /* The only other valid OPs are pseudo registers with
+ REGNO_POINTER_FLAG set. */
+ if (GET_CODE (op) != REG
+ || REGNO (op) < FIRST_PSEUDO_REGISTER
+ || ! register_operand (op, mode))
+ return 0;
+
+ return REGNO_POINTER_FLAG (REGNO (op));
+}
+
/* Return 1 if this operand is anything other than a hard register. */
int
@@ -4502,6 +5730,188 @@ jump_in_call_delay (insn)
return 0;
}
+/* Output an unconditional move and branch insn. */
+
+char *
+output_parallel_movb (operands, length)
+ rtx *operands;
+ int length;
+{
+ /* These are the cases in which we win. */
+ if (length == 4)
+ return "mov%I1b,tr %1,%0,%2";
+
+ /* None of these cases wins, but they don't lose either. */
+ if (dbr_sequence_length () == 0)
+ {
+ /* Nothing in the delay slot, fake it by putting the combined
+ insn (the copy or add) in the delay slot of a bl. */
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return "bl %2,0\n\tldi %1,%0";
+ else
+ return "bl %2,0\n\tcopy %1,%0";
+ }
+ else
+ {
+ /* Something in the delay slot, but we've got a long branch. */
+ if (GET_CODE (operands[1]) == CONST_INT)
+ return "ldi %1,%0\n\tbl %2,0";
+ else
+ return "copy %1,%0\n\tbl %2,0";
+ }
+}
+
+/* Output an unconditional add and branch insn. */
+
+char *
+output_parallel_addb (operands, length)
+ rtx *operands;
+ int length;
+{
+ /* To make life easy we want operand0 to be the shared input/output
+ operand and operand1 to be the readonly operand. */
+ if (operands[0] == operands[1])
+ operands[1] = operands[2];
+
+ /* These are the cases in which we win. */
+ if (length == 4)
+ return "add%I1b,tr %1,%0,%3";
+
+ /* None of these cases win, but they don't lose either. */
+ if (dbr_sequence_length () == 0)
+ {
+ /* Nothing in the delay slot, fake it by putting the combined
+ insn (the copy or add) in the delay slot of a bl. */
+ return "bl %3,0\n\tadd%I1 %1,%0,%0";
+ }
+ else
+ {
+ /* Something in the delay slot, but we've got a long branch. */
+ return "add%I1 %1,%0,%0\n\tbl %3,0";
+ }
+}
+
+/* Return nonzero if INSN (a jump insn) immediately follows a call to
+ a named function. This is used to discourage creating parallel movb/addb
+ insns since a jump which immediately follows a call can execute in the
+ delay slot of the call.
+
+ It is also used to avoid filling the delay slot of a jump which
+ immediately follows a call since the jump can usually be eliminated
+ completely by modifying RP in the delay slot of the call. */
+
+following_call (insn)
+ rtx insn;
+{
+ /* Find the previous real insn, skipping NOTEs. */
+ insn = PREV_INSN (insn);
+ while (insn && GET_CODE (insn) == NOTE)
+ insn = PREV_INSN (insn);
+
+ /* Check for CALL_INSNs and millicode calls. */
+ if (insn
+ && ((GET_CODE (insn) == CALL_INSN
+ && get_attr_type (insn) != TYPE_DYNCALL)
+ || (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) != SEQUENCE
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && get_attr_type (insn) == TYPE_MILLI)))
+ return 1;
+
+ return 0;
+}
+
+/* Restore any INSN_CODEs for insns with unscaled indexed addresses since
+ the INSN_CODE might be clobberd by rerecognition triggered by reorg. */
+
+static void
+restore_unscaled_index_insn_codes (insns)
+ rtx insns;
+{
+ rtx insn;
+
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ {
+ if (INSN_UID (insn) < max_unscaled_index_insn_codes_uid
+ && unscaled_index_insn_codes[INSN_UID (insn)] != -1)
+ INSN_CODE (insn) = unscaled_index_insn_codes[INSN_UID (insn)];
+ }
+}
+
+/* Severe braindamage:
+
+ On the PA, address computations within MEM expressions are not
+ commutative because of the implicit space register selection
+ from the base register (instead of the entire effective address).
+
+ Because of this mis-feature we have to know which register in a reg+reg
+ address is the base and which is the index.
+
+ Before reload, the base can be identified by REGNO_POINTER_FLAG. We use
+ this to force base + index addresses to match a different insn than
+ index + base addresses.
+
+ We assume that no pass during or after reload creates new unscaled indexed
+ addresses, so any unscaled indexed address we find after reload must have
+ at one time been recognized a base + index or index + base and we accept
+ any register as a base register.
+
+ This scheme assumes that no pass during/after reload will rerecognize an
+ insn with an unscaled indexed address. This failed due to a reorg call
+ to rerecognize certain insns.
+
+ So, we record if an insn uses an unscaled indexed address and which
+ register is the base (via recording of the INSN_CODE for such insns).
+
+ Just before we output code for the function, we make sure all the insns
+ using unscaled indexed addresses have the same INSN_CODE as they did
+ immediately before delay slot scheduling.
+
+ This is extremely gross. Long term, I'd like to be able to look at
+ REG_POINTER_FLAG to handle these kinds of problems. */
+
+static void
+record_unscaled_index_insn_codes (insns)
+ rtx insns;
+{
+ rtx insn;
+
+ max_unscaled_index_insn_codes_uid = get_max_uid ();
+ unscaled_index_insn_codes
+ = (int *)xmalloc (max_unscaled_index_insn_codes_uid * sizeof (int));
+ memset (unscaled_index_insn_codes, -1,
+ max_unscaled_index_insn_codes_uid * sizeof (int));
+
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ {
+ rtx set = single_set (insn);
+ rtx mem = NULL_RTX;
+
+ /* Ignore anything that isn't a normal SET. */
+ if (set == NULL_RTX)
+ continue;
+
+ /* No insns can have more than one MEM. */
+ if (GET_CODE (SET_SRC (set)) == MEM)
+ mem = SET_SRC (set);
+
+ if (GET_CODE (SET_DEST (set)) == MEM)
+ mem = SET_DEST (set);
+
+ /* If neither operand is a mem, then there's nothing to do. */
+ if (mem == NULL_RTX)
+ continue;
+
+ if (GET_CODE (XEXP (mem, 0)) != PLUS)
+ continue;
+
+ /* If both are REGs (or SUBREGs), then record the insn code for
+ this insn. */
+ if (REG_P (XEXP (XEXP (mem, 0), 0)) && REG_P (XEXP (XEXP (mem, 0), 1)))
+ unscaled_index_insn_codes[INSN_UID (insn)] = INSN_CODE (insn);
+ }
+}
/* We use this hook to perform a PA specific optimization which is difficult
to do in earlier passes.
@@ -4527,53 +5937,396 @@ jump_in_call_delay (insn)
The jump instructions within the table are special; we must be able
to identify them during assembly output (if the jumps don't get filled
we need to emit a nop rather than nullifying the delay slot)). We
- identify jumps in switch tables by marking the SET with DImode. */
+ identify jumps in switch tables by marking the SET with DImode.
+
+ We also surround the jump table itself with BEGIN_BRTAB and END_BRTAB
+ insns. This serves two purposes, first it prevents jump.c from
+ noticing that the last N entries in the table jump to the instruction
+ immediately after the table and deleting the jumps. Second, those
+ insns mark where we should emit .begin_brtab and .end_brtab directives
+ when using GAS (allows for better link time optimizations). */
pa_reorg (insns)
rtx insns;
{
rtx insn;
+ /* Keep track of which insns have unscaled indexed addresses, and which
+ register is the base address in such insns. */
+ record_unscaled_index_insn_codes (insns);
+
+ remove_useless_addtr_insns (insns, 1);
+
+ pa_combine_instructions (get_insns ());
+
/* This is fairly cheap, so always run it if optimizing. */
- if (optimize > 0)
+ if (optimize > 0 && !TARGET_BIG_SWITCH)
{
- /* Find and explode all ADDR_VEC insns. */
+ /* Find and explode all ADDR_VEC or ADDR_DIFF_VEC insns. */
insns = get_insns ();
for (insn = insns; insn; insn = NEXT_INSN (insn))
{
rtx pattern, tmp, location;
unsigned int length, i;
- /* Find an ADDR_VEC insn to explode. */
+ /* Find an ADDR_VEC or ADDR_DIFF_VEC insn to explode. */
if (GET_CODE (insn) != JUMP_INSN
- || GET_CODE (PATTERN (insn)) != ADDR_VEC)
+ || (GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
continue;
+ /* Emit marker for the beginning of the branch table. */
+ emit_insn_before (gen_begin_brtab (), insn);
+
pattern = PATTERN (insn);
location = PREV_INSN (insn);
- length = XVECLEN (pattern, 0);
+ length = XVECLEN (pattern, GET_CODE (pattern) == ADDR_DIFF_VEC);
+
for (i = 0; i < length; i++)
{
- /* Emit the jump itself. */
- tmp = gen_switch_jump (XEXP (XVECEXP (pattern, 0, i), 0));
- tmp = emit_jump_insn_after (tmp, location);
- JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
- LABEL_NUSES (JUMP_LABEL (tmp))++;
-
- /* Emit a BARRIER after the jump. */
- location = NEXT_INSN (location);
- emit_barrier_after (location);
-
- /* Put a CODE_LABEL before each so jump.c does not optimize
- the jumps away. */
- location = NEXT_INSN (location);
+ /* Emit a label before each jump to keep jump.c from
+ removing this code. */
tmp = gen_label_rtx ();
LABEL_NUSES (tmp) = 1;
emit_label_after (tmp, location);
location = NEXT_INSN (location);
+
+ if (GET_CODE (pattern) == ADDR_VEC)
+ {
+ /* Emit the jump itself. */
+ tmp = gen_switch_jump (XEXP (XVECEXP (pattern, 0, i), 0));
+ tmp = emit_jump_insn_after (tmp, location);
+ JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 0, i), 0);
+ LABEL_NUSES (JUMP_LABEL (tmp))++;
+ location = NEXT_INSN (location);
+ }
+ else
+ {
+ /* Emit the jump itself. */
+ tmp = gen_switch_jump (XEXP (XVECEXP (pattern, 1, i), 0));
+ tmp = emit_jump_insn_after (tmp, location);
+ JUMP_LABEL (tmp) = XEXP (XVECEXP (pattern, 1, i), 0);
+ LABEL_NUSES (JUMP_LABEL (tmp))++;
+ location = NEXT_INSN (location);
+ }
+
+ /* Emit a BARRIER after the jump. */
+ emit_barrier_after (location);
+ location = NEXT_INSN (location);
}
- /* Delete the ADDR_VEC. */
+
+ /* Emit marker for the end of the branch table. */
+ emit_insn_before (gen_end_brtab (), location);
+ location = NEXT_INSN (location);
+ emit_barrier_after (location);
+
+ /* Delete the ADDR_VEC or ADDR_DIFF_VEC. */
delete_insn (insn);
}
}
+ else
+ {
+ /* Sill need an end_brtab insn. */
+ insns = get_insns ();
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ {
+ /* Find an ADDR_VEC insn. */
+ if (GET_CODE (insn) != JUMP_INSN
+ || (GET_CODE (PATTERN (insn)) != ADDR_VEC
+ && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC))
+ continue;
+
+ /* Now generate markers for the beginning and end of the
+ branch table. */
+ emit_insn_before (gen_begin_brtab (), insn);
+ emit_insn_after (gen_end_brtab (), insn);
+ }
+ }
+}
+
+/* The PA has a number of odd instructions which can perform multiple
+ tasks at once. On first generation PA machines (PA1.0 and PA1.1)
+ it may be profitable to combine two instructions into one instruction
+ with two outputs. It's not profitable PA2.0 machines because the
+ two outputs would take two slots in the reorder buffers.
+
+ This routine finds instructions which can be combined and combines
+ them. We only support some of the potential combinations, and we
+ only try common ways to find suitable instructions.
+
+ * addb can add two registers or a register and a small integer
+ and jump to a nearby (+-8k) location. Normally the jump to the
+ nearby location is conditional on the result of the add, but by
+ using the "true" condition we can make the jump unconditional.
+ Thus addb can perform two independent operations in one insn.
+
+ * movb is similar to addb in that it can perform a reg->reg
+ or small immediate->reg copy and jump to a nearby (+-8k location).
+
+ * fmpyadd and fmpysub can perform a FP multiply and either an
+ FP add or FP sub if the operands of the multiply and add/sub are
+ independent (there are other minor restrictions). Note both
+ the fmpy and fadd/fsub can in theory move to better spots according
+ to data dependencies, but for now we require the fmpy stay at a
+ fixed location.
+
+ * Many of the memory operations can perform pre & post updates
+ of index registers. GCC's pre/post increment/decrement addressing
+ is far too simple to take advantage of all the possibilities. This
+ pass may not be suitable since those insns may not be independent.
+
+ * comclr can compare two ints or an int and a register, nullify
+ the following instruction and zero some other register. This
+ is more difficult to use as it's harder to find an insn which
+ will generate a comclr than finding something like an unconditional
+ branch. (conditional moves & long branches create comclr insns).
+
+ * Most arithmetic operations can conditionally skip the next
+ instruction. They can be viewed as "perform this operation
+ and conditionally jump to this nearby location" (where nearby
+ is an insns away). These are difficult to use due to the
+ branch length restrictions. */
+
+pa_combine_instructions (insns)
+ rtx insns;
+{
+ rtx anchor, new;
+
+ /* This can get expensive since the basic algorithm is on the
+ order of O(n^2) (or worse). Only do it for -O2 or higher
+ levels of optimization. */
+ if (optimize < 2)
+ return;
+
+ /* Walk down the list of insns looking for "anchor" insns which
+ may be combined with "floating" insns. As the name implies,
+ "anchor" instructions don't move, while "floating" insns may
+ move around. */
+ new = gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, NULL_RTX, NULL_RTX));
+ new = make_insn_raw (new);
+
+ for (anchor = get_insns (); anchor; anchor = NEXT_INSN (anchor))
+ {
+ enum attr_pa_combine_type anchor_attr;
+ enum attr_pa_combine_type floater_attr;
+
+ /* We only care about INSNs, JUMP_INSNs, and CALL_INSNs.
+ Also ignore any special USE insns. */
+ if (GET_CODE (anchor) != INSN
+ && GET_CODE (anchor) != JUMP_INSN
+ && GET_CODE (anchor) != CALL_INSN
+ || GET_CODE (PATTERN (anchor)) == USE
+ || GET_CODE (PATTERN (anchor)) == CLOBBER
+ || GET_CODE (PATTERN (anchor)) == ADDR_VEC
+ || GET_CODE (PATTERN (anchor)) == ADDR_DIFF_VEC)
+ continue;
+
+ anchor_attr = get_attr_pa_combine_type (anchor);
+ /* See if anchor is an insn suitable for combination. */
+ if (anchor_attr == PA_COMBINE_TYPE_FMPY
+ || anchor_attr == PA_COMBINE_TYPE_FADDSUB
+ || (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
+ && ! forward_branch_p (anchor)))
+ {
+ rtx floater;
+
+ for (floater = PREV_INSN (anchor);
+ floater;
+ floater = PREV_INSN (floater))
+ {
+ if (GET_CODE (floater) == NOTE
+ || (GET_CODE (floater) == INSN
+ && (GET_CODE (PATTERN (floater)) == USE
+ || GET_CODE (PATTERN (floater)) == CLOBBER)))
+ continue;
+
+ /* Anything except a regular INSN will stop our search. */
+ if (GET_CODE (floater) != INSN
+ || GET_CODE (PATTERN (floater)) == ADDR_VEC
+ || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
+ {
+ floater = NULL_RTX;
+ break;
+ }
+
+ /* See if FLOATER is suitable for combination with the
+ anchor. */
+ floater_attr = get_attr_pa_combine_type (floater);
+ if ((anchor_attr == PA_COMBINE_TYPE_FMPY
+ && floater_attr == PA_COMBINE_TYPE_FADDSUB)
+ || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
+ && floater_attr == PA_COMBINE_TYPE_FMPY))
+ {
+ /* If ANCHOR and FLOATER can be combined, then we're
+ done with this pass. */
+ if (pa_can_combine_p (new, anchor, floater, 0,
+ SET_DEST (PATTERN (floater)),
+ XEXP (SET_SRC (PATTERN (floater)), 0),
+ XEXP (SET_SRC (PATTERN (floater)), 1)))
+ break;
+ }
+
+ else if (anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH
+ && floater_attr == PA_COMBINE_TYPE_ADDMOVE)
+ {
+ if (GET_CODE (SET_SRC (PATTERN (floater))) == PLUS)
+ {
+ if (pa_can_combine_p (new, anchor, floater, 0,
+ SET_DEST (PATTERN (floater)),
+ XEXP (SET_SRC (PATTERN (floater)), 0),
+ XEXP (SET_SRC (PATTERN (floater)), 1)))
+ break;
+ }
+ else
+ {
+ if (pa_can_combine_p (new, anchor, floater, 0,
+ SET_DEST (PATTERN (floater)),
+ SET_SRC (PATTERN (floater)),
+ SET_SRC (PATTERN (floater))))
+ break;
+ }
+ }
+ }
+
+ /* If we didn't find anything on the backwards scan try forwards. */
+ if (!floater
+ && (anchor_attr == PA_COMBINE_TYPE_FMPY
+ || anchor_attr == PA_COMBINE_TYPE_FADDSUB))
+ {
+ for (floater = anchor; floater; floater = NEXT_INSN (floater))
+ {
+ if (GET_CODE (floater) == NOTE
+ || (GET_CODE (floater) == INSN
+ && (GET_CODE (PATTERN (floater)) == USE
+ || GET_CODE (PATTERN (floater)) == CLOBBER)))
+
+ continue;
+
+ /* Anything except a regular INSN will stop our search. */
+ if (GET_CODE (floater) != INSN
+ || GET_CODE (PATTERN (floater)) == ADDR_VEC
+ || GET_CODE (PATTERN (floater)) == ADDR_DIFF_VEC)
+ {
+ floater = NULL_RTX;
+ break;
+ }
+
+ /* See if FLOATER is suitable for combination with the
+ anchor. */
+ floater_attr = get_attr_pa_combine_type (floater);
+ if ((anchor_attr == PA_COMBINE_TYPE_FMPY
+ && floater_attr == PA_COMBINE_TYPE_FADDSUB)
+ || (anchor_attr == PA_COMBINE_TYPE_FADDSUB
+ && floater_attr == PA_COMBINE_TYPE_FMPY))
+ {
+ /* If ANCHOR and FLOATER can be combined, then we're
+ done with this pass. */
+ if (pa_can_combine_p (new, anchor, floater, 1,
+ SET_DEST (PATTERN (floater)),
+ XEXP (SET_SRC (PATTERN(floater)),0),
+ XEXP(SET_SRC(PATTERN(floater)),1)))
+ break;
+ }
+ }
+ }
+
+ /* FLOATER will be nonzero if we found a suitable floating
+ insn for combination with ANCHOR. */
+ if (floater
+ && (anchor_attr == PA_COMBINE_TYPE_FADDSUB
+ || anchor_attr == PA_COMBINE_TYPE_FMPY))
+ {
+ /* Emit the new instruction and delete the old anchor. */
+ emit_insn_before (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2, PATTERN (anchor),
+ PATTERN (floater))),
+ anchor);
+ PUT_CODE (anchor, NOTE);
+ NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (anchor) = 0;
+
+ /* Emit a special USE insn for FLOATER, then delete
+ the floating insn. */
+ emit_insn_before (gen_rtx (USE, VOIDmode, floater), floater);
+ delete_insn (floater);
+
+ continue;
+ }
+ else if (floater
+ && anchor_attr == PA_COMBINE_TYPE_UNCOND_BRANCH)
+ {
+ rtx temp;
+ /* Emit the new_jump instruction and delete the old anchor. */
+ temp = emit_jump_insn_before (gen_rtx (PARALLEL, VOIDmode,
+ gen_rtvec (2, PATTERN (anchor),
+ PATTERN (floater))),
+ anchor);
+ JUMP_LABEL (temp) = JUMP_LABEL (anchor);
+ PUT_CODE (anchor, NOTE);
+ NOTE_LINE_NUMBER (anchor) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (anchor) = 0;
+
+ /* Emit a special USE insn for FLOATER, then delete
+ the floating insn. */
+ emit_insn_before (gen_rtx (USE, VOIDmode, floater), floater);
+ delete_insn (floater);
+ continue;
+ }
+ }
+ }
+}
+
+int
+pa_can_combine_p (new, anchor, floater, reversed, dest, src1, src2)
+ rtx new, anchor, floater;
+ int reversed;
+ rtx dest, src1, src2;
+{
+ int insn_code_number;
+ rtx start, end;
+
+ /* Create a PARALLEL with the patterns of ANCHOR and
+ FLOATER, try to recognize it, then test constraints
+ for the resulting pattern.
+
+ If the pattern doesn't match or the constraints
+ aren't met keep searching for a suitable floater
+ insn. */
+ XVECEXP (PATTERN (new), 0, 0) = PATTERN (anchor);
+ XVECEXP (PATTERN (new), 0, 1) = PATTERN (floater);
+ INSN_CODE (new) = -1;
+ insn_code_number = recog_memoized (new);
+ if (insn_code_number < 0
+ || !constrain_operands (insn_code_number, 1))
+ return 0;
+
+ if (reversed)
+ {
+ start = anchor;
+ end = floater;
+ }
+ else
+ {
+ start = floater;
+ end = anchor;
+ }
+
+ /* There's up to three operands to consider. One
+ output and two inputs.
+
+ The output must not be used between FLOATER & ANCHOR
+ exclusive. The inputs must not be set between
+ FLOATER and ANCHOR exclusive. */
+
+ if (reg_used_between_p (dest, start, end))
+ return 0;
+
+ if (reg_set_between_p (src1, start, end))
+ return 0;
+
+ if (reg_set_between_p (src2, start, end))
+ return 0;
+
+ /* If we get here, then everything is good. */
+ return 1;
}
diff --git a/gnu/usr.bin/gcc/config/pa/pa.md b/gnu/usr.bin/gcc/config/pa/pa.md
index c2c2a26b5e1..79c973b6b4d 100644
--- a/gnu/usr.bin/gcc/config/pa/pa.md
+++ b/gnu/usr.bin/gcc/config/pa/pa.md
@@ -1,5 +1,5 @@
;;- Machine description for HP PA-RISC architecture for GNU C compiler
-;; Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
;; Contributed by the Center for Software Science at the University
;; of Utah.
@@ -31,9 +31,13 @@
;; type "binary" insns have two input operands (1,2) and one output (0)
(define_attr "type"
- "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli"
+ "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,parallel_branch"
(const_string "binary"))
+(define_attr "pa_combine_type"
+ "fmpy,faddsub,uncond_branch,addmove,none"
+ (const_string "none"))
+
;; Processor type (for scheduling, not code generation) -- this attribute
;; must exactly match the processor_type enumeration in pa.h.
;;
@@ -69,7 +73,7 @@
;; For conditional branches.
(define_attr "in_branch_delay" "false,true"
- (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli")
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
(eq_attr "length" "4"))
(const_string "true")
(const_string "false")))
@@ -77,7 +81,7 @@
;; Disallow instructions which use the FPU since they will tie up the FPU
;; even if the instruction is nullified.
(define_attr "in_nullified_branch_delay" "false,true"
- (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl")
+ (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch")
(eq_attr "length" "4"))
(const_string "true")
(const_string "false")))
@@ -85,7 +89,7 @@
;; For calls and millicode calls. Allow unconditional branches in the
;; delay slot.
(define_attr "in_call_delay" "false,true"
- (cond [(and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli")
+ (cond [(and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,dyncall,multi,milli,parallel_branch")
(eq_attr "length" "4"))
(const_string "true")
(eq_attr "type" "uncond_branch")
@@ -96,20 +100,19 @@
(const_string "false")))
-;; Unconditional branch and call delay slot description.
-(define_delay (eq_attr "type" "uncond_branch,branch,call")
+;; Call delay slot description.
+(define_delay (eq_attr "type" "call")
[(eq_attr "in_call_delay" "true") (nil) (nil)])
;; millicode call delay slot description. Note it disallows delay slot
-;; when TARGET_PORTABLE_RUNTIME or TARGET_MILLICODE_LONG_CALLS is true.
+;; when TARGET_PORTABLE_RUNTIME is true.
(define_delay (eq_attr "type" "milli")
[(and (eq_attr "in_call_delay" "true")
- (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS") (const_int 0))))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME") (const_int 0)))
(nil) (nil)])
-;; Unconditional branch, return and other similar instructions.
-(define_delay (eq_attr "type" "uncond_branch,branch")
+;; Return and other similar instructions.
+(define_delay (eq_attr "type" "branch,parallel_branch")
[(eq_attr "in_branch_delay" "true") (nil) (nil)])
;; Floating point conditional branch delay slot description and
@@ -130,6 +133,11 @@
(and (eq_attr "in_nullified_branch_delay" "true")
(attr_flag "backward"))])
+(define_delay (and (eq_attr "type" "uncond_branch")
+ (eq (symbol_ref "following_call (insn)")
+ (const_int 0)))
+ [(eq_attr "in_branch_delay" "true") (nil) (nil)])
+
;; Function units of the HPPA. The following data is for the 700 CPUs
;; (Mustang CPU + Timex FPU aka PA-89) because that's what I have the docs for.
;; Scheduling instructions for PA-83 machines according to the Snake
@@ -761,6 +769,15 @@
comiclr,<< %2,%0,0\;ldi %2,%0"
[(set_attr "type" "multi,multi")
(set_attr "length" "8,8")])
+
+(define_insn "abssi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (abs:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "or,>= %%r0,%1,%0\;subi 0,%0,%0"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
;;; Experimental conditional move patterns
(define_expand "movsicc"
@@ -1016,10 +1033,15 @@
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
- (const_int 8188))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28)))])
;; Match the negated branch.
@@ -1039,10 +1061,15 @@
}"
[(set_attr "type" "cbranch")
(set (attr "length")
- (if_then_else (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
- (const_int 8188))
- (const_int 4)
- (const_int 8)))])
+ (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (const_int 8)
+ (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 20)]
+ (const_int 28)))])
;; Branch on Bit patterns.
(define_insn ""
@@ -1063,7 +1090,7 @@
[(set_attr "type" "cbranch")
(set (attr "length")
(if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 4)
(const_int 8)))])
@@ -1085,7 +1112,7 @@
[(set_attr "type" "cbranch")
(set (attr "length")
(if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 4)
(const_int 8)))])
@@ -1107,7 +1134,7 @@
[(set_attr "type" "cbranch")
(set (attr "length")
(if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 4)
(const_int 8)))])
@@ -1129,7 +1156,96 @@
[(set_attr "type" "cbranch")
(set (attr "length")
(if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+;; Branch on Variable Bit patterns.
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "register_operand" "q"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
+ get_attr_length (insn), 0, insn, 0);
+}"
+[(set_attr "type" "cbranch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "register_operand" "q"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "*
+{
+ return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
+ get_attr_length (insn), 1, insn, 0);
+}"
+[(set_attr "type" "cbranch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "register_operand" "q"))
+ (const_int 0))
+ (label_ref (match_operand 2 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
+ get_attr_length (insn), 0, insn, 1);
+}"
+[(set_attr "type" "cbranch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
+ (const_int 1)
+ (match_operand:SI 1 "register_operand" "q"))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 2 "" ""))))]
+ ""
+ "*
+{
+ return output_bvb (operands, INSN_ANNULLED_BRANCH_P (insn),
+ get_attr_length (insn), 1, insn, 1);
+}"
+[(set_attr "type" "cbranch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
(const_int 4)
(const_int 8)))])
@@ -1222,9 +1338,9 @@
(define_insn ""
[(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand"
- "=r,r,r,r,r,Q,*q,!f,f,*T")
+ "=r,r,r,r,r,Q,*q,!f,f,*TR")
(match_operand:SI 1 "move_operand"
- "r,J,N,K,Q,rM,rM,!fM,*T,f"))]
+ "r,J,N,K,RQ,rM,rM,!fM,*RT,f"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
&& ! TARGET_SOFT_FLOAT"
@@ -1237,16 +1353,17 @@
stw%M0 %r1,%0
mtsar %r1
fcpy,sgl %r1,%0
- fldws%F1 %1,%0
- fstws%F0 %1,%0"
+ fldw%F1 %1,%0
+ fstw%F0 %1,%0"
[(set_attr "type" "move,move,move,shift,load,store,move,fpalu,fpload,fpstore")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4,4,4,4,4,4,4,4,4")])
(define_insn ""
[(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand"
"=r,r,r,r,r,Q,*q")
(match_operand:SI 1 "move_operand"
- "r,J,N,K,Q,rM,rM"))]
+ "r,J,N,K,RQ,rM,rM"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))
&& TARGET_SOFT_FLOAT"
@@ -1259,111 +1376,109 @@
stw%M0 %r1,%0
mtsar %r1"
[(set_attr "type" "move,move,move,move,load,store,move")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4,4,4,4,4,4")])
-;; Load indexed. We don't use unscaled modes since they can't be used
-;; unless we can tell which of the registers is the base and which is
-;; the index, due to PA's idea of segment selection using the top bits
-;; of the base register.
-
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
- (mem:SI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 4))
+ (mem:SI (plus:SI (match_operand:SI 1 "basereg_operand" "r")
(match_operand:SI 2 "register_operand" "r"))))]
"! TARGET_DISABLE_INDEXING"
- "ldwx,s %1(0,%2),%0"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"ldwx %1(0,%2),%0\";
+ else
+ return \"ldwx %2(0,%1),%0\";
+}"
[(set_attr "type" "load")
(set_attr "length" "4")])
-;; This variant of the above insn can occur if the second operand
-;; is the frame pointer. This is a kludge, but there doesn't
-;; seem to be a way around it. Only recognize it while reloading.
-;; Note how operand 3 uses a predicate of "const_int_operand", but
-;; has constraints allowing a register. I don't know how this works,
-;; but it somehow makes sure that out-of-range constants are placed
-;; in a register which somehow magically is a "const_int_operand".
-;; (this was stolen from alpha.md, I'm not going to try and change it.)
(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "&=r")
- (mem:SI (plus:SI (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 4))
- (match_operand:SI 2 "register_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "rI"))))]
- "! TARGET_DISABLE_INDEXING && reload_in_progress"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))))]
+ "! TARGET_DISABLE_INDEXING"
"*
{
- if (GET_CODE (operands[3]) == CONST_INT)
- return \"sh2addl %1,%2,%0\;ldw %3(0,%0),%0\";
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"ldwx %2(0,%1),%0\";
else
- return \"sh2addl %1,%2,%0\;ldwx %3(0,%0),%0\";
+ return \"ldwx %1(0,%2),%0\";
}"
[(set_attr "type" "load")
- (set_attr "length" "8")])
+ (set_attr "length" "4")])
;; Load or store with base-register modification.
(define_insn "pre_ldwm"
- [(set (match_operand:SI 3 "register_operand" "=r")
- (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "0")
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "=r")
(match_operand:SI 2 "pre_cint_operand" ""))))
- (set (match_operand:SI 0 "register_operand" "=r")
+ (set (match_dup 1)
(plus:SI (match_dup 1) (match_dup 2)))]
""
"*
{
if (INTVAL (operands[2]) < 0)
- return \"ldwm %2(0,%0),%3\";
- return \"ldws,mb %2(0,%0),%3\";
+ return \"ldwm %2(0,%1),%0\";
+ return \"ldws,mb %2(0,%1),%0\";
}"
[(set_attr "type" "load")
(set_attr "length" "4")])
(define_insn "pre_stwm"
- [(set (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "pre_cint_operand" "")))
- (match_operand:SI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "pre_cint_operand" "")))
+ (match_operand:SI 2 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
""
"*
{
- if (INTVAL (operands[2]) < 0)
- return \"stwm %r3,%2(0,%0)\";
- return \"stws,mb %r3,%2(0,%0)\";
+ if (INTVAL (operands[1]) < 0)
+ return \"stwm %r2,%1(0,%0)\";
+ return \"stws,mb %r2,%1(0,%0)\";
}"
[(set_attr "type" "store")
(set_attr "length" "4")])
(define_insn "post_ldwm"
- [(set (match_operand:SI 3 "register_operand" "r")
- (mem:SI (match_operand:SI 1 "register_operand" "0")))
- (set (match_operand:SI 0 "register_operand" "=r")
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mem:SI (match_operand:SI 1 "register_operand" "=r")))
+ (set (match_dup 1)
(plus:SI (match_dup 1)
(match_operand:SI 2 "post_cint_operand" "")))]
""
"*
{
if (INTVAL (operands[2]) > 0)
- return \"ldwm %2(0,%0),%3\";
- return \"ldws,ma %2(0,%0),%3\";
+ return \"ldwm %2(0,%1),%0\";
+ return \"ldws,ma %2(0,%1),%0\";
}"
[(set_attr "type" "load")
(set_attr "length" "4")])
(define_insn "post_stwm"
- [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
- (match_operand:SI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1)
+ [(set (mem:SI (match_operand:SI 0 "register_operand" "=r"))
+ (match_operand:SI 1 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
(match_operand:SI 2 "post_cint_operand" "")))]
""
"*
{
if (INTVAL (operands[2]) > 0)
- return \"stwm %r3,%2(0,%0)\";
- return \"stws,ma %r3,%2(0,%0)\";
+ return \"stwm %r1,%2(0,%0)\";
+ return \"stws,ma %r1,%2(0,%0)\";
}"
[(set_attr "type" "store")
(set_attr "length" "4")])
@@ -1394,7 +1509,7 @@
if (GET_CODE (operands[1]) == LABEL_REF
&& insn_addresses
&& abs (insn_addresses[INSN_UID (XEXP (operands[1], 0))]
- - insn_current_address) < 8100)
+ - insn_addresses[INSN_UID (insn)]) < 8100)
{
/* Prefixing with R% here is wrong, it extracts just 11 bits and is
always non-negative. */
@@ -1449,9 +1564,19 @@
&& ! function_label_operand (operands[1])
&& ! read_only_operand (operands[1])
&& ! flag_pic"
- "addil LR'%G1,%%r27"
+ "*
+{
+ if (TARGET_LONG_LOAD_STORE)
+ return \"addil NLR'%H1,%%r27\;ldo N'%H1(%%r1),%%r1\";
+ else
+ return \"addil LR'%H1,%%r27\";
+}"
[(set_attr "type" "binary")
- (set_attr "length" "4")])
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "TARGET_LONG_LOAD_STORE") (const_int 0))
+ (const_int 4)
+ (const_int 8)))])
+
;; This is for use in the prologue/epilogue code. We need it
;; to add large constants to a stack pointer or frame pointer.
@@ -1469,25 +1594,6 @@
[(set_attr "type" "binary,binary")
(set_attr "length" "4,8")])
-;; For function addresses.
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (match_operand:SI 1 "function_label_operand" "")))]
- "!TARGET_PORTABLE_RUNTIME"
- "ldil LP'%G1,%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
-;; This version is used only for the portable runtime conventions model
-;; (it does not use/support plabels)
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (high:SI (match_operand:SI 1 "function_label_operand" "")))]
- "TARGET_PORTABLE_RUNTIME"
- "ldil L'%G1,%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand 1 "" "")))]
@@ -1496,39 +1602,13 @@
"*
{
if (symbolic_operand (operands[1], Pmode))
- return \"ldil LR'%G1,%0\";
+ return \"ldil LR'%H1,%0\";
else
return \"ldil L'%G1,%0\";
}"
[(set_attr "type" "move")
(set_attr "length" "4")])
-;; lo_sum of a function address.
-;;
-;; Note since we are not supporting MPE style external calls we can
-;; use the short ldil;ldo sequence. If one wanted to support
-;; MPE external calls you would want to generate something like
-;; ldil;ldo;extru;ldw;add. See the HP compiler's output for details.
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "function_label_operand" "")))]
- "!TARGET_PORTABLE_RUNTIME"
- "ldo RP'%G2(%1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
-;; This version is used only for the portable runtime conventions model
-;; (it does not use/support plabels)
-(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "function_label_operand" "")))]
- "TARGET_PORTABLE_RUNTIME"
- "ldo R'%G2(%1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "4")])
-
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
@@ -1560,6 +1640,52 @@
(set (match_dup 0) (lo_sum:SI (match_dup 2) (match_dup 1)))]
"")
+;; hppa_legitimize_address goes to a great deal of trouble to
+;; create addresses which use indexing. In some cases, this
+;; is a lose because there isn't any store instructions which
+;; allow indexed addresses (with integer register source).
+;;
+;; These define_splits try to turn a 3 insn store into
+;; a 2 insn store with some creative RTL rewriting.
+(define_split
+ [(set (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "shadd_operand" ""))
+ (plus:SI (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "const_int_operand" ""))))
+ (match_operand:SI 4 "register_operand" ""))
+ (clobber (match_operand:SI 5 "register_operand" ""))]
+ ""
+ [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+ (match_dup 2)))
+ (set (mem:SI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
+ "")
+
+(define_split
+ [(set (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "shadd_operand" ""))
+ (plus:SI (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "const_int_operand" ""))))
+ (match_operand:HI 4 "register_operand" ""))
+ (clobber (match_operand:SI 5 "register_operand" ""))]
+ ""
+ [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+ (match_dup 2)))
+ (set (mem:HI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
+ "")
+
+(define_split
+ [(set (mem:QI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "shadd_operand" ""))
+ (plus:SI (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "const_int_operand" ""))))
+ (match_operand:QI 4 "register_operand" ""))
+ (clobber (match_operand:SI 5 "register_operand" ""))]
+ ""
+ [(set (match_dup 5) (plus:SI (mult:SI (match_dup 0) (match_dup 1))
+ (match_dup 2)))
+ (set (mem:QI (plus:SI (match_dup 5) (match_dup 3))) (match_dup 4))]
+ "")
+
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
@@ -1572,7 +1698,7 @@
(define_insn ""
[(set (match_operand:HI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f")
- (match_operand:HI 1 "move_operand" "r,J,N,K,Q,rM,rM,!fM"))]
+ (match_operand:HI 1 "move_operand" "r,J,N,K,RQ,rM,rM,!fM"))]
"register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode)"
"@
@@ -1585,63 +1711,123 @@
mtsar %r1
fcpy,sgl %r1,%0"
[(set_attr "type" "move,move,move,shift,load,store,move,fpalu")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4,4,4,4,4,4,4")])
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
- (mem:HI (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r")
- (const_int 2))
- (match_operand:SI 1 "register_operand" "r"))))]
+ (mem:HI (plus:SI (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))))]
"! TARGET_DISABLE_INDEXING"
- "ldhx,s %2(0,%1),%0"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"ldhx %1(0,%2),%0\";
+ else
+ return \"ldhx %2(0,%1),%0\";
+}"
[(set_attr "type" "load")
(set_attr "length" "4")])
-;; This variant of the above insn can occur if the second operand
-;; is the frame pointer. This is a kludge, but there doesn't
-;; seem to be a way around it. Only recognize it while reloading.
-;; Note how operand 3 uses a predicate of "const_int_operand", but
-;; has constraints allowing a register. I don't know how this works,
-;; but it somehow makes sure that out-of-range constants are placed
-;; in a register which somehow magically is a "const_int_operand".
-;; (this was stolen from alpha.md, I'm not going to try and change it.
(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=&r")
- (mem:HI (plus:SI (plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r")
- (const_int 2))
- (match_operand:SI 1 "register_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "rI"))))]
- "! TARGET_DISABLE_INDEXING && reload_in_progress"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))))]
+ "! TARGET_DISABLE_INDEXING"
"*
{
- if (GET_CODE (operands[3]) == CONST_INT)
- return \"sh1addl %2,%1,%0\;ldh %3(0,%0),%0\";
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"ldhx %2(0,%1),%0\";
else
- return \"sh1addl %2,%1,%0\;ldhx %3(0,%0),%0\";
+ return \"ldhx %1(0,%2),%0\";
}"
[(set_attr "type" "load")
- (set_attr "length" "8")])
+ (set_attr "length" "4")])
+; Now zero extended variants.
(define_insn ""
- [(set (match_operand:HI 3 "register_operand" "=r")
- (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "0")
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:HI
+ (plus:SI
+ (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"ldhx %1(0,%2),%0\";
+ else
+ return \"ldhx %2(0,%1),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:HI
+ (plus:SI
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r")))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"ldhx %2(0,%1),%0\";
+ else
+ return \"ldhx %1(0,%2),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "=r")
(match_operand:SI 2 "int5_operand" "L"))))
- (set (match_operand:SI 0 "register_operand" "=r")
+ (set (match_dup 1)
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "ldhs,mb %2(0,%0),%3"
+ "ldhs,mb %2(0,%1),%0"
[(set_attr "type" "load")
(set_attr "length" "4")])
+; And a zero extended variant.
(define_insn ""
- [(set (mem:HI (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "int5_operand" "L")))
- (match_operand:HI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:HI
+ (plus:SI
+ (match_operand:SI 1 "register_operand" "=r")
+ (match_operand:SI 2 "int5_operand" "L")))))
+ (set (match_dup 1)
(plus:SI (match_dup 1) (match_dup 2)))]
""
- "sths,mb %r3,%2(0,%0)"
+ "ldhs,mb %2(0,%1),%0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (mem:HI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "int5_operand" "L")))
+ (match_operand:HI 2 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
+ ""
+ "sths,mb %r2,%1(0,%0)"
[(set_attr "type" "store")
(set_attr "length" "4")])
@@ -1674,7 +1860,7 @@
(define_insn ""
[(set (match_operand:QI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,r,r,Q,*q,!f")
- (match_operand:QI 1 "move_operand" "r,J,N,K,Q,rM,rM,!fM"))]
+ (match_operand:QI 1 "move_operand" "r,J,N,K,RQ,rM,rM,!fM"))]
"register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode)"
"@
@@ -1687,27 +1873,173 @@
mtsar %r1
fcpy,sgl %r1,%0"
[(set_attr "type" "move,move,move,shift,load,store,move,fpalu")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4,4,4,4,4,4,4")])
(define_insn ""
- [(set (match_operand:QI 3 "register_operand" "=r")
- (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "0")
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:SI (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"ldbx %1(0,%2),%0\";
+ else
+ return \"ldbx %2(0,%1),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"ldbx %2(0,%1),%0\";
+ else
+ return \"ldbx %1(0,%2),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+; Indexed byte load with zero extension to SImode or HImode.
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:QI
+ (plus:SI
+ (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"ldbx %1(0,%2),%0\";
+ else
+ return \"ldbx %2(0,%1),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:QI
+ (plus:SI
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r")))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"ldbx %2(0,%1),%0\";
+ else
+ return \"ldbx %1(0,%2),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (mem:QI
+ (plus:SI
+ (match_operand:SI 1 "basereg_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"ldbx %1(0,%2),%0\";
+ else
+ return \"ldbx %2(0,%1),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (mem:QI
+ (plus:SI
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r")))))]
+ "! TARGET_DISABLE_INDEXING"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"ldbx %2(0,%1),%0\";
+ else
+ return \"ldbx %1(0,%2),%0\";
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "=r")
(match_operand:SI 2 "int5_operand" "L"))))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
""
- "ldbs,mb %2(0,%0),%3"
+ "ldbs,mb %2(0,%1),%0"
[(set_attr "type" "load")
(set_attr "length" "4")])
+; Now the same thing with zero extensions.
(define_insn ""
- [(set (mem:QI (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "int5_operand" "L")))
- (match_operand:QI 3 "reg_or_0_operand" "rM"))
- (set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI (mem:QI (plus:SI
+ (match_operand:SI 1 "register_operand" "=r")
+ (match_operand:SI 2 "int5_operand" "L")))))
+ (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
+ ""
+ "ldbs,mb %2(0,%1),%0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (mem:QI (plus:SI
+ (match_operand:SI 1 "register_operand" "=r")
+ (match_operand:SI 2 "int5_operand" "L")))))
+ (set (match_dup 1) (plus:SI (match_dup 1) (match_dup 2)))]
""
- "stbs,mb %r3,%2(0,%0)"
+ "ldbs,mb %2(0,%1),%0"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn ""
+ [(set (mem:QI (plus:SI (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "int5_operand" "L")))
+ (match_operand:QI 2 "reg_or_0_operand" "rM"))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0) (match_dup 1)))]
+ ""
+ "stbs,mb %r2,%1(0,%0)"
[(set_attr "type" "store")
(set_attr "length" "4")])
@@ -1716,30 +2048,71 @@
;; that anything generated as this insn will be recognized as one
;; and that it will not successfully combine with anything.
(define_expand "movstrsi"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "" ""))
- (mem:BLK (match_operand:BLK 1 "" "")))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
+ [(parallel [(set (match_operand:BLK 0 "" "")
+ (match_operand:BLK 1 "" ""))
+ (clobber (match_dup 7))
+ (clobber (match_dup 8))
(clobber (match_dup 4))
(clobber (match_dup 5))
+ (clobber (match_dup 6))
(use (match_operand:SI 2 "arith_operand" ""))
(use (match_operand:SI 3 "const_int_operand" ""))])]
""
"
{
- /* If the blocks are not at least word-aligned and rather big (>16 items),
- or the size is indeterminate, don't inline the copy code. A
- procedure call is better since it can check the alignment at
- runtime and make the optimal decisions. */
- if (INTVAL (operands[3]) < 4
- && (GET_CODE (operands[2]) != CONST_INT
- || (INTVAL (operands[2]) / INTVAL (operands[3]) > 8)))
- FAIL;
-
- operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
- operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
+ int size, align;
+
+ /* HP provides very fast block move library routine for the PA;
+ this routine includes:
+
+ 4x4 byte at a time block moves,
+ 1x4 byte at a time with alignment checked at runtime with
+ attempts to align the source and destination as needed
+ 1x1 byte loop
+
+ With that in mind, here's the heuristics to try and guess when
+ the inlined block move will be better than the library block
+ move:
+
+ If the size isn't constant, then always use the library routines.
+
+ If the size is large in respect to the known alignment, then use
+ the library routines.
+
+ If the size is small in repsect to the known alignment, then open
+ code the copy (since that will lead to better scheduling).
+
+ Else use the block move pattern. */
+
+ /* Undetermined size, use the library routine. */
+ if (GET_CODE (operands[2]) != CONST_INT)
+ FAIL;
+
+ size = INTVAL (operands[2]);
+ align = INTVAL (operands[3]);
+ align = align > 4 ? 4 : align;
+
+ /* If size/alignment > 8 (eg size is large in respect to alignment),
+ then use the library routines. */
+ if (size / align > 16)
+ FAIL;
+
+ /* This does happen, but not often enough to worry much about. */
+ if (size / align < MOVE_RATIO)
+ FAIL;
+
+ /* Fall through means we're going to use our block move pattern. */
+ operands[0]
+ = change_address (operands[0], VOIDmode,
+ copy_to_mode_reg (SImode, XEXP (operands[0], 0)));
+ operands[1]
+ = change_address (operands[1], VOIDmode,
+ copy_to_mode_reg (SImode, XEXP (operands[1], 0)));
operands[4] = gen_reg_rtx (SImode);
operands[5] = gen_reg_rtx (SImode);
+ operands[6] = gen_reg_rtx (SImode);
+ operands[7] = XEXP (operands[0], 0);
+ operands[8] = XEXP (operands[1], 0);
}")
;; The operand constraints are written like this to support both compile-time
@@ -1747,13 +2120,14 @@
;; the register with the byte count is clobbered by the copying code, and
;; therefore it is forced to operand 2. If the count is compile-time
;; determined, we need two scratch registers for the unrolled code.
-(define_insn ""
+(define_insn "movstrsi_internal"
[(set (mem:BLK (match_operand:SI 0 "register_operand" "+r,r"))
(mem:BLK (match_operand:SI 1 "register_operand" "+r,r")))
(clobber (match_dup 0))
(clobber (match_dup 1))
(clobber (match_operand:SI 2 "register_operand" "=r,r")) ;loop cnt/tmp
(clobber (match_operand:SI 3 "register_operand" "=&r,&r")) ;item tmp
+ (clobber (match_operand:SI 6 "register_operand" "=&r,&r")) ;item tmp2
(use (match_operand:SI 4 "arith_operand" "J,2")) ;byte count
(use (match_operand:SI 5 "const_int_operand" "n,n"))] ;alignment
""
@@ -1772,13 +2146,13 @@
;; This must come before the movdf pattern, and it must be present
;; to handle obscure reloading cases.
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=?r,f")
+ [(set (match_operand:DF 0 "register_operand" "=?r,f")
(match_operand:DF 1 "" "?F,m"))]
"GET_CODE (operands[1]) == CONST_DOUBLE
&& operands[1] != CONST0_RTX (DFmode)
&& ! TARGET_SOFT_FLOAT"
"* return (which_alternative == 0 ? output_move_double (operands)
- : \" fldds%F1 %1,%0\");"
+ : \"fldd%F1 %1,%0\");"
[(set_attr "type" "move,fpload")
(set_attr "length" "16,4")])
@@ -1827,11 +2201,13 @@
(define_insn ""
[(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
- "=f,*r,Q,?o,?Q,f,*&r,*&r")
+ "=f,*r,RQ,?o,?Q,f,*r,*r")
(match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
- "fG,*rG,f,*r,*r,Q,o,Q"))]
+ "fG,*rG,f,*r,*r,RQ,o,RQ"))]
"(register_operand (operands[0], DFmode)
|| reg_or_0_operand (operands[1], DFmode))
+ && ! (GET_CODE (operands[1]) == CONST_DOUBLE
+ && GET_CODE (operands[0]) == MEM)
&& ! TARGET_SOFT_FLOAT"
"*
{
@@ -1845,7 +2221,7 @@
(define_insn ""
[(set (match_operand:DF 0 "reg_or_nonsymb_mem_operand"
- "=r,?o,?Q,&r,&r")
+ "=r,?o,?Q,r,r")
(match_operand:DF 1 "reg_or_0_or_nonsymb_mem_operand"
"rG,r,r,o,Q"))]
"(register_operand (operands[0], DFmode)
@@ -1859,82 +2235,80 @@
(set_attr "length" "8,8,16,8,16")])
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (mem:DF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 8))
+ [(set (match_operand:DF 0 "register_operand" "=fx")
+ (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
(match_operand:SI 2 "register_operand" "r"))))]
"! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
- "flddx,s %1(0,%2),%0"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"flddx %1(0,%2),%0\";
+ else
+ return \"flddx %2(0,%1),%0\";
+}"
[(set_attr "type" "fpload")
(set_attr "length" "4")])
-;; This variant of the above insn can occur if the second operand
-;; is the frame pointer. This is a kludge, but there doesn't
-;; seem to be a way around it. Only recognize it while reloading.
-;; Note how operand 3 uses a predicate of "const_int_operand", but
-;; has constraints allowing a register. I don't know how this works,
-;; but it somehow makes sure that out-of-range constants are placed
-;; in a register which somehow magically is a "const_int_operand".
-;; (this was stolen from alpha.md, I'm not going to try and change it.
-;; Ugh. Output is a FP register; so we need to earlyclobber something
-;; else as a temporary.
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=f")
- (mem:DF (plus:SI
- (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "+&r")
- (const_int 8))
- (match_operand:SI 2 "register_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "rL"))))]
- "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress"
+ [(set (match_operand:DF 0 "register_operand" "=fx")
+ (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))))]
+ "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
"*
{
- if (GET_CODE (operands[3]) == CONST_INT)
- return \"sh3addl %1,%2,%1\;fldds %3(0,%1),%0\";
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"flddx %2(0,%1),%0\";
else
- return \"sh3addl %1,%2,%1\;flddx %3(0,%1),%0\";
+ return \"flddx %1(0,%2),%0\";
}"
[(set_attr "type" "fpload")
- (set_attr "length" "8")])
+ (set_attr "length" "4")])
(define_insn ""
- [(set (mem:DF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 8))
+ [(set (mem:DF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
(match_operand:SI 2 "register_operand" "r")))
- (match_operand:DF 0 "register_operand" "f"))]
+ (match_operand:DF 0 "register_operand" "fx"))]
"! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
- "fstdx,s %0,%1(0,%2)"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"fstdx %0,%1(0,%2)\";
+ else
+ return \"fstdx %0,%2(0,%1)\";
+}"
[(set_attr "type" "fpstore")
(set_attr "length" "4")])
-;; This variant of the above insn can occur if the second operand
-;; is the frame pointer. This is a kludge, but there doesn't
-;; seem to be a way around it. Only recognize it while reloading.
-;; Note how operand 3 uses a predicate of "const_int_operand", but
-;; has constraints allowing a register. I don't know how this works,
-;; but it somehow makes sure that out-of-range constants are placed
-;; in a register which somehow magically is a "const_int_operand".
-;; (this was stolen from alpha.md, I'm not going to try and change it.
-;; Ugh. Output is a FP register; so we need to earlyclobber something
-;; else as a temporary.
(define_insn ""
- [(set (mem:DF (plus:SI
- (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "+&r")
- (const_int 8))
- (match_operand:SI 2 "register_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "rL")))
- (match_operand:DF 0 "register_operand" "f"))]
- "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress"
+ [(set (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r")))
+ (match_operand:DF 0 "register_operand" "fx"))]
+ "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
"*
{
- if (GET_CODE (operands[3]) == CONST_INT)
- return \"sh3addl %1,%2,%1\;fstds %0,%3(0,%1)\";
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"fstdx %0,%2(0,%1)\";
else
- return \"sh3addl %1,%2,%1\;fstdx %0,%3(0,%1)\";
+ return \"fstdx %0,%1(0,%2)\";
}"
[(set_attr "type" "fpstore")
- (set_attr "length" "8")])
+ (set_attr "length" "4")])
(define_expand "movdi"
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
@@ -2018,9 +2392,9 @@
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
- "=r,o,Q,&r,&r,&r,f,f,*T")
+ "=r,o,Q,r,r,r,f,f,*TR")
(match_operand:DI 1 "general_operand"
- "rM,r,r,o,Q,i,fM,*T,f"))]
+ "rM,r,r,o*R,Q,i,fM,*TR,f"))]
"(register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))
&& ! TARGET_SOFT_FLOAT"
@@ -2036,7 +2410,7 @@
(define_insn ""
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand"
- "=r,o,Q,&r,&r,&r")
+ "=r,o,Q,r,r,r")
(match_operand:DI 1 "general_operand"
"rM,r,r,o,Q,i"))]
"(register_operand (operands[0], DImode)
@@ -2077,13 +2451,13 @@
;; This must come before the movsf pattern, and it must be present
;; to handle obscure reloading cases.
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=?r,f")
+ [(set (match_operand:SF 0 "register_operand" "=?r,f")
(match_operand:SF 1 "" "?F,m"))]
"GET_CODE (operands[1]) == CONST_DOUBLE
&& operands[1] != CONST0_RTX (SFmode)
&& ! TARGET_SOFT_FLOAT"
"* return (which_alternative == 0 ? singlemove_string (operands)
- : \" fldws%F1 %1,%0\");"
+ : \" fldw%F1 %1,%0\");"
[(set_attr "type" "move,fpload")
(set_attr "length" "8,4")])
@@ -2132,27 +2506,28 @@
(define_insn ""
[(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand"
- "=f,r,f,r,Q,Q")
+ "=f,r,f,r,RQ,Q")
(match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
- "fG,rG,Q,Q,f,rG"))]
+ "fG,rG,RQ,RQ,f,rG"))]
"(register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode))
&& ! TARGET_SOFT_FLOAT"
"@
fcpy,sgl %r1,%0
copy %r1,%0
- fldws%F1 %1,%0
+ fldw%F1 %1,%0
ldw%M1 %1,%0
- fstws%F0 %r1,%0
+ fstw%F0 %r1,%0
stw%M0 %r1,%0"
[(set_attr "type" "fpalu,move,fpload,load,fpstore,store")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4,4,4,4,4")])
(define_insn ""
[(set (match_operand:SF 0 "reg_or_nonsymb_mem_operand"
"=r,r,Q")
(match_operand:SF 1 "reg_or_0_or_nonsymb_mem_operand"
- "rG,Q,rG"))]
+ "rG,RQ,rG"))]
"(register_operand (operands[0], SFmode)
|| reg_or_0_operand (operands[1], SFmode))
&& TARGET_SOFT_FLOAT"
@@ -2161,115 +2536,140 @@
ldw%M1 %1,%0
stw%M0 %r1,%0"
[(set_attr "type" "move,load,store")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4,4")])
(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- (mem:SF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 4))
+ [(set (match_operand:SF 0 "register_operand" "=fx")
+ (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
(match_operand:SI 2 "register_operand" "r"))))]
"! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
- "fldwx,s %1(0,%2),%0"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"fldwx %1(0,%2),%0\";
+ else
+ return \"fldwx %2(0,%1),%0\";
+}"
[(set_attr "type" "fpload")
(set_attr "length" "4")])
-;; This variant of the above insn can occur if the second operand
-;; is the frame pointer. This is a kludge, but there doesn't
-;; seem to be a way around it. Only recognize it while reloading.
-;; Note how operand 3 uses a predicate of "const_int_operand", but
-;; has constraints allowing a register. I don't know how this works,
-;; but it somehow makes sure that out-of-range constants are placed
-;; in a register which somehow magically is a "const_int_operand".
-;; (this was stolen from alpha.md, I'm not going to try and change it.
-;; Ugh. Output is a FP register; so we need to earlyclobber something
-;; else as a temporary.
(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=f")
- (mem:SF (plus:SI
- (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "+&r")
- (const_int 4))
- (match_operand:SI 2 "register_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "rL"))))]
- "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress"
+ [(set (match_operand:SF 0 "register_operand" "=fx")
+ (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r"))))]
+ "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
"*
{
- if (GET_CODE (operands[3]) == CONST_INT)
- return \"sh2addl %1,%2,%1\;fldws %3(0,%1),%0\";
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"fldwx %2(0,%1),%0\";
else
- return \"sh2addl %1,%2,%1\;fldwx %3(0,%1),%0\";
+ return \"fldwx %1(0,%2),%0\";
}"
[(set_attr "type" "fpload")
- (set_attr "length" "8")])
+ (set_attr "length" "4")])
(define_insn ""
- [(set (mem:SF (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- (const_int 4))
+ [(set (mem:SF (plus:SI (match_operand:SI 1 "basereg_operand" "r")
(match_operand:SI 2 "register_operand" "r")))
- (match_operand:SF 0 "register_operand" "f"))]
+ (match_operand:SF 0 "register_operand" "fx"))]
"! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
- "fstwx,s %0,%1(0,%2)"
+ "*
+{
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[2] == hard_frame_pointer_rtx
+ || operands[2] == stack_pointer_rtx)
+ return \"fstwx %0,%1(0,%2)\";
+ else
+ return \"fstwx %0,%2(0,%1)\";
+}"
[(set_attr "type" "fpstore")
(set_attr "length" "4")])
-
-;; This variant of the above insn can occur if the second operand
-;; is the frame pointer. This is a kludge, but there doesn't
-;; seem to be a way around it. Only recognize it while reloading.
-;; Note how operand 3 uses a predicate of "const_int_operand", but
-;; has constraints allowing a register. I don't know how this works,
-;; but it somehow makes sure that out-of-range constants are placed
-;; in a register which somehow magically is a "const_int_operand".
-;; (this was stolen from alpha.md, I'm not going to try and change it.
-;; Ugh. Output is a FP register; so we need to earlyclobber something
-;; else as a temporary.
+
(define_insn ""
- [(set (mem:SF (plus:SI
- (plus:SI
- (mult:SI (match_operand:SI 1 "register_operand" "+&r")
- (const_int 4))
- (match_operand:SI 2 "register_operand" "r"))
- (match_operand:SI 3 "const_int_operand" "rL")))
- (match_operand:SF 0 "register_operand" "f"))]
- "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT && reload_in_progress"
+ [(set (mem:SF (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "basereg_operand" "r")))
+ (match_operand:SF 0 "register_operand" "fx"))]
+ "! TARGET_DISABLE_INDEXING && ! TARGET_SOFT_FLOAT"
"*
{
- if (GET_CODE (operands[3]) == CONST_INT)
- return \"sh2addl %1,%2,%1\;fstws %0,%3(0,%1)\";
+ /* Reload can create backwards (relative to cse) unscaled index
+ address modes when eliminating registers and possibly for
+ pseudos that don't get hard registers. Deal with it. */
+ if (operands[1] == hard_frame_pointer_rtx
+ || operands[1] == stack_pointer_rtx)
+ return \"fstwx %0,%2(0,%1)\";
else
- return \"sh2addl %1,%2,%1\;fstwx %0,%3(0,%1)\";
+ return \"fstwx %0,%1(0,%2)\";
}"
[(set_attr "type" "fpstore")
- (set_attr "length" "8")])
+ (set_attr "length" "4")])
+
;;- zero extension instructions
+;; We have define_expand for zero extension patterns to make sure the
+;; operands get loaded into registers. The define_insns accept
+;; memory operands. This gives us better overall code than just
+;; having a pattern that does or does not accept memory operands.
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
+(define_expand "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI
- (match_operand:HI 1 "reg_or_nonsymb_mem_operand" "r,Q")))]
+ (match_operand:HI 1 "register_operand" "")))]
""
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI
+ (match_operand:HI 1 "move_operand" "r,RQ")))]
+ "GET_CODE (operands[1]) != CONST_INT"
"@
extru %1,31,16,%0
ldh%M1 %1,%0"
[(set_attr "type" "shift,load")
(set_attr "length" "4,4")])
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=r,r")
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
(zero_extend:HI
- (match_operand:QI 1 "reg_or_nonsymb_mem_operand" "r,Q")))]
+ (match_operand:QI 1 "register_operand" "")))]
""
+ "")
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (zero_extend:HI
+ (match_operand:QI 1 "move_operand" "r,RQ")))]
+ "GET_CODE (operands[1]) != CONST_INT"
"@
extru %1,31,8,%0
ldb%M1 %1,%0"
[(set_attr "type" "shift,load")
(set_attr "length" "4,4")])
-(define_insn "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
(zero_extend:SI
- (match_operand:QI 1 "reg_or_nonsymb_mem_operand" "r,Q")))]
+ (match_operand:QI 1 "register_operand" "")))]
""
+ "")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI
+ (match_operand:QI 1 "move_operand" "r,RQ")))]
+ "GET_CODE (operands[1]) != CONST_INT"
"@
extru %1,31,8,%0
ldb%M1 %1,%0"
@@ -2334,15 +2734,15 @@
;; to be reloaded by putting the constant into memory.
;; It must come before the more general floatsisf2 pattern.
(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:SI 1 "const_int_operand" "m")))]
"! TARGET_SOFT_FLOAT"
- "fldws %1,%0\;fcnvxf,sgl,sgl %0,%0"
+ "fldw%F1 %1,%0\;fcnvxf,sgl,sgl %0,%0"
[(set_attr "type" "fpalu")
(set_attr "length" "8")])
(define_insn "floatsisf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:SI 1 "register_operand" "f")))]
"! TARGET_SOFT_FLOAT"
"fcnvxf,sgl,sgl %1,%0"
@@ -2353,15 +2753,15 @@
;; to be reloaded by putting the constant into memory.
;; It must come before the more general floatsidf2 pattern.
(define_insn ""
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "register_operand" "=f")
(float:DF (match_operand:SI 1 "const_int_operand" "m")))]
"! TARGET_SOFT_FLOAT"
- "fldws %1,%0\;fcnvxf,sgl,dbl %0,%0"
+ "fldw%F1 %1,%0\;fcnvxf,sgl,dbl %0,%0"
[(set_attr "type" "fpalu")
(set_attr "length" "8")])
(define_insn "floatsidf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "register_operand" "=f")
(float:DF (match_operand:SI 1 "register_operand" "f")))]
"! TARGET_SOFT_FLOAT"
"fcnvxf,sgl,dbl %1,%0"
@@ -2373,7 +2773,7 @@
(match_operand:SI 1 "register_operand" ""))
(set (subreg:SI (match_dup 2) 0)
(const_int 0))
- (set (match_operand:SF 0 "general_operand" "")
+ (set (match_operand:SF 0 "register_operand" "")
(float:SF (match_dup 2)))]
"TARGET_SNAKE && ! TARGET_SOFT_FLOAT"
"operands[2] = gen_reg_rtx (DImode);")
@@ -2383,13 +2783,13 @@
(match_operand:SI 1 "register_operand" ""))
(set (subreg:SI (match_dup 2) 0)
(const_int 0))
- (set (match_operand:DF 0 "general_operand" "")
+ (set (match_operand:DF 0 "register_operand" "")
(float:DF (match_dup 2)))]
"TARGET_SNAKE && ! TARGET_SOFT_FLOAT"
"operands[2] = gen_reg_rtx (DImode);")
(define_insn "floatdisf2"
- [(set (match_operand:SF 0 "general_operand" "=f")
+ [(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:DI 1 "register_operand" "f")))]
"TARGET_SNAKE && ! TARGET_SOFT_FLOAT"
"fcnvxf,dbl,sgl %1,%0"
@@ -2397,7 +2797,7 @@
(set_attr "length" "4")])
(define_insn "floatdidf2"
- [(set (match_operand:DF 0 "general_operand" "=f")
+ [(set (match_operand:DF 0 "register_operand" "=f")
(float:DF (match_operand:DI 1 "register_operand" "f")))]
"TARGET_SNAKE && ! TARGET_SOFT_FLOAT"
"fcnvxf,dbl,dbl %1,%0"
@@ -2506,7 +2906,10 @@
/* Try dividing the constant by 2, then 4, and finally 8 to see
if we can get a constant which can be loaded into a register
- in a single instruction (cint_ok_for_move). */
+ in a single instruction (cint_ok_for_move).
+
+ If that fails, try to negate the constant and subtract it
+ from our input operand. */
if (intval % 2 == 0 && cint_ok_for_move (intval / 2))
{
operands[2] = GEN_INT (intval / 2);
@@ -2522,6 +2925,12 @@
operands[2] = GEN_INT (intval / 8);
operands[3] = GEN_INT (8);
}
+ else if (cint_ok_for_move (-intval))
+ {
+ emit_insn (gen_rtx (SET, VOIDmode, operands[4], GEN_INT (-intval)));
+ emit_insn (gen_subsi3 (operands[0], operands[1], operands[4]));
+ DONE;
+ }
else
FAIL;
}")
@@ -2535,6 +2944,7 @@
addl %1,%2,%0
ldo %2(%1),%0"
[(set_attr "type" "binary,binary")
+ (set_attr "pa_combine_type" "addmove")
(set_attr "length" "4,4")])
;; Disgusting kludge to work around reload bugs with frame pointer
@@ -2635,12 +3045,29 @@
"* return output_mul_insn (0, insn);"
[(set_attr "type" "milli")
(set (attr "length")
- (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
- (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
- (const_int 0)))
- (const_int 4)
- (const_int 24)))])
+ (cond [
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 4)
+
+;; NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 8)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+;; same as NO_SPACE_REGS code
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 8)]
+
+;; Out of range and either PIC or PORTABLE_RUNTIME
+ (const_int 24)))])
;;; Division and mod.
(define_expand "divsi3"
@@ -2672,12 +3099,29 @@
return output_div_insn (operands, 0, insn);"
[(set_attr "type" "milli")
(set (attr "length")
- (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
- (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
- (const_int 0)))
- (const_int 4)
- (const_int 24)))])
+ (cond [
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 4)
+
+;; NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 8)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+;; same as NO_SPACE_REGS code
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 8)]
+
+;; Out of range and either PIC or PORTABLE_RUNTIME
+ (const_int 24)))])
(define_expand "udivsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
@@ -2708,12 +3152,29 @@
return output_div_insn (operands, 1, insn);"
[(set_attr "type" "milli")
(set (attr "length")
- (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
- (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
- (const_int 0)))
- (const_int 4)
- (const_int 24)))])
+ (cond [
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 4)
+
+;; NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 8)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+;; same as NO_SPACE_REGS code
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 8)]
+
+;; Out of range and either PIC or PORTABLE_RUNTIME
+ (const_int 24)))])
(define_expand "modsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
@@ -2741,12 +3202,29 @@
return output_mod_insn (0, insn);"
[(set_attr "type" "milli")
(set (attr "length")
- (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
- (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
- (const_int 0)))
- (const_int 4)
- (const_int 24)))])
+ (cond [
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 4)
+
+;; NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 8)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+;; same as NO_SPACE_REGS code
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 8)]
+
+;; Out of range and either PIC or PORTABLE_RUNTIME
+ (const_int 24)))])
(define_expand "umodsi3"
[(set (reg:SI 26) (match_operand:SI 1 "move_operand" ""))
@@ -2774,12 +3252,29 @@
return output_mod_insn (1, insn);"
[(set_attr "type" "milli")
(set (attr "length")
- (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
- (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
- (const_int 0)))
- (const_int 4)
- (const_int 24)))])
+ (cond [
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 4)
+
+;; NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 8)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+;; same as NO_SPACE_REGS code
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 8)]
+
+;; Out of range and either PIC or PORTABLE_RUNTIME
+ (const_int 24)))])
;;- and instructions
;; We define DImode `and` so with DImode `not` we can get
@@ -2970,6 +3465,7 @@
"! TARGET_SOFT_FLOAT"
"fadd,dbl %1,%2,%0"
[(set_attr "type" "fpalu")
+ (set_attr "pa_combine_type" "faddsub")
(set_attr "length" "4")])
(define_insn "addsf3"
@@ -2979,6 +3475,7 @@
"! TARGET_SOFT_FLOAT"
"fadd,sgl %1,%2,%0"
[(set_attr "type" "fpalu")
+ (set_attr "pa_combine_type" "faddsub")
(set_attr "length" "4")])
(define_insn "subdf3"
@@ -2988,6 +3485,7 @@
"! TARGET_SOFT_FLOAT"
"fsub,dbl %1,%2,%0"
[(set_attr "type" "fpalu")
+ (set_attr "pa_combine_type" "faddsub")
(set_attr "length" "4")])
(define_insn "subsf3"
@@ -2997,6 +3495,7 @@
"! TARGET_SOFT_FLOAT"
"fsub,sgl %1,%2,%0"
[(set_attr "type" "fpalu")
+ (set_attr "pa_combine_type" "faddsub")
(set_attr "length" "4")])
(define_insn "muldf3"
@@ -3006,6 +3505,7 @@
"! TARGET_SOFT_FLOAT"
"fmpy,dbl %1,%2,%0"
[(set_attr "type" "fpmuldbl")
+ (set_attr "pa_combine_type" "fmpy")
(set_attr "length" "4")])
(define_insn "mulsf3"
@@ -3015,6 +3515,7 @@
"! TARGET_SOFT_FLOAT"
"fmpy,sgl %1,%2,%0"
[(set_attr "type" "fpmulsgl")
+ (set_attr "pa_combine_type" "fmpy")
(set_attr "length" "4")])
(define_insn "divdf3"
@@ -3300,19 +3801,6 @@
[(set_attr "type" "shift")
(set_attr "length" "4")])
-(define_insn "rotlsi3"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (rotate:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "const_int_operand" "n")))]
- ""
- "*
-{
- operands[2] = GEN_INT ((32 - INTVAL (operands[2])) & 31);
- return \"shd %1,%1,%2,%0\";
-}"
- [(set_attr "type" "shift")
- (set_attr "length" "4")])
-
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 5 "plus_xor_ior_operator"
@@ -3421,18 +3909,75 @@
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
- "bl%* %l0,0"
+ "*
+{
+ extern int optimize;
+ /* An unconditional branch which can reach its target. */
+ if (get_attr_length (insn) != 24
+ && get_attr_length (insn) != 16)
+ return \"bl%* %l0,0\";
+
+ /* An unconditional branch which can not reach its target.
+
+ We need to be able to use %r1 as a scratch register; however,
+ we can never be sure whether or not it's got a live value in
+ it. Therefore, we must restore its original value after the
+ jump.
+
+ To make matters worse, we don't have a stack slot which we
+ can always clobber. sp-12/sp-16 shouldn't ever have a live
+ value during a non-optimizing compilation, so we use those
+ slots for now. We don't support very long branches when
+ optimizing -- they should be quite rare when optimizing.
+
+ Really the way to go long term is a register scavenger; goto
+ the target of the jump and find a register which we can use
+ as a scratch to hold the value in %r1. */
+
+ /* We don't know how to register scavenge yet. */
+ if (optimize)
+ abort ();
+
+ /* First store %r1 into the stack. */
+ output_asm_insn (\"stw %%r1,-16(%%r30)\", operands);
+
+ /* Now load the target address into %r1 and do an indirect jump
+ to the value specified in %r1. Be careful to generate PIC
+ code as needed. */
+ if (flag_pic)
+ {
+ rtx xoperands[2];
+ xoperands[0] = operands[0];
+ xoperands[1] = gen_label_rtx ();
+
+ output_asm_insn (\"bl .+8,%%r1\\n\\taddil L'%l0-%l1,%%r1\", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xoperands[1]));
+ output_asm_insn (\"ldo R'%l0-%l1(%%r1),%%r1\\n\\tbv 0(%%r1)\",
+ xoperands);
+ }
+ else
+ output_asm_insn (\"ldil L'%l0,%%r1\\n\\tbe R'%l0(%%sr4,%%r1)\", operands);;
+
+ /* And restore the value of %r1 in the delay slot. We're not optimizing,
+ so we know nothing else can be in the delay slot. */
+ return \"ldw -16(%%r30),%%r1\";
+}"
[(set_attr "type" "uncond_branch")
+ (set_attr "pa_combine_type" "uncond_branch")
(set (attr "length")
- (cond [(eq (symbol_ref "jump_in_call_delay (insn)") (const_int 0))
- (const_int 4)
-;; If the jump is in the delay slot of a call, then its length depends
-;; on whether or not we can add the proper offset to %r2 with an ldo
-;; instruction.
- (lt (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
- (const_int 8188))
- (const_int 4)]
- (const_int 8)))])
+ (cond [(eq (symbol_ref "jump_in_call_delay (insn)") (const_int 1))
+ (if_then_else (lt (abs (minus (match_dup 0)
+ (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8))
+ (ge (abs (minus (match_dup 0) (plus (pc) (const_int 8))))
+ (const_int 262100))
+ (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
+ (const_int 16)
+ (const_int 24))]
+ (const_int 4)))])
;; Subroutines of "casesi".
;; operand 0 is index
@@ -3465,37 +4010,29 @@
operands[0] = reg;
}
- if (!INT_11_BITS (operands[2]))
+ if (!INT_5_BITS (operands[2]))
operands[2] = force_reg (SImode, operands[2]);
- emit_jump_insn (gen_casesi0 (operands[0], operands[2],
- operands[3], operands[4]));
+ emit_insn (gen_cmpsi (operands[0], operands[2]));
+ emit_jump_insn (gen_bgtu (operands[4]));
+ if (TARGET_BIG_SWITCH)
+ {
+ rtx temp = gen_reg_rtx (SImode);
+ emit_move_insn (temp, gen_rtx (PLUS, SImode, operands[0], operands[0]));
+ operands[0] = temp;
+ }
+ emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
DONE;
}")
(define_insn "casesi0"
- [(set (pc)
- (if_then_else (leu (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "arith11_operand" "rI"))
- (plus:SI (mem:SI (plus:SI (pc) (match_dup 0)))
- (label_ref (match_operand 2 "" "")))
- (pc)))
- (use (label_ref (match_operand 3 "" "")))]
+ [(set (pc) (plus:SI
+ (mem:SI (plus:SI (pc) (match_operand 0 "register_operand" "r")))
+ (label_ref (match_operand 1 "" ""))))]
""
- "*
-{
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- operands[1] = GEN_INT (~INTVAL (operands[1]));
- return \"addi,uv %1,%0,0\;blr,n %0,0\;b,n %l3\";
- }
- else
- {
- return \"sub,>> %0,%1,0\;blr,n %0,0\;b,n %l3\";
- }
-}"
+ "blr %0,0\;nop"
[(set_attr "type" "multi")
- (set_attr "length" "12")])
+ (set_attr "length" "8")])
;; Need nops for the calls because execution is supposed to continue
;; past; we don't want to nullify an instruction that we need.
@@ -3524,8 +4061,11 @@
if (GET_CODE (op) == SYMBOL_REF)
call_insn = emit_call_insn (gen_call_internal_symref (op, operands[1]));
else
- call_insn = emit_call_insn (gen_call_internal_reg (force_reg (SImode, op),
- operands[1]));
+ {
+ rtx tmpreg = gen_rtx (REG, SImode, 22);
+ emit_move_insn (tmpreg, force_reg (SImode, op));
+ call_insn = emit_call_insn (gen_call_internal_reg (operands[1]));
+ }
if (flag_pic)
{
@@ -3539,6 +4079,16 @@
emit_move_insn (pic_offset_table_rtx,
gen_rtx (REG, SImode, PIC_OFFSET_TABLE_REGNUM_SAVED));
emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
+
+ /* Gross. We have to keep the scheduler from moving the restore
+ of the PIC register away from the call. SCHED_GROUP_P is
+ supposed to do this, but for some reason the compiler will
+ go into an infinite loop when we use that.
+
+ This method (blockage insn) may make worse code (then again
+ it may not since calls are nearly blockages anyway), but at
+ least it should work. */
+ emit_insn (gen_blockage ());
}
DONE;
}")
@@ -3556,39 +4106,91 @@
}"
[(set_attr "type" "call")
(set (attr "length")
+;; If we're sure that we can either reach the target or that the
+;; linker can use a long-branch stub, then the length is 4 bytes.
+;;
+;; For long-calls the length will be either 52 bytes (non-pic)
+;; or 68 bytes (pic). */
+;; Else we have to use a long-call;
(if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc))
(const_int 240000))
(const_int 4)
- (if_then_else (ne (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
+ (if_then_else (eq (symbol_ref "flag_pic")
(const_int 0))
- (const_int 64)
- (const_int 52))))])
+ (const_int 52)
+ (const_int 68))))])
(define_insn "call_internal_reg"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "r"))
- (match_operand 1 "" "i"))
+ [(call (mem:SI (reg:SI 22))
+ (match_operand 0 "" "i"))
(clobber (reg:SI 2))
(use (const_int 1))]
""
"*
{
- if (TARGET_FAST_INDIRECT_CALLS)
- return \"ble 0(%%sr4,%r0)\;copy %%r31,%%r2\";
+ rtx xoperands[2];
- /* Yuk! bl may not be able to reach $$dyncall. */
- if (TARGET_PORTABLE_RUNTIME || TARGET_MILLICODE_LONG_CALLS)
- return \"copy %r0,%%r22\;ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\";
- else
- return \"copy %r0,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\";
+ /* First the special case for kernels, level 0 systems, etc. */
+ if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS)
+ return \"ble 0(%%sr4,%%r22)\;copy %%r31,%%r2\";
+
+ /* Now the normal case -- we can reach $$dyncall directly or
+ we're sure that we can get there via a long-branch stub.
+
+ No need to check target flags as the length uniquely identifies
+ the remaining cases. */
+ if (get_attr_length (insn) == 8)
+ return \".CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\";
+
+ /* Long millicode call, but we are not generating PIC or portable runtime
+ code. */
+ if (get_attr_length (insn) == 12)
+ return \".CALL\\tARGW0=GR\;ldil L%%$$dyncall,%%r2\;ble R%%$$dyncall(%%sr4,%%r2)\;copy %%r31,%%r2\";
+
+ /* Long millicode call for portable runtime. */
+ if (get_attr_length (insn) == 20)
+ return \"ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\";
+
+ /* If we're generating PIC code. */
+ xoperands[0] = operands[0];
+ xoperands[1] = gen_label_rtx ();
+ output_asm_insn (\"bl .+8,%%r1\", xoperands);
+ output_asm_insn (\"addil L%%$$dyncall-%1,%%r1\", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xoperands[1]));
+ output_asm_insn (\"ldo R%%$$dyncall-%1(%%r1),%%r1\", xoperands);
+ output_asm_insn (\"blr 0,%%r2\", xoperands);
+ output_asm_insn (\"bv,n 0(%%r1)\\n\\tnop\", xoperands);
+ return \"\";
}"
[(set_attr "type" "dyncall")
(set (attr "length")
- (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
- (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
- (const_int 0)))
- (const_int 12)
- (const_int 24)))])
+ (cond [
+;; First NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 8)
+
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 8)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 12)
+
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (const_int 20)]
+
+;; Out of range PIC case
+ (const_int 24)))])
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
@@ -3616,10 +4218,12 @@
op,
operands[2]));
else
- call_insn = emit_call_insn (gen_call_value_internal_reg (operands[0],
- force_reg (SImode, op),
- operands[2]));
-
+ {
+ rtx tmpreg = gen_rtx (REG, SImode, 22);
+ emit_move_insn (tmpreg, force_reg (SImode, op));
+ call_insn = emit_call_insn (gen_call_value_internal_reg (operands[0],
+ operands[2]));
+ }
if (flag_pic)
{
use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx);
@@ -3642,16 +4246,6 @@
it may not since calls are nearly blockages anyway), but at
least it should work. */
emit_insn (gen_blockage ());
-
- /* Gross. We have to keep the scheduler from moving the restore
- of the PIC register away from the call. SCHED_GROUP_P is
- supposed to do this, but for some reason the compiler will
- go into an infinite loop when we use that.
-
- This method (blockage insn) may make worse code (then again
- it may not since calls are nearly blockages anyway), but at
- least it should work. */
- emit_insn (gen_blockage ());
}
DONE;
}")
@@ -3671,40 +4265,92 @@
}"
[(set_attr "type" "call")
(set (attr "length")
+;; If we're sure that we can either reach the target or that the
+;; linker can use a long-branch stub, then the length is 4 bytes.
+;;
+;; For long-calls the length will be either 52 bytes (non-pic)
+;; or 68 bytes (pic). */
+;; Else we have to use a long-call;
(if_then_else (lt (plus (symbol_ref "total_code_bytes") (pc))
(const_int 240000))
(const_int 4)
- (if_then_else (ne (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
+ (if_then_else (eq (symbol_ref "flag_pic")
(const_int 0))
- (const_int 64)
- (const_int 52))))])
+ (const_int 52)
+ (const_int 68))))])
(define_insn "call_value_internal_reg"
[(set (match_operand 0 "" "=rf")
- (call (mem:SI (match_operand:SI 1 "register_operand" "r"))
- (match_operand 2 "" "i")))
+ (call (mem:SI (reg:SI 22))
+ (match_operand 1 "" "i")))
(clobber (reg:SI 2))
(use (const_int 1))]
""
"*
{
- if (TARGET_FAST_INDIRECT_CALLS)
- return \"ble 0(%%sr4,%r1)\;copy %%r31,%%r2\";
-
- /* Yuk! bl may not be able to reach $$dyncall. */
- if (TARGET_PORTABLE_RUNTIME || TARGET_MILLICODE_LONG_CALLS)
- return \"copy %r1,%%r22\;ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\";
- else
- return \"copy %r1,%%r22\;.CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\";
+ rtx xoperands[2];
+
+ /* First the special case for kernels, level 0 systems, etc. */
+ if (TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS)
+ return \"ble 0(%%sr4,%%r22)\;copy %%r31,%%r2\";
+
+ /* Now the normal case -- we can reach $$dyncall directly or
+ we're sure that we can get there via a long-branch stub.
+
+ No need to check target flags as the length uniquely identifies
+ the remaining cases. */
+ if (get_attr_length (insn) == 8)
+ return \".CALL\\tARGW0=GR\;bl $$dyncall,%%r31\;copy %%r31,%%r2\";
+
+ /* Long millicode call, but we are not generating PIC or portable runtime
+ code. */
+ if (get_attr_length (insn) == 12)
+ return \".CALL\\tARGW0=GR\;ldil L%%$$dyncall,%%r2\;ble R%%$$dyncall(%%sr4,%%r2)\;copy %%r31,%%r2\";
+
+ /* Long millicode call for portable runtime. */
+ if (get_attr_length (insn) == 20)
+ return \"ldil L%%$$dyncall,%%r31\;ldo R%%$$dyncall(%%r31),%%r31\;blr 0,%%r2\;bv,n 0(%%r31)\;nop\";
+
+ /* If we're generating PIC code. */
+ xoperands[0] = operands[1];
+ xoperands[1] = gen_label_rtx ();
+ output_asm_insn (\"bl .+8,%%r1\", xoperands);
+ output_asm_insn (\"addil L%%$$dyncall-%1,%%r1\", xoperands);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (xoperands[1]));
+ output_asm_insn (\"ldo R%%$$dyncall-%1(%%r1),%%r1\", xoperands);
+ output_asm_insn (\"blr 0,%%r2\", xoperands);
+ output_asm_insn (\"bv,n 0(%%r1)\\n\\tnop\", xoperands);
+ return \"\";
}"
[(set_attr "type" "dyncall")
(set (attr "length")
- (if_then_else (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
- (const_int 0))
- (eq (symbol_ref "TARGET_MILLICODE_LONG_CALLS")
- (const_int 0)))
- (const_int 12)
- (const_int 24)))])
+ (cond [
+;; First NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 8)
+
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 8)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 12)
+
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (const_int 20)]
+
+;; Out of range PIC case
+ (const_int 24)))])
;; Call subroutine returning any type.
@@ -3741,6 +4387,36 @@
[(set_attr "type" "move")
(set_attr "length" "4")])
+;; These are just placeholders so we know where branch tables
+;; begin and end.
+(define_insn "begin_brtab"
+ [(const_int 1)]
+ ""
+ "*
+{
+ /* Only GAS actually supports this pseudo-op. */
+ if (TARGET_GAS)
+ return \".begin_brtab\";
+ else
+ return \"\";
+}"
+ [(set_attr "type" "move")
+ (set_attr "length" "0")])
+
+(define_insn "end_brtab"
+ [(const_int 2)]
+ ""
+ "*
+{
+ /* Only GAS actually supports this pseudo-op. */
+ if (TARGET_GAS)
+ return \".end_brtab\";
+ else
+ return \"\";
+}"
+ [(set_attr "type" "move")
+ (set_attr "length" "0")])
+
;;; Hope this is only within a function...
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
@@ -3845,7 +4521,7 @@
;; Short branch has length of 4
;; Long branch has length of 8
(if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 4)
(const_int 8))
@@ -3855,12 +4531,12 @@
(if_then_else (lt (match_dup 3) (pc))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
- (const_int 8188))
+ (const_int 8184))
(const_int 24)
(const_int 28))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 24)
(const_int 28)))
;; Loop counter in memory case.
@@ -3868,68 +4544,12 @@
(if_then_else (lt (match_dup 3) (pc))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8188))
+ (const_int 8184))
(const_int 12)
(const_int 16))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
- (const_int 12)
- (const_int 16))))))])
-
-;; Simply another variant of the dbra pattern. More restrictive
-;; in testing the comparison operator as it must worry about overflow
-;; problems.
-(define_insn ""
- [(set (pc)
- (if_then_else
- (match_operator 2 "eq_neq_comparison_operator"
- [(match_operand:SI 0 "register_operand" "+!r,!*f,!*m")
- (match_operand:SI 5 "const_int_operand" "")])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 1 "int5_operand" "L,L,L")))
- (clobber (match_scratch:SI 4 "=X,r,r"))]
- "INTVAL (operands[5]) == - INTVAL (operands[1])"
-"* return output_dbra (operands, insn, which_alternative);"
-;; Do not expect to understand this the first time through.
-[(set_attr "type" "cbranch,multi,multi")
- (set (attr "length")
- (if_then_else (eq_attr "alternative" "0")
-;; Loop counter in register case
-;; Short branch has length of 4
-;; Long branch has length of 8
- (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
- (const_int 4)
- (const_int 8))
-
-;; Loop counter in FP reg case.
-;; Extra goo to deal with additional reload insns.
- (if_then_else (eq_attr "alternative" "1")
- (if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 24))))
- (const_int 8188))
- (const_int 24)
- (const_int 28))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
- (const_int 24)
- (const_int 28)))
-;; Loop counter in memory case.
-;; Extra goo to deal with additional reload insns.
- (if_then_else (lt (match_dup 3) (pc))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8188))
- (const_int 12)
- (const_int 16))
- (if_then_else
- (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 12)
(const_int 16))))))])
@@ -3937,22 +4557,22 @@
[(set (pc)
(if_then_else
(match_operator 2 "movb_comparison_operator"
- [(match_operand:SI 1 "register_operand" "r,r,r") (const_int 0)])
+ [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)])
(label_ref (match_operand 3 "" ""))
(pc)))
- (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m")
+ (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m,!*q")
(match_dup 1))]
""
"* return output_movb (operands, insn, which_alternative, 0); "
;; Do not expect to understand this the first time through.
-[(set_attr "type" "cbranch,multi,multi")
+[(set_attr "type" "cbranch,multi,multi,multi")
(set (attr "length")
(if_then_else (eq_attr "alternative" "0")
;; Loop counter in register case
;; Short branch has length of 4
;; Long branch has length of 8
(if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 4)
(const_int 8))
@@ -3962,19 +4582,19 @@
(if_then_else (lt (match_dup 3) (pc))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8188))
+ (const_int 8184))
(const_int 12)
(const_int 16))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 12)
(const_int 16)))
-;; Loop counter in memory case.
+;; Loop counter in memory or sar case.
;; Extra goo to deal with additional reload insns.
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 8)
(const_int 12)))))])
@@ -3983,22 +4603,22 @@
[(set (pc)
(if_then_else
(match_operator 2 "movb_comparison_operator"
- [(match_operand:SI 1 "register_operand" "r,r,r") (const_int 0)])
+ [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)])
(pc)
(label_ref (match_operand 3 "" ""))))
- (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m")
+ (set (match_operand:SI 0 "register_operand" "=!r,!*f,!*m,!*q")
(match_dup 1))]
""
"* return output_movb (operands, insn, which_alternative, 1); "
;; Do not expect to understand this the first time through.
-[(set_attr "type" "cbranch,multi,multi")
+[(set_attr "type" "cbranch,multi,multi,multi")
(set (attr "length")
(if_then_else (eq_attr "alternative" "0")
;; Loop counter in register case
;; Short branch has length of 4
;; Long branch has length of 8
(if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 4)
(const_int 8))
@@ -4008,62 +4628,146 @@
(if_then_else (lt (match_dup 3) (pc))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 12))))
- (const_int 8188))
+ (const_int 8184))
(const_int 12)
(const_int 16))
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 12)
(const_int 16)))
-;; Loop counter in memory case.
+;; Loop counter in memory or SAR case.
;; Extra goo to deal with additional reload insns.
(if_then_else
(lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
- (const_int 8188))
+ (const_int 8184))
(const_int 8)
(const_int 12)))))])
-;; The next four peepholes take advantage of the new 5 operand
-;; fmpy{add,sub} instructions available on 1.1 CPUS. Basically
-;; fmpyadd performs a multiply and add/sub of independent operands
-;; at the same time. Because the operands must be independent
-;; combine will not try to combine such insns... Thus we have
-;; to use a peephole.
-(define_peephole
+;; The next several patterns (parallel_addb, parallel_movb, fmpyadd and
+;; fmpysub aren't currently used by the FSF sources, but will be soon.
+;;
+;; They're in the FSF tree for documentation and to make Cygnus<->FSF
+;; merging easier.
+(define_insn ""
+ [(set (pc) (label_ref (match_operand 3 "" "" )))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "ireg_or_int5_operand" "rL")))]
+ "reload_completed && operands[0] == operands[1] || operands[0] == operands[2]"
+ "*
+{
+ return output_parallel_addb (operands, get_attr_length (insn));
+}"
+ [(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 3) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (pc) (label_ref (match_operand 2 "" "" )))
+ (set (match_operand:SF 0 "register_operand" "=r")
+ (match_operand:SF 1 "ireg_or_int5_operand" "rL"))]
+ "reload_completed"
+ "*
+{
+ return output_parallel_movb (operands, get_attr_length (insn));
+}"
+ [(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (pc) (label_ref (match_operand 2 "" "" )))
+ (set (match_operand:SI 0 "register_operand" "=r")
+ (match_operand:SI 1 "ireg_or_int5_operand" "rL"))]
+ "reload_completed"
+ "*
+{
+ return output_parallel_movb (operands, get_attr_length (insn));
+}"
+ [(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (pc) (label_ref (match_operand 2 "" "" )))
+ (set (match_operand:HI 0 "register_operand" "=r")
+ (match_operand:HI 1 "ireg_or_int5_operand" "rL"))]
+ "reload_completed"
+ "*
+{
+ return output_parallel_movb (operands, get_attr_length (insn));
+}"
+ [(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
+ [(set (pc) (label_ref (match_operand 2 "" "" )))
+ (set (match_operand:QI 0 "register_operand" "=r")
+ (match_operand:QI 1 "ireg_or_int5_operand" "rL"))]
+ "reload_completed"
+ "*
+{
+ return output_parallel_movb (operands, get_attr_length (insn));
+}"
+ [(set_attr "type" "parallel_branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (match_dup 2) (plus (pc) (const_int 8))))
+ (const_int 8184))
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn ""
[(set (match_operand 0 "register_operand" "=f")
(mult (match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")))
(set (match_operand 3 "register_operand" "+f")
(plus (match_operand 4 "register_operand" "f")
(match_operand 5 "register_operand" "f")))]
- "TARGET_SNAKE && fmpyaddoperands (operands)"
+ "TARGET_SNAKE && ! TARGET_SOFT_FLOAT
+ && reload_completed && fmpyaddoperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
{
- if (rtx_equal_p (operands[5], operands[3]))
+ if (rtx_equal_p (operands[3], operands[5]))
return \"fmpyadd,dbl %1,%2,%0,%4,%3\";
else
return \"fmpyadd,dbl %1,%2,%0,%5,%3\";
}
else
{
- if (rtx_equal_p (operands[5], operands[3]))
+ if (rtx_equal_p (operands[3], operands[5]))
return \"fmpyadd,sgl %1,%2,%0,%4,%3\";
else
return \"fmpyadd,sgl %1,%2,%0,%5,%3\";
}
-}")
+}"
+ [(set_attr "type" "fpalu")
+ (set_attr "length" "4")])
-(define_peephole
+(define_insn ""
[(set (match_operand 3 "register_operand" "+f")
(plus (match_operand 4 "register_operand" "f")
(match_operand 5 "register_operand" "f")))
(set (match_operand 0 "register_operand" "=f")
(mult (match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")))]
- "TARGET_SNAKE && fmpyaddoperands (operands)"
+ "TARGET_SNAKE && ! TARGET_SOFT_FLOAT
+ && reload_completed && fmpyaddoperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
@@ -4080,40 +4784,124 @@
else
return \"fmpyadd,sgl %1,%2,%0,%5,%3\";
}
-}")
+}"
+ [(set_attr "type" "fpalu")
+ (set_attr "length" "4")])
-;; Note fsub subtracts the second operand from the first while fmpysub
-;; does the opposite for the subtraction operands!
-(define_peephole
+(define_insn ""
[(set (match_operand 0 "register_operand" "=f")
(mult (match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")))
(set (match_operand 3 "register_operand" "+f")
(minus (match_operand 4 "register_operand" "f")
(match_operand 5 "register_operand" "f")))]
- "TARGET_SNAKE && fmpysuboperands (operands)"
+ "TARGET_SNAKE && ! TARGET_SOFT_FLOAT
+ && reload_completed && fmpysuboperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
return \"fmpysub,dbl %1,%2,%0,%5,%3\";
else
return \"fmpysub,sgl %1,%2,%0,%5,%3\";
-}")
+}"
+ [(set_attr "type" "fpalu")
+ (set_attr "length" "4")])
-(define_peephole
+(define_insn ""
[(set (match_operand 3 "register_operand" "+f")
(minus (match_operand 4 "register_operand" "f")
(match_operand 5 "register_operand" "f")))
(set (match_operand 0 "register_operand" "=f")
(mult (match_operand 1 "register_operand" "f")
(match_operand 2 "register_operand" "f")))]
- "TARGET_SNAKE && fmpysuboperands (operands)"
+ "TARGET_SNAKE && ! TARGET_SOFT_FLOAT
+ && reload_completed && fmpysuboperands (operands)"
"*
{
if (GET_MODE (operands[0]) == DFmode)
return \"fmpysub,dbl %1,%2,%0,%5,%3\";
else
return \"fmpysub,sgl %1,%2,%0,%5,%3\";
+}"
+ [(set_attr "type" "fpalu")
+ (set_attr "length" "4")])
+
+;; Clean up turds left by reload.
+(define_peephole
+ [(set (match_operand 0 "reg_or_nonsymb_mem_operand" "")
+ (match_operand 1 "register_operand" "fr"))
+ (set (match_operand 2 "register_operand" "fr")
+ (match_dup 0))]
+ "! TARGET_SOFT_FLOAT
+ && GET_CODE (operands[0]) == MEM
+ && ! MEM_VOLATILE_P (operands[0])
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE (operands[0]) == GET_MODE (operands[2])
+ && GET_MODE (operands[0]) == DFmode
+ && GET_CODE (operands[1]) == REG
+ && GET_CODE (operands[2]) == REG
+ && ! side_effects_p (XEXP (operands[0], 0))
+ && REGNO_REG_CLASS (REGNO (operands[1]))
+ == REGNO_REG_CLASS (REGNO (operands[2]))"
+ "*
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx xoperands[2];
+
+ if (FP_REG_P (operands[1]))
+ output_asm_insn (output_fp_move_double (operands), operands);
+ else
+ output_asm_insn (output_move_double (operands), operands);
+
+ if (rtx_equal_p (operands[1], operands[2]))
+ return \"\";
+
+ xoperands[0] = operands[2];
+ xoperands[1] = operands[1];
+
+ if (FP_REG_P (xoperands[1]))
+ output_asm_insn (output_fp_move_double (xoperands), xoperands);
+ else
+ output_asm_insn (output_move_double (xoperands), xoperands);
+
+ return \"\";
+}")
+
+(define_peephole
+ [(set (match_operand 0 "register_operand" "fr")
+ (match_operand 1 "reg_or_nonsymb_mem_operand" ""))
+ (set (match_operand 2 "register_operand" "fr")
+ (match_dup 1))]
+ "! TARGET_SOFT_FLOAT
+ && GET_CODE (operands[1]) == MEM
+ && ! MEM_VOLATILE_P (operands[1])
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE (operands[0]) == GET_MODE (operands[2])
+ && GET_MODE (operands[0]) == DFmode
+ && GET_CODE (operands[0]) == REG
+ && GET_CODE (operands[2]) == REG
+ && ! side_effects_p (XEXP (operands[1], 0))
+ && REGNO_REG_CLASS (REGNO (operands[0]))
+ == REGNO_REG_CLASS (REGNO (operands[2]))"
+ "*
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ rtx xoperands[2];
+
+ if (FP_REG_P (operands[0]))
+ output_asm_insn (output_fp_move_double (operands), operands);
+ else
+ output_asm_insn (output_move_double (operands), operands);
+
+ xoperands[0] = operands[2];
+ xoperands[1] = operands[0];
+
+ if (FP_REG_P (xoperands[1]))
+ output_asm_insn (output_fp_move_double (xoperands), xoperands);
+ else
+ output_asm_insn (output_move_double (xoperands), xoperands);
+
+ return \"\";
}")
;; Flush the I and D cache line found at the address in operand 0.
@@ -4141,3 +4929,231 @@
"mfsp %%sr0,%4\;ldsid (0,%2),%3\;mtsp %3,%%sr0\;fic 0(%%sr0,%0)\;fic 0(%%sr0,%1)\;sync\;mtsp %4,%%sr0\;nop\;nop\;nop\;nop\;nop\;nop"
[(set_attr "type" "multi")
(set_attr "length" "52")])
+
+;; An out-of-line prologue.
+(define_insn "outline_prologue_call"
+ [(unspec_volatile [(const_int 0)] 0)
+ (clobber (reg:SI 31))
+ (clobber (reg:SI 22))
+ (clobber (reg:SI 21))
+ (clobber (reg:SI 20))
+ (clobber (reg:SI 19))
+ (clobber (reg:SI 1))]
+ ""
+ "*
+{
+ extern int frame_pointer_needed;
+
+ /* We need two different versions depending on whether or not we
+ need a frame pointer. Also note that we return to the instruction
+ immediately after the branch rather than two instructions after the
+ break as normally is the case. */
+ if (frame_pointer_needed)
+ {
+ /* Must import the magic millicode routine(s). */
+ output_asm_insn (\".IMPORT __outline_prologue_fp,MILLICODE\", NULL);
+
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_prologue_fp,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_prologue_fp(%%sr0,%%r31)\",
+ NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_prologue_fp,%%r31\", NULL);
+ }
+ else
+ {
+ /* Must import the magic millicode routine(s). */
+ output_asm_insn (\".IMPORT __outline_prologue,MILLICODE\", NULL);
+
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_prologue,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_prologue(%%sr0,%%r31)\", NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_prologue,%%r31\", NULL);
+ }
+ return \"\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+;; An out-of-line epilogue.
+(define_insn "outline_epilogue_call"
+ [(unspec_volatile [(const_int 1)] 0)
+ (use (reg:SI 29))
+ (use (reg:SI 28))
+ (clobber (reg:SI 31))
+ (clobber (reg:SI 22))
+ (clobber (reg:SI 21))
+ (clobber (reg:SI 20))
+ (clobber (reg:SI 19))
+ (clobber (reg:SI 2))
+ (clobber (reg:SI 1))]
+ ""
+ "*
+{
+ extern int frame_pointer_needed;
+
+ /* We need two different versions depending on whether or not we
+ need a frame pointer. Also note that we return to the instruction
+ immediately after the branch rather than two instructions after the
+ break as normally is the case. */
+ if (frame_pointer_needed)
+ {
+ /* Must import the magic millicode routine. */
+ output_asm_insn (\".IMPORT __outline_epilogue_fp,MILLICODE\", NULL);
+
+ /* The out-of-line prologue will make sure we return to the right
+ instruction. */
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_epilogue_fp,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_epilogue_fp(%%sr0,%%r31)\",
+ NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_epilogue_fp,%%r31\", NULL);
+ }
+ else
+ {
+ /* Must import the magic millicode routine. */
+ output_asm_insn (\".IMPORT __outline_epilogue,MILLICODE\", NULL);
+
+ /* The out-of-line prologue will make sure we return to the right
+ instruction. */
+ if (TARGET_PORTABLE_RUNTIME)
+ {
+ output_asm_insn (\"ldil L'__outline_epilogue,%%r31\", NULL);
+ output_asm_insn (\"ble,n R'__outline_epilogue(%%sr0,%%r31)\", NULL);
+ }
+ else
+ output_asm_insn (\"bl,n __outline_epilogue,%%r31\", NULL);
+ }
+ return \"\";
+}"
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+;; Given a function pointer, canonicalize it so it can be
+;; reliably compared to another function pointer. */
+(define_expand "canonicalize_funcptr_for_compare"
+ [(set (reg:SI 26) (match_operand:SI 1 "register_operand" ""))
+ (parallel [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0))
+ (clobber (match_dup 2))
+ (clobber (reg:SI 26))
+ (clobber (reg:SI 22))
+ (clobber (reg:SI 31))])
+ (set (match_operand:SI 0 "register_operand" "")
+ (reg:SI 29))]
+ "! TARGET_PORTABLE_RUNTIME"
+ "
+{
+ operands[2] = gen_reg_rtx (SImode);
+ if (GET_CODE (operands[1]) != REG)
+ {
+ rtx tmp = gen_reg_rtx (Pmode);
+ emit_move_insn (tmp, operands[1]);
+ operands[1] = tmp;
+ }
+}")
+
+(define_insn ""
+ [(set (reg:SI 29) (unspec:SI [(reg:SI 26)] 0))
+ (clobber (match_operand:SI 0 "register_operand" "=a"))
+ (clobber (reg:SI 26))
+ (clobber (reg:SI 22))
+ (clobber (reg:SI 31))]
+ ""
+ "*
+{
+ /* Must import the magic millicode routine. */
+ output_asm_insn (\".IMPORT $$sh_func_adrs,MILLICODE\", NULL);
+
+ /* This is absolutely amazing.
+
+ First, copy our input parameter into %r29 just in case we don't
+ need to call $$sh_func_adrs. */
+ output_asm_insn (\"copy %%r26,%%r29\", NULL);
+
+ /* Next, examine the low two bits in %r26, if they aren't 0x2, then
+ we use %r26 unchanged. */
+ if (get_attr_length (insn) == 32)
+ output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+24\", NULL);
+ else if (get_attr_length (insn) == 40)
+ output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+32\", NULL);
+ else if (get_attr_length (insn) == 44)
+ output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+36\", NULL);
+ else
+ output_asm_insn (\"extru %%r26,31,2,%%r31\;comib,<>,n 2,%%r31,.+20\", NULL);
+
+ /* Next, compare %r26 with 4096, if %r26 is less than or equal to
+ 4096, then we use %r26 unchanged. */
+ if (get_attr_length (insn) == 32)
+ output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+16\", NULL);
+ else if (get_attr_length (insn) == 40)
+ output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+24\", NULL);
+ else if (get_attr_length (insn) == 44)
+ output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+28\", NULL);
+ else
+ output_asm_insn (\"ldi 4096,%%r31\;comb,<<,n %%r26,%%r31,.+12\", NULL);
+
+ /* Else call $$sh_func_adrs to extract the function's real add24. */
+ return output_millicode_call (insn,
+ gen_rtx (SYMBOL_REF, SImode,
+ \"$$sh_func_adrs\"));
+}"
+ [(set_attr "type" "multi")
+ (set (attr "length")
+ (cond [
+;; Target (or stub) within reach
+ (and (lt (plus (symbol_ref "total_code_bytes") (pc))
+ (const_int 240000))
+ (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0)))
+ (const_int 28)
+
+;; NO_SPACE_REGS
+ (ne (symbol_ref "TARGET_NO_SPACE_REGS || TARGET_FAST_INDIRECT_CALLS")
+ (const_int 0))
+ (const_int 32)
+
+;; Out of reach, but not PIC or PORTABLE_RUNTIME
+;; same as NO_SPACE_REGS code
+ (and (eq (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (eq (symbol_ref "flag_pic")
+ (const_int 0)))
+ (const_int 32)
+
+;; PORTABLE_RUNTIME
+ (ne (symbol_ref "TARGET_PORTABLE_RUNTIME")
+ (const_int 0))
+ (const_int 40)]
+
+;; Out of range and PIC
+ (const_int 44)))])
+
+;; On the PA, the PIC register is call clobbered, so it must
+;; be saved & restored around calls by the caller. If the call
+;; doesn't return normally (nonlocal goto, or an exception is
+;; thrown), then the code at the exception handler label must
+;; restore the PIC register.
+(define_expand "exception_receiver"
+ [(const_int 4)]
+ "!TARGET_PORTABLE_RUNTIME && flag_pic"
+ "
+{
+ /* Load the PIC register from the stack slot (in our caller's
+ frame). */
+ emit_move_insn (pic_offset_table_rtx,
+ gen_rtx (MEM, SImode,
+ plus_constant (stack_pointer_rtx, -32)));
+ emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
+ emit_insn (gen_blockage ());
+ DONE;
+}")
+
+
diff --git a/gnu/usr.bin/gcc/config/pa/t-pa b/gnu/usr.bin/gcc/config/pa/t-pa
index 07dc2cb09c7..a359918a125 100644
--- a/gnu/usr.bin/gcc/config/pa/t-pa
+++ b/gnu/usr.bin/gcc/config/pa/t-pa
@@ -1,8 +1,18 @@
LIBGCC1=libgcc1.null
CROSS_LIBGCC1=libgcc1.null
ADA_CFLAGS=-mdisable-indexing
-LIB2FUNCS_EXTRA=lib2funcs.asm
+LIB2FUNCS_EXTRA=lib2funcs.asm ee.asm ee_fp.asm
-lib2funcs.asm: $(srcdir)/config/pa/$(LIB2FUNCS_EXTRA)
+lib2funcs.asm: $(srcdir)/config/pa/lib2funcs.asm
rm -f lib2funcs.asm
- cp $(srcdir)/config/pa/$(LIB2FUNCS_EXTRA) .
+ cp $(srcdir)/config/pa/lib2funcs.asm .
+
+ee.asm: $(srcdir)/config/pa/ee.asm
+ rm -f ee.asm
+ cp $(srcdir)/config/pa/ee.asm .
+
+ee_fp.asm: $(srcdir)/config/pa/ee_fp.asm
+ rm -f ee_fp.asm
+ cp $(srcdir)/config/pa/ee_fp.asm .
+
+TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gnu/usr.bin/gcc/config/pa/x-pa b/gnu/usr.bin/gcc/config/pa/x-pa
index c1409ab77b4..4c250477358 100644
--- a/gnu/usr.bin/gcc/config/pa/x-pa
+++ b/gnu/usr.bin/gcc/config/pa/x-pa
@@ -1,3 +1,3 @@
# BSD on the PA already has ANSI include files which are c++ compatible.
-INSTALL_HEADERS=
+USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS)
STMP_FIXPROTO=
diff --git a/gnu/usr.bin/gcc/config/pa/x-pa-hpux b/gnu/usr.bin/gcc/config/pa/x-pa-hpux
index 3375d421849..1b8bb9fa733 100644
--- a/gnu/usr.bin/gcc/config/pa/x-pa-hpux
+++ b/gnu/usr.bin/gcc/config/pa/x-pa-hpux
@@ -1 +1,4 @@
ALLOCA=alloca.o
+
+# So putenv and other functions get seen by fixproto.
+FIXPROTO_DEFINES = -D_HPUX_SOURCE
diff --git a/gnu/usr.bin/gcc/config/pa/xm-pa.h b/gnu/usr.bin/gcc/config/pa/xm-pa.h
index cb87a7615bf..0249055bf6e 100644
--- a/gnu/usr.bin/gcc/config/pa/xm-pa.h
+++ b/gnu/usr.bin/gcc/config/pa/xm-pa.h
@@ -50,9 +50,6 @@ extern int errno;
/* Don't try to use sys_siglist. */
#define NO_SYS_SIGLIST
-/* We have strerror, don't try to use sys_errlist. */
-#define HAVE_STRERROR
-
/* 4.3BSD, OSF1 and Lites on the PA are all derived from NET2 or
later code from Berkeley. */
#define __BSD_NET2__
@@ -61,5 +58,5 @@ extern int errno;
#define ONLY_INT_FIELDS
/* Always claim to use C alloca; this prevents losing if building with
- gcc -fno-builtin ... " */
+ gcc -fno-builtin ... */
#define USE_C_ALLOCA
diff --git a/gnu/usr.bin/gcc/config/pa/xm-pahpux.h b/gnu/usr.bin/gcc/config/pa/xm-pahpux.h
index 97e9403b158..09c949b358e 100644
--- a/gnu/usr.bin/gcc/config/pa/xm-pahpux.h
+++ b/gnu/usr.bin/gcc/config/pa/xm-pahpux.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for PA-RISC.
- Copyright (C) 1988, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1995, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
This file is part of GNU CC.
@@ -24,13 +24,6 @@ Boston, MA 02111-1307, USA. */
#define USG
/* Use System V memory functions. */
-#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 rindex strrchr
-#define index strchr
-
/* #defines that need visibility everywhere. */
#define FALSE 0
#define TRUE 1
diff --git a/gnu/usr.bin/gcc/config/pdp11/2bsd.h b/gnu/usr.bin/gcc/config/pdp11/2bsd.h
index 6293da64cf2..3cc97dbace3 100644
--- a/gnu/usr.bin/gcc/config/pdp11/2bsd.h
+++ b/gnu/usr.bin/gcc/config/pdp11/2bsd.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for a PDP with 2BSD
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
This file is part of GNU CC.
@@ -18,8 +18,6 @@ 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 "pdp11/pdp11.h"
-
/* This macro generates the assembly code for function entry. */
#undef FUNCTION_PROLOGUE
#define FUNCTION_PROLOGUE(FILE, SIZE) \
diff --git a/gnu/usr.bin/gcc/config/pdp11/pdp11.c b/gnu/usr.bin/gcc/config/pdp11/pdp11.c
index ec1e080661f..20628d42792 100644
--- a/gnu/usr.bin/gcc/config/pdp11/pdp11.c
+++ b/gnu/usr.bin/gcc/config/pdp11/pdp11.c
@@ -1,5 +1,5 @@
/* Subroutines for gcc2 for pdp11.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
This file is part of GNU CC.
@@ -19,10 +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. */
-#ifndef FILE
-#include <stdio.h>
-#endif
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -32,6 +30,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
+#include "flags.h"
/*
#define FPU_REG_P(X) ((X)>=8 && (X)<14)
@@ -97,9 +96,6 @@ output_function_prologue(stream, size)
FILE *stream;
int size;
{
- extern char call_used_regs[];
- extern int frame_pointer_needed;
-
int fsize = ((size) + 1) & ~1;
int regno, nregs, i;
int offset = 0;
@@ -196,7 +192,6 @@ output_function_epilogue(stream, size)
FILE *stream;
int size;
{
- extern char call_used_regs[];
extern int may_call_alloca;
int fsize = ((size) + 1) & ~1;
diff --git a/gnu/usr.bin/gcc/config/pdp11/pdp11.h b/gnu/usr.bin/gcc/config/pdp11/pdp11.h
index 46cd53d38e6..9f755c1227e 100644
--- a/gnu/usr.bin/gcc/config/pdp11/pdp11.h
+++ b/gnu/usr.bin/gcc/config/pdp11/pdp11.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for the pdp-11
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
This file is part of GNU CC.
@@ -378,7 +378,7 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
#define N_REG_CLASSES (int) LIM_REG_CLASSES
/* have to allow this till cmpsi/tstsi are fixed in a better way !! */
-#define SMALL_REGISTER_CLASSES
+#define SMALL_REGISTER_CLASSES 1
/* Since GENERAL_REGS is the same class as ALL_REGS,
don't give it a different class number; just make it an alias. */
@@ -598,7 +598,7 @@ maybe ac0 ? - as option someday! */
when the function gets a structure-value-address as an
invisible first argument. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
@@ -1079,11 +1079,9 @@ fprintf (FILE, "$help$: . = .+8 ; space for tmp moves!\n") \
#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. */
@@ -1149,11 +1147,9 @@ fprintf (FILE, "$help$: . = .+8 ; space for tmp moves!\n") \
fprintf (FILE, "\t.word L_%d\n", VALUE)
/* This is how to output an element of a case-vector that is relative.
- (the pdp does not use such vectors,
- but we must define this macro anyway.) */
+ Don't define this if it is not supported. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
- fprintf (FILE, "\tERROR @L%d-@L%d ! error should not be used\n", VALUE, REL)
+/* #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) */
/* This is how to output an assembler line
that says to advance the location counter
diff --git a/gnu/usr.bin/gcc/config/pdp11/pdp11.md b/gnu/usr.bin/gcc/config/pdp11/pdp11.md
index d23c2cd6657..ec6a43f66d1 100644
--- a/gnu/usr.bin/gcc/config/pdp11/pdp11.md
+++ b/gnu/usr.bin/gcc/config/pdp11/pdp11.md
@@ -1,5 +1,5 @@
;;- Machine description for the pdp11 for GNU C compiler
-;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
;; Contributed by Michael K. Gschwind (mike@vlsivie.tuwien.ac.at).
;; This file is part of GNU CC.
@@ -48,7 +48,7 @@
;; The only thing that remains to be done then is output
;; the floats in a way the assembler can handle it (and
;; if you're really into it, use a PDP11 float emulation
-;; libary to do floating point constant folding - but
+;; library to do floating point constant folding - but
;; I guess you'll get reasonable results even when not
;; doing this)
;; the last thing to do is fix the UPDATE_CC macro to check
@@ -682,20 +682,26 @@
;; let constraints only accept a register ...
(define_expand "movstrhi"
- [(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" "=g,g"))
- (mem:BLK (match_operand:BLK 1 "general_operand" "g,g")))
+ [(parallel [(set (match_operand:BLK 0 "general_operand" "=g,g")
+ (match_operand:BLK 1 "general_operand" "g,g"))
(use (match_operand:HI 2 "arith_operand" "n,&mr"))
(use (match_operand:HI 3 "immediate_operand" "i,i"))
(clobber (match_scratch:HI 4 "=&r,X"))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
+ (clobber (match_dup 5))
+ (clobber (match_dup 6))
(clobber (match_dup 2))])]
"(TARGET_BCOPY_BUILTIN)"
"
{
- operands[0] = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- operands[1] = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
- operands[2] = force_not_mem (operands[2]);
+ operands[0]
+ = change_address (operands[0], VOIDmode,
+ copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
+ operands[1]
+ = change_address (operands[1], VOIDmode,
+ copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
+
+ operands[5] = XEXP (operands[0], 0);
+ operands[6] = XEXP (operands[1], 0);
}")
diff --git a/gnu/usr.bin/gcc/config/pyr/pyr.c b/gnu/usr.bin/gcc/config/pyr/pyr.c
index 3203377e2c7..46ea25c0374 100644
--- a/gnu/usr.bin/gcc/config/pyr/pyr.c
+++ b/gnu/usr.bin/gcc/config/pyr/pyr.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Pyramid 90x, 9000, and MIServer Series.
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,8 +19,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Some output-actions in pyr.md need these. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gnu/usr.bin/gcc/config/pyr/pyr.h b/gnu/usr.bin/gcc/config/pyr/pyr.h
index e59bd0acd1b..ea88ee4ba10 100644
--- a/gnu/usr.bin/gcc/config/pyr/pyr.h
+++ b/gnu/usr.bin/gcc/config/pyr/pyr.h
@@ -1,6 +1,6 @@
/* Definitions of target machine parameters for GNU compiler,
for Pyramid 90x, 9000, and MIServer Series.
- Copyright (C) 1989, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -495,7 +495,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
We may nevertheless provide this as an option. */
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \
- ((TARGET_RETD && TREE_CODE (FUNTYPE) != IDENTIFIER_NODE \
+ ((TARGET_RETD && (!(FUNDECL) || TREE_CODE (FUNDECL) != IDENTIFIER_NODE) \
&& (TYPE_ARG_TYPES (FUNTYPE) == 0 \
|| (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \
== void_type_node))) \
@@ -629,7 +629,7 @@ extern int inner_param_safe_helper();
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) \
((CUM) = (FNTYPE && !flag_pcc_struct_return \
&& aggregate_value_p (TREE_TYPE (FNTYPE))))
@@ -1177,10 +1177,9 @@ extern int swap_operands;
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs (".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. */
+/* 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/gnu/usr.bin/gcc/config/pyr/pyr.md b/gnu/usr.bin/gcc/config/pyr/pyr.md
index 3c03beaec6f..97d91014595 100644
--- a/gnu/usr.bin/gcc/config/pyr/pyr.md
+++ b/gnu/usr.bin/gcc/config/pyr/pyr.md
@@ -1,5 +1,5 @@
;; GNU C machine description for Pyramid 90x, 9000, MIServer Series
-;; Copyright (C) 1989, 1990, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1990, 1995, 1997 Free Software Foundation, Inc.
;; This file is part of GNU CC.
@@ -903,7 +903,6 @@
""
"*
{
- extern int optimize;
if (optimize && REG_P (operands[0]) && REG_P (operands[1])
&& REGNO (operands[0]) == REGNO (operands[1])
&& already_sign_extended (insn, HImode, operands[0]))
@@ -920,7 +919,6 @@
""
"*
{
- extern int optimize;
if (optimize && REG_P (operands[0]) && REG_P (operands[1])
&& REGNO (operands[0]) == REGNO (operands[1])
&& already_sign_extended (insn, QImode, operands[0]))
@@ -1029,7 +1027,6 @@
""
"*
{
- extern int optimize;
if (optimize)
switch (GET_CODE (operands[0]))
{
@@ -1056,7 +1053,6 @@
""
"*
{
- extern int optimize;
if (optimize)
switch (GET_CODE (operands[0]))
{
diff --git a/gnu/usr.bin/gcc/config/romp/romp.c b/gnu/usr.bin/gcc/config/romp/romp.c
index 5926b74dce7..ed36259f652 100644
--- a/gnu/usr.bin/gcc/config/romp/romp.c
+++ b/gnu/usr.bin/gcc/config/romp/romp.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on ROMP.
- Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -1317,7 +1317,7 @@ struct symref_hashent {
static struct symref_hashent *symref_hash_table[SYMHASHSIZE];
-/* Given a name (allocatable in temporary storage), return a SYMBOL_REF
+/* Given a name (allocable in temporary storage), return a SYMBOL_REF
for the name. The rtx is allocated from the current rtl_obstack, while
the name string is allocated from the permanent obstack. */
rtx
diff --git a/gnu/usr.bin/gcc/config/romp/romp.h b/gnu/usr.bin/gcc/config/romp/romp.h
index 33872bb5cf8..be12d367fbb 100644
--- a/gnu/usr.bin/gcc/config/romp/romp.h
+++ b/gnu/usr.bin/gcc/config/romp/romp.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for ROMP chip.
- Copyright (C) 1989, 1991, 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1991, 1993, 1995, 1996 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@nyu.edu)
This file is part of GNU CC.
@@ -591,7 +591,7 @@ struct rt_cargs {int gregs, fregs; };
when the function gets a structure-value-address as an
invisible first argument. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
(CUM).gregs = 0, \
(CUM).fregs = 0
@@ -1419,11 +1419,9 @@ extern int romp_debugger_arg_correction();
#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. */
@@ -1508,10 +1506,9 @@ extern int romp_debugger_arg_correction();
fprintf (FILE, "\t.long L%d\n", VALUE)
/* This is how to output an element of a case-vector that is relative.
- (ROMP does not use such vectors,
- but we must define this macro anyway.) */
+ Don't define this if it is not supported. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) abort ()
+/* #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) */
/* This is how to output an assembler line
that says to advance the location counter
diff --git a/gnu/usr.bin/gcc/config/rs6000/aix31.h b/gnu/usr.bin/gcc/config/rs6000/aix31.h
index 644cee532b6..46bd03c38fb 100644
--- a/gnu/usr.bin/gcc/config/rs6000/aix31.h
+++ b/gnu/usr.bin/gcc/config/rs6000/aix31.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 running AIX version 3.1.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993,1997 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@nyu.edu)
This file is part of GNU CC.
@@ -30,3 +30,12 @@ Boston, MA 02111-1307, USA. */
/* AIX 3.1 uses bit 15 in CROR as the magic nop. */
#undef RS6000_CALL_GLUE
#define RS6000_CALL_GLUE "cror 15,15,15"
+
+/* AIX 3.1 does not prepend underscores to itrunc, uitrunc, or mcount. */
+#undef RS6000_ITRUNC
+#define RS6000_ITRUNC "itrunc"
+#undef RS6000_UITRUNC
+#define RS6000_UITRUNC "uitrunc"
+#undef RS6000_MCOUNT
+#define RS6000_MCOUNT ".mcount"
+
diff --git a/gnu/usr.bin/gcc/config/rs6000/aix3newas.h b/gnu/usr.bin/gcc/config/rs6000/aix3newas.h
index 31c0fd354d7..9659794d7c8 100644
--- a/gnu/usr.bin/gcc/config/rs6000/aix3newas.h
+++ b/gnu/usr.bin/gcc/config/rs6000/aix3newas.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 POWER running AIX version 3.x with the fixed assembler.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC.
@@ -21,31 +21,23 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Enable AIX XL compiler calling convention breakage compatibility. */
+#define MASK_XL_CALL 0x40000000
+#define TARGET_XL_CALL (target_flags & MASK_XL_CALL)
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+ {"xl-call", MASK_XL_CALL}, \
+ {"no-xl-call", - MASK_XL_CALL},
+
#include "rs6000/rs6000.h"
/* Tell the assembler to assume that all undefined names are external. */
#undef ASM_SPEC
-#define ASM_SPEC "-u \
-%{!mcpu*: \
- %{mpower: %{!mpowerpc*: %{!mpower2: -mpwr}}} \
- %{mpower2: -mpwrx} \
- %{mno-power: %{mpowerpc*: -mppc}} \
- %{mno-power: %{!mpowerpc*: -mcom}} \
- %{!mno-power: %{mpowerpc*: -m601}} \
- %{!mno-power: %{!mpowerpc*: %{!mpower2: -mpwr}}}} \
-%{mcpu=common: -mcom} \
-%{mcpu=power: -mpwr} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rios: -mpwr} \
-%{mcpu=rios1: -mpwr} \
-%{mcpu=rios2: -mpwrx} \
-%{mcpu=rsc: -mpwr} \
-%{mcpu=rsc1: -mpwr} \
-%{mcpu=403: -mppc} \
-%{mcpu=601: -m601} \
-%{mcpu=603: -mppc} \
-%{mcpu=604: -mppc}"
+#define ASM_SPEC "-u %(asm_cpu)"
+
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mpwr"
/* Define the options for the binder: Start text at 512, align all segments
to 512 bytes, and warn if there is text relocation.
@@ -65,10 +57,17 @@ Boston, MA 02111-1307, USA. */
as per README.RS6000. */
#undef LINK_SPEC
+#ifndef CROSS_COMPILE
#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
%{static:-bnso -bI:/lib/syscalls.exp} \
%{mcpu=common: milli.exp%s} \
%{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}"
+#else
+#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
+ %{static:-bnso} \
+ %{mcpu=common: milli.exp%s} \
+ %{shared:-bM:SRE}"
+#endif
/* These are not necessary when we pass -u to the assembler, and undefining
them saves a great deal of space in object files. */
@@ -79,7 +78,6 @@ Boston, MA 02111-1307, USA. */
{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
if ((TREE_CODE (DECL) == VAR_DECL \
|| TREE_CODE (DECL) == FUNCTION_DECL) \
- && (NAME)[0] != '*' \
&& (NAME)[strlen (NAME) - 1] != ']') \
{ \
char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
diff --git a/gnu/usr.bin/gcc/config/rs6000/aix41.h b/gnu/usr.bin/gcc/config/rs6000/aix41.h
index caf1a8bc0b6..fe4d757de79 100644
--- a/gnu/usr.bin/gcc/config/rs6000/aix41.h
+++ b/gnu/usr.bin/gcc/config/rs6000/aix41.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 POWER running AIX version 4.1.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by David Edelsohn (edelsohn@npac.syr.edu).
This file is part of GNU CC.
@@ -21,29 +21,54 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Enable AIX XL compiler calling convention breakage compatibility. */
+#define MASK_XL_CALL 0x40000000
+#define TARGET_XL_CALL (target_flags & MASK_XL_CALL)
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+ {"xl-call", MASK_XL_CALL}, \
+ {"no-xl-call", - MASK_XL_CALL}, \
+ {"threads", 0}, \
+ {"pe", 0},
+
#include "rs6000/rs6000.h"
#undef ASM_SPEC
-#define ASM_SPEC "-u \
-%{!mcpu*: \
- %{mpower: %{!mpowerpc*: %{!mpower2: -mpwr}}} \
- %{mpower2: -mpwrx} \
- %{mno-power: %{mpowerpc*: -mppc}} \
- %{mno-power: %{!mpowerpc*: -mcom}} \
- %{!mno-power: %{mpowerpc*: -m601}} \
- %{!mno-power: %{!mpowerpc*: %{!mpower2: -mpwr}}}} \
-%{mcpu=common: -mcom} \
-%{mcpu=power: -mpwr} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rios: -mpwr} \
-%{mcpu=rios1: -mpwr} \
-%{mcpu=rios2: -mpwrx} \
-%{mcpu=rsc: -mpwr} \
-%{mcpu=rsc1: -mpwr} \
-%{mcpu=403: -mppc} \
-%{mcpu=601: -m601} \
-%{mcpu=603: -mppc} \
-%{mcpu=604: -mppc}"
+#define ASM_SPEC "-u %(asm_cpu)"
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 -D_AIX41 \
+-Asystem(unix) -Asystem(aix)"
+
+#undef CPP_SPEC
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
+ %{mpe: -I/usr/lpp/ppe.poe/include}\
+ %{mthreads: -D_THREAD_SAFE}\
+ %(cpp_cpu)"
+
+#undef CPP_DEFAULT_SPEC
+#define CPP_DEFAULT_SPEC "-D_ARCH_COM"
+
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mcom"
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT MASK_NEW_MNEMONICS
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC601
+
+/* Define this macro as a C expression for the initializer of an
+ array of string to tell the driver program which options are
+ defaults for this target and thus do not need to be handled
+ specially when using `MULTILIB_OPTIONS'.
+
+ Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+ the target makefile fragment or if none of the options listed in
+ `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
+
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mcpu=common" }
/* These are not necessary when we pass -u to the assembler, and undefining
them saves a great deal of space in object files. */
@@ -54,7 +79,6 @@ Boston, MA 02111-1307, USA. */
{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
if ((TREE_CODE (DECL) == VAR_DECL \
|| TREE_CODE (DECL) == FUNCTION_DECL) \
- && (NAME)[0] != '*' \
&& (NAME)[strlen (NAME) - 1] != ']') \
{ \
char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
@@ -64,7 +88,24 @@ Boston, MA 02111-1307, USA. */
} \
}
+#undef LIB_SPEC
+#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
+ %{p:-L/lib/profiled -L/usr/lib/profiled} %{!shared:%{g*:-lg}}\
+ %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+ %{mthreads: -L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a}\
+ %{!mthreads: -lc}"
+
#undef LINK_SPEC
#define LINK_SPEC "-bpT:0x10000000 -bpD:0x20000000 %{!r:-btextro} -bnodelcsect\
- %{static:-bnso -bI:/lib/syscalls.exp} %{g*:-bexport:/usr/lib/libg.exp}\
- %{shared:-bM:SRE}"
+ %{static:-bnso %(link_syscalls) } %{!shared: %{g*: %(link_libg) }}\
+ %{shared:-bM:SRE %{!e:-bnoentry}}"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "%{!shared:\
+ %{mpe:%{pg:/usr/lpp/ppe.poe/lib/gcrt0.o}\
+ %{!pg:%{p:/usr/lpp/ppe.poe/lib/mcrt0.o}\
+ %{!p:/usr/lpp/ppe.poe/lib/crt0.o}}}\
+ %{!mpe:\
+ %{mthreads:%{pg:gcrt0_r%O%s}%{!pg:%{p:mcrt0_r%O%s}%{!p:crt0_r%O%s}}}\
+ %{!mthreads:%{pg:gcrt0%O%s}%{!pg:%{p:mcrt0%O%s}%{!p:crt0%O%s}}}}}"
+
diff --git a/gnu/usr.bin/gcc/config/rs6000/eabi-ctors.c b/gnu/usr.bin/gcc/config/rs6000/eabi-ctors.c
index 6f6a891eca0..ebc23ded35c 100644
--- a/gnu/usr.bin/gcc/config/rs6000/eabi-ctors.c
+++ b/gnu/usr.bin/gcc/config/rs6000/eabi-ctors.c
@@ -21,6 +21,13 @@ 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. */
+
/* Declare a pointer to void function type. */
@@ -34,6 +41,19 @@ extern func_ptr __CTOR_END__ [];
extern func_ptr __DTOR_LIST__[];
extern func_ptr __DTOR_END__ [];
+extern void __do_global_ctors (void);
+extern void __do_global_dtors (void);
+
+extern void __init (), __fini ();
+
+/* The Solaris linker seems to incorrectly relocate PC relative relocations
+ to a different section (ie, calls to __init, __fini), so avoid it by
+ using a function pointer. */
+static void (*init_ptr) (void) = __init;
+static void (*fini_ptr) (void) = __fini;
+
+void (*__atexit)(func_ptr);
+
/* Call all global constructors */
void
__do_global_ctors (void)
@@ -41,18 +61,32 @@ __do_global_ctors (void)
func_ptr *ptr = &__CTOR_LIST__[0];
func_ptr *end = &__CTOR_END__[0];
+ if (__atexit)
+ __atexit (__do_global_dtors);
+
+ /* Call the constructors collected in the .ctors section. */
for ( ; ptr != end; ptr++)
- (*ptr)();
+ if (*ptr)
+ (*ptr)();
+
+ /* Call the initialization function in the .init section. */
+ (*init_ptr) ();
}
/* Call all global destructors */
void
__do_global_dtors (void)
{
- func_ptr *ptr = &__DTOR_LIST__[0];
- func_ptr *end = &__DTOR_END__[0];
+ func_ptr *ptr = &__DTOR_END__[0] - 1;
+ func_ptr *start = &__DTOR_LIST__[0];
- for ( ; ptr != end; ptr++)
- (*ptr)();
+ /* Call the termination function in the .fini section. */
+ (*fini_ptr) ();
+
+ /* Call the destructors collected in the .dtors section. Run
+ the destructors in reverse order. */
+ for ( ; ptr >= start; ptr--)
+ if (*ptr)
+ (*ptr)();
}
diff --git a/gnu/usr.bin/gcc/config/rs6000/eabi.asm b/gnu/usr.bin/gcc/config/rs6000/eabi.asm
index 38674dd7234..879a63e87ad 100644
--- a/gnu/usr.bin/gcc/config/rs6000/eabi.asm
+++ b/gnu/usr.bin/gcc/config/rs6000/eabi.asm
@@ -1,379 +1,555 @@
-# File to either setup register 2 to point to the GOT, or to adjust the
-# pointers in the .got2 section to point to their new addresses.
+/*
+ * special support for eabi
+ *
+ * Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+ * Written By Michael Meissner
+ *
+ * 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.
+ */
+
+/* Do any initializations needed for the eabi environment */
.file "eabi.asm"
.section ".text"
- .globl __eabi
+ #include "ppc-asm.h"
.section ".got2","aw"
-.LCTOC1 = . # +32768
+ .align 2
+.LCTOC1 = . /* +32768 */
-# Table of addresses
+/* Table of addresses */
.Ltable = .-.LCTOC1
- .long .LCTOC1 # address we are really at
+ .long .LCTOC1 /* address we are really at */
-.Lgot = .-.LCTOC1
- .long _GLOBAL_OFFSET_TABLE_ # normal GOT address
+.Lsda = .-.LCTOC1
+ .long _SDA_BASE_ /* address of the first small data area */
+.Lsdas = .-.LCTOC1
+ .long __SDATA_START__ /* start of .sdata/.sbss section */
+
+.Lsdae = .-.LCTOC1
+ .long __SBSS_END__ /* end of .sdata/.sbss section */
+
+.Lsda2 = .-.LCTOC1
+ .long _SDA2_BASE_ /* address of the second small data area */
+
+.Lsda2s = .-.LCTOC1
+ .long __SDATA2_START__ /* start of .sdata2/.sbss2 section */
+
+.Lsda2e = .-.LCTOC1
+ .long __SBSS2_END__ /* end of .sdata2/.sbss2 section */
+
+#ifdef _RELOCATABLE
.Lgots = .-.LCTOC1
- .long _GOT_START_ # start of .got section
+ .long __GOT_START__ /* Global offset table start */
+
+.Lgotm1 = .-.LCTOC1
+ .long _GLOBAL_OFFSET_TABLE_-4 /* end of GOT ptrs before BLCL + 3 reserved words */
+
+.Lgotm2 = .-.LCTOC1
+ .long _GLOBAL_OFFSET_TABLE_+12 /* start of GOT ptrs after BLCL + 3 reserved words */
.Lgote = .-.LCTOC1
- .long _GOT_END_ # end of .got section
+ .long __GOT_END__ /* Global offset table end */
.Lgot2s = .-.LCTOC1
- .long _GOT2_START_ # -mrelocatable GOT pointers start
+ .long __GOT2_START__ /* -mrelocatable GOT pointers start */
.Lgot2e = .-.LCTOC1
- .long _GOT2_END_ # -mrelocatable GOT pointers end
+ .long __GOT2_END__ /* -mrelocatable GOT pointers end */
.Lfixups = .-.LCTOC1
- .long _FIXUP_START_ # start of .fixup section
+ .long __FIXUP_START__ /* start of .fixup section */
.Lfixupe = .-.LCTOC1
- .long _FIXUP_END_ # end of .fixup section
+ .long __FIXUP_END__ /* end of .fixup section */
+
+.Lctors = .-.LCTOC1
+ .long __CTOR_LIST__ /* start of .ctor section */
+
+.Lctore = .-.LCTOC1
+ .long __CTOR_END__ /* end of .ctor section */
+
+.Ldtors = .-.LCTOC1
+ .long __DTOR_LIST__ /* start of .dtor section */
+
+.Ldtore = .-.LCTOC1
+ .long __DTOR_END__ /* end of .dtor section */
+
+.Lexcepts = .-.LCTOC1
+ .long __EXCEPT_START__ /* start of .gcc_except_table section */
+
+.Lexcepte = .-.LCTOC1
+ .long __EXCEPT_END__ /* end of .gcc_except_table section */
+
+.Linit = .-.LCTOC1
+ .long .Linit_p /* address of variable to say we've been called */
.text
+ .align 2
.Lptr:
- .long .LCTOC1-.Laddr # PC relative pointer to .got2
- .long 0x4000 # traceback table
+ .long .LCTOC1-.Laddr /* PC relative pointer to .got2 */
+#endif
-__eabi: mflr 0
- bl .Laddr # get current address
+ .data
+ .align 2
+.Linit_p:
+ .long 0
+
+ .text
+
+FUNC_START(__eabi)
+
+/* Eliminate -mrelocatable code if not -mrelocatable, so that this file can
+ be assembled with other assemblers than GAS, such as the Solaris PowerPC
+ assembler. */
+
+#ifndef _RELOCATABLE
+ addis 10,0,.Linit_p@ha /* init flag */
+ addis 11,0,.LCTOC1@ha /* load address of .LCTOC1 */
+ lwz 9,.Linit_p@l(10) /* init flag */
+ addi 11,11,.LCTOC1@l
+ cmplwi 2,9,0 /* init flag != 0? */
+ bnelr 2 /* return now, if we've been called already */
+ stw 1,.Linit_p@l(10) /* store a non-zero value in the done flag */
+
+#else /* -mrelocatable */
+ mflr 0
+ bl .Laddr /* get current address */
.Laddr:
- mflr 12 # real address of .Laddr
- lwz 11,(.Lptr-.Laddr)(12) # linker generated address of .LCTOC1
- add 11,11,12 # correct to real pointer
- lwz 12,.Ltable(11) # get linker's idea of where .Laddr is
- subf. 12,12,11 # calculate difference
- mtlr 0 # restore link register
- bc 4,2,.Lreloc # skip if we need to relocate
+ mflr 12 /* real address of .Laddr */
+ lwz 11,(.Lptr-.Laddr)(12) /* linker generated address of .LCTOC1 */
+ add 11,11,12 /* correct to real pointer */
+ lwz 12,.Ltable(11) /* get linker's idea of where .Laddr is */
+ lwz 10,.Linit(11) /* address of init flag */
+ subf. 12,12,11 /* calculate difference */
+ lwzx 9,10,12 /* done flag */
+ cmplwi 2,9,0 /* init flag != 0? */
+ bnelr 2 /* return now, if we've been called already */
+ stwx 1,10,12 /* store a non-zero value in the done flag */
+ beq+ 0,.Lsdata /* skip if we don't need to relocate */
+
+/* We need to relocate the .got2 pointers. */
+
+ lwz 3,.Lgot2s(11) /* GOT2 pointers start */
+ lwz 4,.Lgot2e(11) /* GOT2 pointers end */
+ add 3,12,3 /* adjust pointers */
+ add 4,12,4
+ bl FUNC_NAME(__eabi_convert) /* convert pointers in .got2 section */
-# Only load up register 2 if there is a .got section
+/* Fixup the .ctor section for static constructors */
- lwz 3,.Lgots(11) # start of .got section
- lwz 4,.Lgote(11) # end of .got section
- cmpw 1,3,4 # .got section non-empty?
- bc 12,6,.Ldone
+ lwz 3,.Lctors(11) /* constructors pointers start */
+ lwz 4,.Lctore(11) /* constructors pointers end */
+ bl FUNC_NAME(__eabi_convert) /* convert constructors */
-# Normal program, load up register 2
+/* Fixup the .dtor section for static destructors */
- lwz 2,.Lgot(11) # normal GOT address (obsolete in register 2)
- mr 13,2 # also same as _SDA_BASE_ (V.4 small data ptr)
- b __do_global_ctors # do any C++ global constructors (which returns to caller)
+ lwz 3,.Ldtors(11) /* destructors pointers start */
+ lwz 4,.Ldtore(11) /* destructors pointers end */
+ bl FUNC_NAME(__eabi_convert) /* convert destructors */
-# We need to relocate the .got2 pointers. Don't load register 2
+/* Fixup the .gcc_except_table section for G++ exceptions */
-.Lreloc:
- lwz 3,.Lgot2s(11) # GOT pointers start
- lwz 4,.Lgot2e(11) # GOT pointers end
- add 3,12,3 # adjust pointers
- add 4,12,4
+ lwz 3,.Lexcepts(11) /* exception table pointers start */
+ lwz 4,.Lexcepte(11) /* exception table pointers end */
+ bl FUNC_NAME(__eabi_convert) /* convert exceptions */
+
+/* Fixup the the addresses in the GOT below _GLOBAL_OFFSET_TABLE_-4 */
- cmpw 1,3,4 # any pointers to adjust
- bc 12,6,.Lfix
+ lwz 3,.Lgots(11) /* GOT table pointers start */
+ lwz 4,.Lgotm1(11) /* GOT table pointers below _GLOBAL_OFFSET_TABLE-4 */
+ bl FUNC_NAME(__eabi_convert) /* convert lower GOT */
-.Lloop:
- lwz 5,0(3) # next pointer
- add 5,5,12 # adjust
- stw 5,0(3)
- addi 3,3,4 # bump to next word
- cmpw 1,3,4 # more pointers to adjust?
- bc 4,6,.Lloop
+/* Fixup the the addresses in the GOT above _GLOBAL_OFFSET_TABLE_+12 */
-# Fixup any user initialized pointers now (the compiler drops pointers to
-# each of the relocs that it does in the .fixup section). Note, the pointers
-# themselves have already been fixed up by the previous loop.
+ lwz 3,.Lgotm2(11) /* GOT table pointers above _GLOBAL_OFFSET_TABLE+12 */
+ lwz 4,.Lgote(11) /* GOT table pointers end */
+ bl FUNC_NAME(__eabi_convert) /* convert lower GOT */
+
+/* Fixup any user initialized pointers now (the compiler drops pointers to */
+/* each of the relocs that it does in the .fixup section). */
.Lfix:
- lwz 3,.Lfixups(11) # fixup pointers start
- lwz 4,.Lfixupe(11) # fixup pointers end
+ lwz 3,.Lfixups(11) /* fixup pointers start */
+ lwz 4,.Lfixupe(11) /* fixup pointers end */
+ bl FUNC_NAME(__eabi_uconvert) /* convert user initialized pointers */
+
+.Lsdata:
+ mtlr 0 /* restore link register */
+#endif /* _RELOCATABLE */
+
+/* Only load up register 13 if there is a .sdata and/or .sbss section */
+ lwz 3,.Lsdas(11) /* start of .sdata/.sbss section */
+ lwz 4,.Lsdae(11) /* end of .sdata/.sbss section */
+ cmpw 1,3,4 /* .sdata/.sbss section non-empty? */
+ beq- 1,.Lsda2l /* skip loading r13 */
+
+ lwz 13,.Lsda(11) /* load r13 with _SDA_BASE_ address */
+
+/* Only load up register 2 if there is a .sdata2 and/or .sbss2 section */
- cmpw 1,3,4 # any user pointers to adjust
- bc 12,6,.Ldone
+.Lsda2l:
+ lwz 3,.Lsda2s(11) /* start of .sdata/.sbss section */
+ lwz 4,.Lsda2e(11) /* end of .sdata/.sbss section */
+ cmpw 1,3,4 /* .sdata/.sbss section non-empty? */
+ beq+ 1,.Ldone /* skip loading r2 */
-.Lfloop:
- lwz 5,0(3) # next pointer
- lwz 6,0(5) # get the pointer it points to
- add 6,6,12 # adjust
- stw 6,0(5)
- addi 3,3,4 # bump to next word
- cmpw 1,3,4 # more pointers to adjust?
- bc 4,6,.Lfloop
+ lwz 2,.Lsda2(11) /* load r2 with _SDA2_BASE_ address */
-# Done adjusting pointers, return
+/* Done adjusting pointers, return by way of doing the C++ global constructors. */
.Ldone:
- b __do_global_ctors # do any C++ global constructors (which returns to caller)
-
-# Routines for saving floating point registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the floating point save area.
-
- .globl _savefpr_14
- .globl _savefpr_15
- .globl _savefpr_16
- .globl _savefpr_17
- .globl _savefpr_18
- .globl _savefpr_19
- .globl _savefpr_20
- .globl _savefpr_21
- .globl _savefpr_22
- .globl _savefpr_23
- .globl _savefpr_24
- .globl _savefpr_25
- .globl _savefpr_26
- .globl _savefpr_27
- .globl _savefpr_28
- .globl _savefpr_29
- .globl _savefpr_30
- .globl _savefpr_31
-
- .long 0x00400000 # traceback tag
-_savefpr_14: stfd 14,-144(11) # save fp registers
-_savefpr_15: stfd 15,-136(11)
-_savefpr_16: stfd 16,-128(11)
-_savefpr_17: stfd 17,-120(11)
-_savefpr_18: stfd 18,-112(11)
-_savefpr_19: stfd 19,-104(11)
-_savefpr_20: stfd 20,-96(11)
-_savefpr_21: stfd 21,-88(11)
-_savefpr_22: stfd 22,-80(11)
-_savefpr_23: stfd 23,-72(11)
-_savefpr_24: stfd 24,-64(11)
-_savefpr_25: stfd 25,-56(11)
-_savefpr_26: stfd 26,-48(11)
-_savefpr_27: stfd 27,-40(11)
-_savefpr_28: stfd 28,-32(11)
-_savefpr_29: stfd 29,-24(11)
-_savefpr_30: stfd 30,-16(11)
-_savefpr_31: stfd 31,-8(11)
- blr
-
-# Routines for saving integer registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the integer save area.
-
- .globl _savegpr_14
- .globl _savegpr_15
- .globl _savegpr_16
- .globl _savegpr_17
- .globl _savegpr_18
- .globl _savegpr_19
- .globl _savegpr_20
- .globl _savegpr_21
- .globl _savegpr_22
- .globl _savegpr_23
- .globl _savegpr_24
- .globl _savegpr_25
- .globl _savegpr_26
- .globl _savegpr_27
- .globl _savegpr_28
- .globl _savegpr_29
- .globl _savegpr_30
- .globl _savegpr_31
-
- .long 0x00400000 # traceback tag
-_savegpr_14: stw 14,-72(11) # save gp registers
-_savegpr_15: stw 15,-68(11)
-_savegpr_16: stw 16,-64(11)
-_savegpr_17: stw 17,-60(11)
-_savegpr_18: stw 18,-56(11)
-_savegpr_19: stw 19,-52(11)
-_savegpr_20: stw 20,-48(11)
-_savegpr_21: stw 21,-44(11)
-_savegpr_22: stw 22,-40(11)
-_savegpr_23: stw 23,-36(11)
-_savegpr_24: stw 24,-32(11)
-_savegpr_25: stw 25,-28(11)
-_savegpr_26: stw 26,-24(11)
-_savegpr_27: stw 27,-20(11)
-_savegpr_28: stw 28,-16(11)
-_savegpr_29: stw 29,-12(11)
-_savegpr_30: stw 30,-8(11)
-_savegpr_31: stw 31,-4(11)
- blr
-
-# Routines for restoring floating point registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the floating point save area.
-
- .globl _restfpr_14
- .globl _restfpr_15
- .globl _restfpr_16
- .globl _restfpr_17
- .globl _restfpr_18
- .globl _restfpr_19
- .globl _restfpr_20
- .globl _restfpr_21
- .globl _restfpr_22
- .globl _restfpr_23
- .globl _restfpr_24
- .globl _restfpr_25
- .globl _restfpr_26
- .globl _restfpr_27
- .globl _restfpr_28
- .globl _restfpr_29
- .globl _restfpr_30
- .globl _restfpr_31
-
- .long 0x00600000 # traceback tag
-_restfpr_14: lfd 14,-144(11) # restore fp registers
-_restfpr_15: lfd 15,-136(11)
-_restfpr_16: lfd 16,-128(11)
-_restfpr_17: lfd 17,-120(11)
-_restfpr_18: lfd 18,-112(11)
-_restfpr_19: lfd 19,-104(11)
-_restfpr_20: lfd 20,-96(11)
-_restfpr_21: lfd 21,-88(11)
-_restfpr_22: lfd 22,-80(11)
-_restfpr_23: lfd 23,-72(11)
-_restfpr_24: lfd 24,-64(11)
-_restfpr_25: lfd 25,-56(11)
-_restfpr_26: lfd 26,-48(11)
-_restfpr_27: lfd 27,-40(11)
-_restfpr_28: lfd 28,-32(11)
-_restfpr_29: lfd 29,-24(11)
-_restfpr_30: lfd 30,-16(11)
-_restfpr_31: lfd 31,-8(11)
- blr
-
-# Routines for restoring integer registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the integer restore area.
-
- .globl _restgpr_14
- .globl _restgpr_15
- .globl _restgpr_16
- .globl _restgpr_17
- .globl _restgpr_18
- .globl _restgpr_19
- .globl _restgpr_20
- .globl _restgpr_21
- .globl _restgpr_22
- .globl _restgpr_23
- .globl _restgpr_24
- .globl _restgpr_25
- .globl _restgpr_26
- .globl _restgpr_27
- .globl _restgpr_28
- .globl _restgpr_29
- .globl _restgpr_30
- .globl _restgpr_31
-
- .long 0x00600000 # traceback tag
-_restgpr_14: lwz 14,-72(11) # rest gp registers
-_restgpr_15: lwz 15,-68(11)
-_restgpr_16: lwz 16,-64(11)
-_restgpr_17: lwz 17,-60(11)
-_restgpr_18: lwz 18,-56(11)
-_restgpr_19: lwz 19,-52(11)
-_restgpr_20: lwz 20,-48(11)
-_restgpr_21: lwz 21,-44(11)
-_restgpr_22: lwz 22,-40(11)
-_restgpr_23: lwz 23,-36(11)
-_restgpr_24: lwz 24,-32(11)
-_restgpr_25: lwz 25,-28(11)
-_restgpr_26: lwz 26,-24(11)
-_restgpr_27: lwz 27,-20(11)
-_restgpr_28: lwz 28,-16(11)
-_restgpr_29: lwz 29,-12(11)
-_restgpr_30: lwz 30,-8(11)
-_restgpr_31: lwz 31,-4(11)
- blr
-
-# Routines for restoring floating point registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the floating point save area.
-# In addition to restoring the fp registers, it will return to the caller's
-# caller
-
- .globl _restfpr_14_x
- .globl _restfpr_15_x
- .globl _restfpr_16_x
- .globl _restfpr_17_x
- .globl _restfpr_18_x
- .globl _restfpr_19_x
- .globl _restfpr_20_x
- .globl _restfpr_21_x
- .globl _restfpr_22_x
- .globl _restfpr_23_x
- .globl _restfpr_24_x
- .globl _restfpr_25_x
- .globl _restfpr_26_x
- .globl _restfpr_27_x
- .globl _restfpr_28_x
- .globl _restfpr_29_x
- .globl _restfpr_30_x
- .globl _restfpr_31_x
-
- .long 0x00600000 # traceback tag
-_restfpr_14_x: lfd 14,-144(11) # restore fp registers
-_restfpr_15_x: lfd 15,-136(11)
-_restfpr_16_x: lfd 16,-128(11)
-_restfpr_17_x: lfd 17,-120(11)
-_restfpr_18_x: lfd 18,-112(11)
-_restfpr_19_x: lfd 19,-104(11)
-_restfpr_20_x: lfd 20,-96(11)
-_restfpr_21_x: lfd 21,-88(11)
-_restfpr_22_x: lfd 22,-80(11)
-_restfpr_23_x: lfd 23,-72(11)
-_restfpr_24_x: lfd 24,-64(11)
-_restfpr_25_x: lfd 25,-56(11)
-_restfpr_26_x: lfd 26,-48(11)
-_restfpr_27_x: lfd 27,-40(11)
-_restfpr_28_x: lfd 28,-32(11)
-_restfpr_29_x: lfd 29,-24(11)
-_restfpr_30_x: lfd 30,-16(11)
-_restfpr_31_x: lwz 0,4(11)
- lfd 31,-8(11)
- mtlr 0
- mr 1,11
- blr
-
-# Routines for restoring integer registers, called by the compiler.
-# Called with r11 pointing to the stack header word of the caller of the
-# function, just beyond the end of the integer restore area.
-
- .globl _restgpr_14_x
- .globl _restgpr_15_x
- .globl _restgpr_16_x
- .globl _restgpr_17_x
- .globl _restgpr_18_x
- .globl _restgpr_19_x
- .globl _restgpr_20_x
- .globl _restgpr_21_x
- .globl _restgpr_22_x
- .globl _restgpr_23_x
- .globl _restgpr_24_x
- .globl _restgpr_25_x
- .globl _restgpr_26_x
- .globl _restgpr_27_x
- .globl _restgpr_28_x
- .globl _restgpr_29_x
- .globl _restgpr_30_x
- .globl _restgpr_31_x
-
- .long 0x00600000 # traceback tag
-_restgpr_14_x: lwz 14,-72(11) # rest gp registers
-_restgpr_15_x: lwz 15,-68(11)
-_restgpr_16_x: lwz 16,-64(11)
-_restgpr_17_x: lwz 17,-60(11)
-_restgpr_18_x: lwz 18,-56(11)
-_restgpr_19_x: lwz 19,-52(11)
-_restgpr_20_x: lwz 20,-48(11)
-_restgpr_21_x: lwz 21,-44(11)
-_restgpr_22_x: lwz 22,-40(11)
-_restgpr_23_x: lwz 23,-36(11)
-_restgpr_24_x: lwz 24,-32(11)
-_restgpr_25_x: lwz 25,-28(11)
-_restgpr_26_x: lwz 26,-24(11)
-_restgpr_27_x: lwz 27,-20(11)
-_restgpr_28_x: lwz 28,-16(11)
-_restgpr_29_x: lwz 29,-12(11)
-_restgpr_30_x: lwz 30,-8(11)
-_restgpr_31_x: lwz 0,4(11)
- lwz 31,-4(11)
- mtlr 0
- mr 1,11
- blr
+ b FUNC_NAME(__do_global_ctors) /* do any C++ global constructors (which returns to caller) */
+FUNC_END(__eabi)
+
+/* Special subroutine to convert a bunch of pointers directly.
+ r0 has original link register
+ r3 has low pointer to convert
+ r4 has high pointer to convert
+ r5 .. r10 are scratch registers
+ r11 has the address of .LCTOC1 in it.
+ r12 has the value to add to each pointer
+ r13 .. r31 are unchanged */
+
+FUNC_START(__eabi_convert)
+ cmplw 1,3,4 /* any pointers to convert? */
+ subf 5,3,4 /* calculate number of words to convert */
+ bclr 4,4 /* return if no pointers */
+
+ srawi 5,5,2
+ addi 3,3,-4 /* start-4 for use with lwzu */
+ mtctr 5
+
+.Lcvt:
+ lwzu 6,4(3) /* pointer to convert */
+ cmpi 0,6,0
+ beq- .Lcvt2 /* if pointer is null, don't convert */
+
+ add 6,6,12 /* convert pointer */
+ stw 6,0(3)
+.Lcvt2:
+ bdnz+ .Lcvt
+ blr
+
+FUNC_END(__eabi_convert)
+
+/* Special subroutine to convert the pointers the user has initialized. The
+ compiler has placed the address of the initialized pointer into the .fixup
+ section.
+
+ r0 has original link register
+ r3 has low pointer to convert
+ r4 has high pointer to convert
+ r5 .. r10 are scratch registers
+ r11 has the address of .LCTOC1 in it.
+ r12 has the value to add to each pointer
+ r13 .. r31 are unchanged */
+
+FUNC_START(__eabi_uconvert)
+ cmplw 1,3,4 /* any pointers to convert? */
+ subf 5,3,4 /* calculate number of words to convert */
+ bclr 4,4 /* return if no pointers */
+
+ srawi 5,5,2
+ addi 3,3,-4 /* start-4 for use with lwzu */
+ mtctr 5
+
+.Lucvt:
+ lwzu 6,4(3) /* next pointer to pointer to convert */
+ add 6,6,12 /* adjust pointer */
+ lwz 7,0(6) /* get the pointer it points to */
+ stw 6,0(3) /* store adjusted pointer */
+ add 7,7,12 /* adjust */
+ stw 7,0(6)
+ bdnz+ .Lucvt
+ blr
+
+FUNC_END(__eabi_uconvert)
+
+/* Routines for saving floating point registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the floating point save area. */
+
+FUNC_START(_savefpr_14) stfd 14,-144(11) /* save fp registers */
+FUNC_START(_savefpr_15) stfd 15,-136(11)
+FUNC_START(_savefpr_16) stfd 16,-128(11)
+FUNC_START(_savefpr_17) stfd 17,-120(11)
+FUNC_START(_savefpr_18) stfd 18,-112(11)
+FUNC_START(_savefpr_19) stfd 19,-104(11)
+FUNC_START(_savefpr_20) stfd 20,-96(11)
+FUNC_START(_savefpr_21) stfd 21,-88(11)
+FUNC_START(_savefpr_22) stfd 22,-80(11)
+FUNC_START(_savefpr_23) stfd 23,-72(11)
+FUNC_START(_savefpr_24) stfd 24,-64(11)
+FUNC_START(_savefpr_25) stfd 25,-56(11)
+FUNC_START(_savefpr_26) stfd 26,-48(11)
+FUNC_START(_savefpr_27) stfd 27,-40(11)
+FUNC_START(_savefpr_28) stfd 28,-32(11)
+FUNC_START(_savefpr_29) stfd 29,-24(11)
+FUNC_START(_savefpr_30) stfd 30,-16(11)
+FUNC_START(_savefpr_31) stfd 31,-8(11)
+ blr
+FUNC_END(_savefpr_31)
+FUNC_END(_savefpr_30)
+FUNC_END(_savefpr_29)
+FUNC_END(_savefpr_28)
+FUNC_END(_savefpr_27)
+FUNC_END(_savefpr_26)
+FUNC_END(_savefpr_25)
+FUNC_END(_savefpr_24)
+FUNC_END(_savefpr_23)
+FUNC_END(_savefpr_22)
+FUNC_END(_savefpr_21)
+FUNC_END(_savefpr_20)
+FUNC_END(_savefpr_19)
+FUNC_END(_savefpr_18)
+FUNC_END(_savefpr_17)
+FUNC_END(_savefpr_16)
+FUNC_END(_savefpr_15)
+FUNC_END(_savefpr_14)
+
+/* Routines for saving integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer save area. */
+
+FUNC_START(_savegpr_14) stw 14,-72(11) /* save gp registers */
+FUNC_START(_savegpr_15) stw 15,-68(11)
+FUNC_START(_savegpr_16) stw 16,-64(11)
+FUNC_START(_savegpr_17) stw 17,-60(11)
+FUNC_START(_savegpr_18) stw 18,-56(11)
+FUNC_START(_savegpr_19) stw 19,-52(11)
+FUNC_START(_savegpr_20) stw 20,-48(11)
+FUNC_START(_savegpr_21) stw 21,-44(11)
+FUNC_START(_savegpr_22) stw 22,-40(11)
+FUNC_START(_savegpr_23) stw 23,-36(11)
+FUNC_START(_savegpr_24) stw 24,-32(11)
+FUNC_START(_savegpr_25) stw 25,-28(11)
+FUNC_START(_savegpr_26) stw 26,-24(11)
+FUNC_START(_savegpr_27) stw 27,-20(11)
+FUNC_START(_savegpr_28) stw 28,-16(11)
+FUNC_START(_savegpr_29) stw 29,-12(11)
+FUNC_START(_savegpr_30) stw 30,-8(11)
+FUNC_START(_savegpr_31) stw 31,-4(11)
+ blr
+FUNC_END(_savegpr_31)
+FUNC_END(_savegpr_30)
+FUNC_END(_savegpr_29)
+FUNC_END(_savegpr_28)
+FUNC_END(_savegpr_27)
+FUNC_END(_savegpr_26)
+FUNC_END(_savegpr_25)
+FUNC_END(_savegpr_24)
+FUNC_END(_savegpr_23)
+FUNC_END(_savegpr_22)
+FUNC_END(_savegpr_21)
+FUNC_END(_savegpr_20)
+FUNC_END(_savegpr_19)
+FUNC_END(_savegpr_18)
+FUNC_END(_savegpr_17)
+FUNC_END(_savegpr_16)
+FUNC_END(_savegpr_15)
+FUNC_END(_savegpr_14)
+
+/* Routines for restoring floating point registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the floating point save area. */
+
+FUNC_START(_restfpr_14) lfd 14,-144(11) /* restore fp registers */
+FUNC_START(_restfpr_15) lfd 15,-136(11)
+FUNC_START(_restfpr_16) lfd 16,-128(11)
+FUNC_START(_restfpr_17) lfd 17,-120(11)
+FUNC_START(_restfpr_18) lfd 18,-112(11)
+FUNC_START(_restfpr_19) lfd 19,-104(11)
+FUNC_START(_restfpr_20) lfd 20,-96(11)
+FUNC_START(_restfpr_21) lfd 21,-88(11)
+FUNC_START(_restfpr_22) lfd 22,-80(11)
+FUNC_START(_restfpr_23) lfd 23,-72(11)
+FUNC_START(_restfpr_24) lfd 24,-64(11)
+FUNC_START(_restfpr_25) lfd 25,-56(11)
+FUNC_START(_restfpr_26) lfd 26,-48(11)
+FUNC_START(_restfpr_27) lfd 27,-40(11)
+FUNC_START(_restfpr_28) lfd 28,-32(11)
+FUNC_START(_restfpr_29) lfd 29,-24(11)
+FUNC_START(_restfpr_30) lfd 30,-16(11)
+FUNC_START(_restfpr_31) lfd 31,-8(11)
+ blr
+FUNC_END(_restfpr_31)
+FUNC_END(_restfpr_30)
+FUNC_END(_restfpr_29)
+FUNC_END(_restfpr_28)
+FUNC_END(_restfpr_27)
+FUNC_END(_restfpr_26)
+FUNC_END(_restfpr_25)
+FUNC_END(_restfpr_24)
+FUNC_END(_restfpr_23)
+FUNC_END(_restfpr_22)
+FUNC_END(_restfpr_21)
+FUNC_END(_restfpr_20)
+FUNC_END(_restfpr_19)
+FUNC_END(_restfpr_18)
+FUNC_END(_restfpr_17)
+FUNC_END(_restfpr_16)
+FUNC_END(_restfpr_15)
+FUNC_END(_restfpr_14)
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+FUNC_START(_restgpr_14) lwz 14,-72(11) /* restore gp registers */
+FUNC_START(_restgpr_15) lwz 15,-68(11)
+FUNC_START(_restgpr_16) lwz 16,-64(11)
+FUNC_START(_restgpr_17) lwz 17,-60(11)
+FUNC_START(_restgpr_18) lwz 18,-56(11)
+FUNC_START(_restgpr_19) lwz 19,-52(11)
+FUNC_START(_restgpr_20) lwz 20,-48(11)
+FUNC_START(_restgpr_21) lwz 21,-44(11)
+FUNC_START(_restgpr_22) lwz 22,-40(11)
+FUNC_START(_restgpr_23) lwz 23,-36(11)
+FUNC_START(_restgpr_24) lwz 24,-32(11)
+FUNC_START(_restgpr_25) lwz 25,-28(11)
+FUNC_START(_restgpr_26) lwz 26,-24(11)
+FUNC_START(_restgpr_27) lwz 27,-20(11)
+FUNC_START(_restgpr_28) lwz 28,-16(11)
+FUNC_START(_restgpr_29) lwz 29,-12(11)
+FUNC_START(_restgpr_30) lwz 30,-8(11)
+FUNC_START(_restgpr_31) lwz 31,-4(11)
+ blr
+FUNC_END(_restgpr_31)
+FUNC_END(_restgpr_30)
+FUNC_END(_restgpr_29)
+FUNC_END(_restgpr_28)
+FUNC_END(_restgpr_27)
+FUNC_END(_restgpr_26)
+FUNC_END(_restgpr_25)
+FUNC_END(_restgpr_24)
+FUNC_END(_restgpr_23)
+FUNC_END(_restgpr_22)
+FUNC_END(_restgpr_21)
+FUNC_END(_restgpr_20)
+FUNC_END(_restgpr_19)
+FUNC_END(_restgpr_18)
+FUNC_END(_restgpr_17)
+FUNC_END(_restgpr_16)
+FUNC_END(_restgpr_15)
+FUNC_END(_restgpr_14)
+
+/* Routines for restoring floating point registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the floating point save area. */
+/* In addition to restoring the fp registers, it will return to the caller's */
+/* caller */
+
+FUNC_START(_restfpr_14_x) lfd 14,-144(11) /* restore fp registers */
+FUNC_START(_restfpr_15_x) lfd 15,-136(11)
+FUNC_START(_restfpr_16_x) lfd 16,-128(11)
+FUNC_START(_restfpr_17_x) lfd 17,-120(11)
+FUNC_START(_restfpr_18_x) lfd 18,-112(11)
+FUNC_START(_restfpr_19_x) lfd 19,-104(11)
+FUNC_START(_restfpr_20_x) lfd 20,-96(11)
+FUNC_START(_restfpr_21_x) lfd 21,-88(11)
+FUNC_START(_restfpr_22_x) lfd 22,-80(11)
+FUNC_START(_restfpr_23_x) lfd 23,-72(11)
+FUNC_START(_restfpr_24_x) lfd 24,-64(11)
+FUNC_START(_restfpr_25_x) lfd 25,-56(11)
+FUNC_START(_restfpr_26_x) lfd 26,-48(11)
+FUNC_START(_restfpr_27_x) lfd 27,-40(11)
+FUNC_START(_restfpr_28_x) lfd 28,-32(11)
+FUNC_START(_restfpr_29_x) lfd 29,-24(11)
+FUNC_START(_restfpr_30_x) lfd 30,-16(11)
+FUNC_START(_restfpr_31_x) lwz 0,4(11)
+ lfd 31,-8(11)
+ mtlr 0
+ mr 1,11
+ blr
+FUNC_END(_restfpr_31_x)
+FUNC_END(_restfpr_30_x)
+FUNC_END(_restfpr_29_x)
+FUNC_END(_restfpr_28_x)
+FUNC_END(_restfpr_27_x)
+FUNC_END(_restfpr_26_x)
+FUNC_END(_restfpr_25_x)
+FUNC_END(_restfpr_24_x)
+FUNC_END(_restfpr_23_x)
+FUNC_END(_restfpr_22_x)
+FUNC_END(_restfpr_21_x)
+FUNC_END(_restfpr_20_x)
+FUNC_END(_restfpr_19_x)
+FUNC_END(_restfpr_18_x)
+FUNC_END(_restfpr_17_x)
+FUNC_END(_restfpr_16_x)
+FUNC_END(_restfpr_15_x)
+FUNC_END(_restfpr_14_x)
+
+/* Routines for restoring integer registers, called by the compiler. */
+/* Called with r11 pointing to the stack header word of the caller of the */
+/* function, just beyond the end of the integer restore area. */
+
+FUNC_START(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */
+FUNC_START(_restgpr_15_x) lwz 15,-68(11)
+FUNC_START(_restgpr_16_x) lwz 16,-64(11)
+FUNC_START(_restgpr_17_x) lwz 17,-60(11)
+FUNC_START(_restgpr_18_x) lwz 18,-56(11)
+FUNC_START(_restgpr_19_x) lwz 19,-52(11)
+FUNC_START(_restgpr_20_x) lwz 20,-48(11)
+FUNC_START(_restgpr_21_x) lwz 21,-44(11)
+FUNC_START(_restgpr_22_x) lwz 22,-40(11)
+FUNC_START(_restgpr_23_x) lwz 23,-36(11)
+FUNC_START(_restgpr_24_x) lwz 24,-32(11)
+FUNC_START(_restgpr_25_x) lwz 25,-28(11)
+FUNC_START(_restgpr_26_x) lwz 26,-24(11)
+FUNC_START(_restgpr_27_x) lwz 27,-20(11)
+FUNC_START(_restgpr_28_x) lwz 28,-16(11)
+FUNC_START(_restgpr_29_x) lwz 29,-12(11)
+FUNC_START(_restgpr_30_x) lwz 30,-8(11)
+FUNC_START(_restgpr_31_x) lwz 0,4(11)
+ lwz 31,-4(11)
+ mtlr 0
+ mr 1,11
+ blr
+FUNC_END(_restgpr_31_x)
+FUNC_END(_restgpr_30_x)
+FUNC_END(_restgpr_29_x)
+FUNC_END(_restgpr_28_x)
+FUNC_END(_restgpr_27_x)
+FUNC_END(_restgpr_26_x)
+FUNC_END(_restgpr_25_x)
+FUNC_END(_restgpr_24_x)
+FUNC_END(_restgpr_23_x)
+FUNC_END(_restgpr_22_x)
+FUNC_END(_restgpr_21_x)
+FUNC_END(_restgpr_20_x)
+FUNC_END(_restgpr_19_x)
+FUNC_END(_restgpr_18_x)
+FUNC_END(_restgpr_17_x)
+FUNC_END(_restgpr_16_x)
+FUNC_END(_restgpr_15_x)
+FUNC_END(_restgpr_14_x)
diff --git a/gnu/usr.bin/gcc/config/rs6000/eabi.h b/gnu/usr.bin/gcc/config/rs6000/eabi.h
index 0f8bdb5ead4..1c225ea35dc 100644
--- a/gnu/usr.bin/gcc/config/rs6000/eabi.h
+++ b/gnu/usr.bin/gcc/config/rs6000/eabi.h
@@ -1,6 +1,6 @@
/* Core target definitions for GNU compiler
for IBM RS/6000 PowerPC targeted to embedded ELF systems.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GNU CC.
@@ -22,45 +22,12 @@ Boston, MA 02111-1307, USA. */
#include "rs6000/sysv4.h"
-/* For now, make stabs the default debugging type, not dwarf. */
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-/* Make int foo : 8 not cause structures to be aligned to an int boundary */
-
-#undef PCC_BITFIELD_TYPE_MATTERS
-#define PCC_BITFIELD_TYPE_MATTERS (TARGET_BITFIELD_TYPE)
-
-/* Define this macro to be the value 1 if instructions will fail to
- work if given data not on the nominal alignment. If instructions
- will merely go slower in that case, define this macro as 0.
-
- Note, little endian systems trap on unaligned addresses, so never
- turn off strict alignment in that case. */
-#undef STRICT_ALIGNMENT
-#define STRICT_ALIGNMENT (TARGET_STRICT_ALIGN || TARGET_LITTLE_ENDIAN)
-
-/* Align stack to 8 byte boundaries, rather than 16 bytes Sys V.4 uses */
-#undef STACK_BOUNDARY
-#define STACK_BOUNDARY 64
-
-/* No data type wants to be aligned rounder than this. */
-#undef BIGGEST_ALIGNMENT
-#define BIGGEST_ALIGNMENT 64
-
-/* Put PC relative got entries in .got2 */
-#undef MINIMAL_TOC_SECTION_ASM_OP
-#define MINIMAL_TOC_SECTION_ASM_OP \
- ((TARGET_RELOCATABLE) ? "\t.section\t\".got2\",\"aw\"" : "\t.section\t\".got1\",\"aw\"")
-
-/* Put relocatable data in .data, not .rodata so initialized pointers can be updated */
-#undef CONST_SECTION_ASM_OP
-#define CONST_SECTION_ASM_OP \
- ((TARGET_RELOCATABLE) ? "\t.section\t\".data\"\t# .rodata" : "\t.section\t\".rodata\"")
+/* Add -meabi to target flags */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI)
/* Invoke an initializer function to set up the GOT */
#define NAME__MAIN "__eabi"
-#define INVOKE__main 1
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded)");
@@ -69,57 +36,5 @@ Boston, MA 02111-1307, USA. */
#define CPP_PREDEFINES \
"-DPPC -D__embedded__ -Asystem(embedded) -Acpu(powerpc) -Amachine(powerpc)"
-/* Don't use startfiles or libraries except for libgcc.a */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC ""
-
-#undef LIB_SPEC
-#define LIB_SPEC ""
-
-#undef LIBGCC_SPEC
-#define LIBGCC_SPEC "libgcc.a%s"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
-
-/* This is how to output an assembler line defining an `int' constant.
- For -mrelocatable, we mark all addresses that need to be fixed up
- in the .fixup section. */
-#undef ASM_OUTPUT_INT
-#define ASM_OUTPUT_INT(FILE,VALUE) \
-do { \
- static int recurse = 0; \
- if (TARGET_RELOCATABLE \
- && in_section != in_toc \
- && in_section != in_text \
- && in_section != in_ctors \
- && in_section != in_dtors \
- && !recurse \
- && GET_CODE (VALUE) != CONST_INT \
- && GET_CODE (VALUE) != CONST_DOUBLE \
- && CONSTANT_P (VALUE)) \
- { \
- static int labelno = 0; \
- char buf[256], *p; \
- \
- recurse = 1; \
- ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++); \
- STRIP_NAME_ENCODING (p, buf); \
- fprintf (FILE, "%s:\n", p); \
- fprintf (FILE, "\t.long ("); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, ")@fixup\n"); \
- fprintf (FILE, "\t.section\t\".fixup\",\"aw\"\n"); \
- ASM_OUTPUT_ALIGN (FILE, 2); \
- fprintf (FILE, "\t.long\t%s\n", p); \
- fprintf (FILE, "\t.previous\n"); \
- recurse = 0; \
- } \
- else \
- { \
- fprintf (FILE, "\t.long "); \
- output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n"); \
- } \
-} while (0)
-
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mbig", "mcall-sysv" }
diff --git a/gnu/usr.bin/gcc/config/rs6000/eabiaix.h b/gnu/usr.bin/gcc/config/rs6000/eabiaix.h
index 6e92d17df8c..5cfd890a03e 100644
--- a/gnu/usr.bin/gcc/config/rs6000/eabiaix.h
+++ b/gnu/usr.bin/gcc/config/rs6000/eabiaix.h
@@ -1,5 +1,5 @@
/* Embedded ELF system support, using old AIX based calling sequence.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GNU CC.
@@ -21,33 +21,21 @@ Boston, MA 02111-1307, USA. */
#include "rs6000/eabi.h"
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_AIX_CALLS)
-
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_AIX}} \
-%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
-%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{!mlittle: %{!mlittle-endian: -D_BIG_ENDIAN -Amachine(bigendian)}} \
-%{!mcpu*: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
- %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+/* Default ABI to use */
+#undef RS6000_ABI_NAME
+#define RS6000_ABI_NAME "aix"
+
+#undef CPP_SYSV_DEFAULT_SPEC
+#define CPP_SYSV_DEFAULT_SPEC "-D_CALL_AIX"
+
+/* Define this macro as a C expression for the initializer of an
+ array of string to tell the driver program which options are
+ defaults for this target and thus do not need to be handled
+ specially when using `MULTILIB_OPTIONS'.
+
+ Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+ the target makefile fragment or if none of the options listed in
+ `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
+
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mbig", "mcall-aix" }
diff --git a/gnu/usr.bin/gcc/config/rs6000/eabile.h b/gnu/usr.bin/gcc/config/rs6000/eabile.h
index 11ff65ea9fa..78dc7bc89c4 100644
--- a/gnu/usr.bin/gcc/config/rs6000/eabile.h
+++ b/gnu/usr.bin/gcc/config/rs6000/eabile.h
@@ -1,6 +1,6 @@
/* Core target definitions for GNU compiler for PowerPC targeted to
little endian embedded ELF systems.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GNU CC.
@@ -23,32 +23,24 @@ Boston, MA 02111-1307, USA. */
#include "rs6000/eabi.h"
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN)
-
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
-%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
-%{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \
-%{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \
-%{!mbig: %{!mbig-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)}} \
-%{!mcpu*: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
- %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN | MASK_EABI)
+
+#undef CPP_ENDIAN_DEFAULT_SPEC
+#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_little)"
+
+#undef LINK_TARGET_SPEC
+#define LINK_TARGET_SPEC "\
+%{mbig: -oformat elf32-powerpc } %{mbig-endian: -oformat elf32-powerpc } \
+%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: %{mcall-linux: -oformat elf32-powerpc}}}}}"
+
+/* Define this macro as a C expression for the initializer of an
+ array of string to tell the driver program which options are
+ defaults for this target and thus do not need to be handled
+ specially when using `MULTILIB_OPTIONS'.
+
+ Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+ the target makefile fragment or if none of the options listed in
+ `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
+
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mlittle", "mcall-sysv" }
diff --git a/gnu/usr.bin/gcc/config/rs6000/eabilesim.h b/gnu/usr.bin/gcc/config/rs6000/eabilesim.h
index afc85652676..7ced05c7cb2 100644
--- a/gnu/usr.bin/gcc/config/rs6000/eabilesim.h
+++ b/gnu/usr.bin/gcc/config/rs6000/eabilesim.h
@@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA. */
#include "rs6000/eabile.h"
-/* Right now, the simulator doesn't handle floating point, so disable it
- by default. */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN | MASK_SOFT_FLOAT)
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)");
@@ -34,43 +29,18 @@ Boston, MA 02111-1307, USA. */
#define CPP_PREDEFINES \
"-DPPC -D__embedded__ -D__simulator__ -Asystem(embedded) -Asystem(simulator) -Acpu(powerpc) -Amachine(powerpc)"
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
-%{!mhard-float: -D_SOFT_FLOAT} \
-%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{!mlittle: %{!mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)}} \
-%{!mcpu*: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
- %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+/* Make the simulator the default */
+#undef LIB_DEFAULT_SPEC
+#define LIB_DEFAULT_SPEC "%(lib_sim)"
-/* Use the simulator crt0 and libgloss/newlib libraries */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "sim-crt0.o%s"
+#undef STARTFILE_DEFAULT_SPEC
+#define STARTFILE_DEFAULT_SPEC "%(startfile_sim)"
-#undef LIB_SPEC
-#define LIB_SPEC "-lsim -lc -lsim"
+#undef ENDFILE_DEFAULT_SPEC
+#define ENDFILE_DEFAULT_SPEC "%(endfile_sim)"
-#undef LIBGCC_SPEC
-#define LIBGCC_SPEC "libgcc.a%s"
+#undef LINK_START_DEFAULT_SPEC
+#define LINK_START_DEFAULT_SPEC "%(link_start_sim)"
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
+#undef LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC "%(link_start_sim)"
diff --git a/gnu/usr.bin/gcc/config/rs6000/eabisim.h b/gnu/usr.bin/gcc/config/rs6000/eabisim.h
index 98c9f0ea8bb..0fc590bd6f2 100644
--- a/gnu/usr.bin/gcc/config/rs6000/eabisim.h
+++ b/gnu/usr.bin/gcc/config/rs6000/eabisim.h
@@ -1,6 +1,6 @@
/* Support for GCC on simulated PowerPC systems targeted to embedded ELF
systems.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GNU CC.
@@ -22,11 +22,6 @@ Boston, MA 02111-1307, USA. */
#include "rs6000/eabi.h"
-/* Right now, the simulator doesn't handle floating point, so disable it
- by default. */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_SOFT_FLOAT)
-
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)");
@@ -34,43 +29,18 @@ Boston, MA 02111-1307, USA. */
#define CPP_PREDEFINES \
"-DPPC -D__embedded__ -D__simulator__ -Asystem(embedded) -Asystem(simulator) -Acpu(powerpc) -Amachine(powerpc)"
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
-%{!mhard-float: -D_SOFT_FLOAT} \
-%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{!mlittle: %{!mlittle-endian: -D_BIG_ENDIAN -Amachine(bigendian)}} \
-%{!mcpu*: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
- %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+/* Make the simulator the default */
+#undef LIB_DEFAULT_SPEC
+#define LIB_DEFAULT_SPEC "%(lib_sim)"
-/* Use the simulator crt0 and libgloss/newlib libraries */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "sim-crt0.o%s"
+#undef STARTFILE_DEFAULT_SPEC
+#define STARTFILE_DEFAULT_SPEC "%(startfile_sim)"
-#undef LIB_SPEC
-#define LIB_SPEC "-lsim -lc -lsim"
+#undef ENDFILE_DEFAULT_SPEC
+#define ENDFILE_DEFAULT_SPEC "%(endfile_sim)"
-#undef LIBGCC_SPEC
-#define LIBGCC_SPEC "libgcc.a%s"
+#undef LINK_START_DEFAULT_SPEC
+#define LINK_START_DEFAULT_SPEC "%(link_start_sim)"
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
+#undef LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC "%(link_os_sim)"
diff --git a/gnu/usr.bin/gcc/config/rs6000/lynx.h b/gnu/usr.bin/gcc/config/rs6000/lynx.h
index 53b3ebfcb0f..e2fe6339fe4 100644
--- a/gnu/usr.bin/gcc/config/rs6000/lynx.h
+++ b/gnu/usr.bin/gcc/config/rs6000/lynx.h
@@ -1,5 +1,5 @@
/* Definitions for Rs6000 running LynxOS.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Contributed by David Henkel-Wallace, Cygnus Support (gumby@cygnus.com)
This file is part of GNU CC.
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#undef EXTRA_SECTION_FUNCTIONS
#undef SELECT_RTX_SECTION
#undef SELECT_SECTION
+#undef USER_LABEL_PREFIX
#undef ASM_OUTPUT_LABELREF
#undef ASM_OUTPUT_INTERNAL_LABEL
#undef ASM_GENERATE_INTERNAL_LABEL
@@ -72,7 +73,7 @@ Boston, MA 02111-1307, USA. */
/* This can become more refined as we have more powerpc options. */
#undef ASM_SPEC
-#define ASM_SPEC "-u %{m601:-m601} %{power*:-m601}"
+#define ASM_SPEC "-u %(asm_cpu)"
#undef SUBTARGET_SWITCHES
#define SUBTARGET_SWITCHES \
diff --git a/gnu/usr.bin/gcc/config/rs6000/mach.h b/gnu/usr.bin/gcc/config/rs6000/mach.h
index c812c6bb46f..bb4e8b4df84 100644
--- a/gnu/usr.bin/gcc/config/rs6000/mach.h
+++ b/gnu/usr.bin/gcc/config/rs6000/mach.h
@@ -20,6 +20,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 TARGET_AIX 0
#include "rs6000/rs6000.h"
diff --git a/gnu/usr.bin/gcc/config/rs6000/netware.h b/gnu/usr.bin/gcc/config/rs6000/netware.h
index 8e86a3438dd..f6de2aab0ea 100644
--- a/gnu/usr.bin/gcc/config/rs6000/netware.h
+++ b/gnu/usr.bin/gcc/config/rs6000/netware.h
@@ -1,6 +1,6 @@
/* Core target definitions for GNU compiler
for IBM RS/6000 PowerPC running NetWare
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GNU CC.
@@ -19,6 +19,8 @@ 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. */
+#define TARGET_AIX 0
+
#include "rs6000/powerpc.h"
/* Don't generate XCOFF debugging information. */
@@ -32,8 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The XCOFF support uses weird symbol suffixes, which we don't want
for ELF. */
-#undef RS6000_OUTPUT_BASENAME
-#define RS6000_OUTPUT_BASENAME(FILE, NAME) assemble_name (FILE, NAME)
+#undef STRIP_NAME_ENCODING
/* Don't bother to output .extern pseudo-ops. They are not needed by
ELF assemblers. */
@@ -180,11 +181,9 @@ toc_section () \
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \
fprintf (FILE, ".%s", PREFIX)
-/* Pass -m601 to the assembler, since that is what powerpc.h currently
- implies. */
#undef ASM_SPEC
-#define ASM_SPEC \
- "-u -m601 %{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}"
+#define ASM_SPEC "-u %(asm_cpu) \
+{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}"
/* This is the end of what might become sysv4.h. */
/* Enable output of DBX (stabs) debugging information when asked for it. */
diff --git a/gnu/usr.bin/gcc/config/rs6000/powerpc.h b/gnu/usr.bin/gcc/config/rs6000/powerpc.h
index e8f6a17168a..9f1ffd606cc 100644
--- a/gnu/usr.bin/gcc/config/rs6000/powerpc.h
+++ b/gnu/usr.bin/gcc/config/rs6000/powerpc.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 PowerPC running AIX version 3.2.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
Contributed by David Edelsohn (edelsohn@npac.syr.edu).
This file is part of GNU CC.
@@ -24,52 +24,17 @@ Boston, MA 02111-1307, USA. */
#include "rs6000/rs6000.h"
#undef ASM_SPEC
-#define ASM_SPEC "-u \
-%{!mcpu*: \
- %{mpower2: -mpwrx} \
- %{mpowerpc*: %{!mpower: -mppc}} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -mcom}}} \
- %{mno-powerpc: %{mpower: %{!mpower2: -mpwr}}} \
- %{!mno-powerpc: %{mpower: -m601}} \
- %{!mno-powerpc: %{!mpower: -mppc}}} \
-%{mcpu=common: -mcom} \
-%{mcpu=power: -mpwr} \
-%{mcpu=powerpc: -mppc} \
-%{mcpu=rios: -mpwr} \
-%{mcpu=rios1: -mpwr} \
-%{mcpu=rios2: -mpwrx} \
-%{mcpu=rsc: -mpwr} \
-%{mcpu=rsc1: -mpwr} \
-%{mcpu=403: -mppc} \
-%{mcpu=601: -m601} \
-%{mcpu=603: -mppc} \
-%{mcpu=604: -mppc}"
+#define ASM_SPEC "-u %(asm_cpu)"
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-D_IBMR2 -D_POWER -D_AIX -D_AIX32 \
-Asystem(unix) -Asystem(aix) -Acpu(powerpc) -Amachine(powerpc)"
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{!mcpu*: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
- %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+#undef CPP_DEFAULT_SPEC
+#define CPP_DEFAULT_SPEC "-D_ARCH_PPC"
+
+#undef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_SPEC "-mppc"
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
@@ -86,7 +51,6 @@ Boston, MA 02111-1307, USA. */
{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
if ((TREE_CODE (DECL) == VAR_DECL \
|| TREE_CODE (DECL) == FUNCTION_DECL) \
- && (NAME)[0] != '*' \
&& (NAME)[strlen (NAME) - 1] != ']') \
{ \
char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
diff --git a/gnu/usr.bin/gcc/config/rs6000/rs6000.h b/gnu/usr.bin/gcc/config/rs6000/rs6000.h
index 7cb08fea37e..087ac5ad8ce 100644
--- a/gnu/usr.bin/gcc/config/rs6000/rs6000.h
+++ b/gnu/usr.bin/gcc/config/rs6000/rs6000.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -32,6 +32,11 @@ Boston, MA 02111-1307, USA. */
/* Print subsidiary information on the compiler version in use. */
#define TARGET_VERSION ;
+/* Default string to use for cpu if not specified. */
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT ((char *)0)
+#endif
+
/* Tell the assembler to assume that all undefined names are external.
Don't do this until the fixed IBM assembler is more generally available.
@@ -40,21 +45,25 @@ Boston, MA 02111-1307, USA. */
longer be needed. Also, the extern declaration of mcount in ASM_FILE_START
will no longer be needed. */
-/* #define ASM_SPEC "-u" */
+/* #define ASM_SPEC "-u %(asm_cpu)" */
/* Define appropriate architecture macros for preprocessor depending on
target switches. */
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{!mcpu*: \
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_cpu)"
+
+/* Common CPP definitions used by CPP_SPEC among the various targets
+ for handling -mcpu=xxx switches. */
+#define CPP_CPU_SPEC \
+"%{!mcpu*: \
%{mpower: %{!mpower2: -D_ARCH_PWR}} \
%{mpower2: -D_ARCH_PWR2} \
%{mpowerpc*: -D_ARCH_PPC} \
%{mno-power: %{!mpowerpc*: -D_ARCH_COM}} \
- %{!mno-power: %{!mpower2: -D_ARCH_PWR}}} \
+ %{!mno-power: %{!mpower2: %(cpp_default)}}} \
%{mcpu=common: -D_ARCH_COM} \
%{mcpu=power: -D_ARCH_PWR} \
+%{mcpu=power2: -D_ARCH_PWR2} \
%{mcpu=powerpc: -D_ARCH_PPC} \
%{mcpu=rios: -D_ARCH_PWR} \
%{mcpu=rios1: -D_ARCH_PWR} \
@@ -62,9 +71,109 @@ Boston, MA 02111-1307, USA. */
%{mcpu=rsc: -D_ARCH_PWR} \
%{mcpu=rsc1: -D_ARCH_PWR} \
%{mcpu=403: -D_ARCH_PPC} \
+%{mcpu=505: -D_ARCH_PPC} \
%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
+%{mcpu=602: -D_ARCH_PPC} \
%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+%{mcpu=603e: -D_ARCH_PPC} \
+%{mcpu=604: -D_ARCH_PPC} \
+%{mcpu=620: -D_ARCH_PPC} \
+%{mcpu=821: -D_ARCH_PPC} \
+%{mcpu=860: -D_ARCH_PPC}"
+
+#ifndef CPP_DEFAULT_SPEC
+#define CPP_DEFAULT_SPEC "-D_ARCH_PWR"
+#endif
+
+#ifndef CPP_SYSV_SPEC
+#define CPP_SYSV_SPEC ""
+#endif
+
+#ifndef CPP_ENDIAN_SPEC
+#define CPP_ENDIAN_SPEC ""
+#endif
+
+#ifndef CPP_ENDIAN_DEFAULT_SPEC
+#define CPP_ENDIAN_DEFAULT_SPEC ""
+#endif
+
+#ifndef CPP_SYSV_DEFAULT_SPEC
+#define CPP_SYSV_DEFAULT_SPEC ""
+#endif
+
+/* Common ASM definitions used by ASM_SPEC among the various targets
+ for handling -mcpu=xxx switches. */
+#define ASM_CPU_SPEC \
+"%{!mcpu*: \
+ %{mpower: %{!mpower2: -mpwr}} \
+ %{mpower2: -mpwrx} \
+ %{mpowerpc*: -mppc} \
+ %{mno-power: %{!mpowerpc*: -mcom}} \
+ %{!mno-power: %{!mpower2: %(asm_default)}}} \
+%{mcpu=common: -mcom} \
+%{mcpu=power: -mpwr} \
+%{mcpu=power2: -mpwrx} \
+%{mcpu=powerpc: -mppc} \
+%{mcpu=rios: -mpwr} \
+%{mcpu=rios1: -mpwr} \
+%{mcpu=rios2: -mpwrx} \
+%{mcpu=rsc: -mpwr} \
+%{mcpu=rsc1: -mpwr} \
+%{mcpu=403: -mppc} \
+%{mcpu=505: -mppc} \
+%{mcpu=601: -m601} \
+%{mcpu=602: -mppc} \
+%{mcpu=603: -mppc} \
+%{mcpu=603e: -mppc} \
+%{mcpu=604: -mppc} \
+%{mcpu=620: -mppc} \
+%{mcpu=821: -mppc} \
+%{mcpu=860: -mppc}"
+
+#ifndef ASM_DEFAULT_SPEC
+#define ASM_DEFAULT_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_cpu", CPP_CPU_SPEC }, \
+ { "cpp_default", CPP_DEFAULT_SPEC }, \
+ { "cpp_sysv", CPP_SYSV_SPEC }, \
+ { "cpp_sysv_default", CPP_SYSV_DEFAULT_SPEC }, \
+ { "cpp_endian_default", CPP_ENDIAN_DEFAULT_SPEC }, \
+ { "cpp_endian", CPP_ENDIAN_SPEC }, \
+ { "asm_cpu", ASM_CPU_SPEC }, \
+ { "asm_default", ASM_DEFAULT_SPEC }, \
+ { "link_syscalls", LINK_SYSCALLS_SPEC }, \
+ { "link_libg", LINK_LIBG_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
+
+/* Default location of syscalls.exp under AIX */
+#ifndef CROSS_COMPILE
+#define LINK_SYSCALLS_SPEC "-bI:/lib/syscalls.exp"
+#else
+#define LINK_SYSCALLS_SPEC ""
+#endif
+
+/* Default location of libg.exp under AIX */
+#ifndef CROSS_COMPILE
+#define LINK_LIBG_SPEC "-bexport:/usr/lib/libg.exp"
+#else
+#define LINK_LIBG_SPEC ""
+#endif
/* Define the options for the binder: Start text at 512, align all segments
to 512 bytes, and warn if there is text relocation.
@@ -81,8 +190,8 @@ Boston, MA 02111-1307, USA. */
export list with the -Wl,-bE option. */
#define LINK_SPEC "-T512 -H512 %{!r:-btextro} -bhalt:4 -bnodelcsect\
- %{static:-bnso -bI:/lib/syscalls.exp} \
- %{!shared:%{g*:-bexport:/usr/lib/libg.exp}} %{shared:-bM:SRE}"
+ %{static:-bnso %(link_syscalls) } \
+ %{!shared:%{g*: %(link_libg) }} %{shared:-bM:SRE}"
/* Profiled library versions are used by linking with special directories. */
#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
@@ -99,33 +208,33 @@ Boston, MA 02111-1307, USA. */
extern int target_flags;
/* Use POWER architecture instructions and MQ register. */
-#define MASK_POWER 0x01
+#define MASK_POWER 0x00000001
/* Use POWER2 extensions to POWER architecture. */
-#define MASK_POWER2 0x02
+#define MASK_POWER2 0x00000002
/* Use PowerPC architecture instructions. */
-#define MASK_POWERPC 0x04
+#define MASK_POWERPC 0x00000004
/* Use PowerPC General Purpose group optional instructions, e.g. fsqrt. */
-#define MASK_PPC_GPOPT 0x08
+#define MASK_PPC_GPOPT 0x00000008
/* Use PowerPC Graphics group optional instructions, e.g. fsel. */
-#define MASK_PPC_GFXOPT 0x10
+#define MASK_PPC_GFXOPT 0x00000010
/* Use PowerPC-64 architecture instructions. */
-#define MASK_POWERPC64 0x20
+#define MASK_POWERPC64 0x00000020
/* Use revised mnemonic names defined for PowerPC architecture. */
-#define MASK_NEW_MNEMONICS 0x40
+#define MASK_NEW_MNEMONICS 0x00000040
/* Disable placing fp constants in the TOC; can be turned on when the
TOC overflows. */
-#define MASK_NO_FP_IN_TOC 0x80
+#define MASK_NO_FP_IN_TOC 0x00000080
/* Disable placing symbol+offset constants in the TOC; can be turned on when
the TOC overflows. */
-#define MASK_NO_SUM_IN_TOC 0x100
+#define MASK_NO_SUM_IN_TOC 0x00000100
/* Output only one TOC entry per module. Normally linking fails if
there are more than 16K unique variables/constants in an executable. With
@@ -133,26 +242,28 @@ extern int target_flags;
if there are more than 16K unique variables/constant in a single module.
This is at the cost of having 2 extra loads and one extra store per
- function, and one less allocatable register. */
-#define MASK_MINIMAL_TOC 0x200
+ function, and one less allocable register. */
+#define MASK_MINIMAL_TOC 0x00000200
/* Nonzero for the 64bit model: ints, longs, and pointers are 64 bits. */
-#define MASK_64BIT 0x400
+#define MASK_64BIT 0x00000400
/* Disable use of FPRs. */
-#define MASK_SOFT_FLOAT 0x800
+#define MASK_SOFT_FLOAT 0x00000800
/* Enable load/store multiple, even on powerpc */
-#define MASK_MULTIPLE 0x1000
-#define MASK_MULTIPLE_SET 0x2000
+#define MASK_MULTIPLE 0x00001000
+#define MASK_MULTIPLE_SET 0x00002000
/* Use string instructions for block moves */
-#define MASK_STRING 0x4000
-#define MASK_STRING_SET 0x8000
+#define MASK_STRING 0x00004000
+#define MASK_STRING_SET 0x00008000
+
+/* Disable update form of load/store */
+#define MASK_NO_UPDATE 0x00010000
-/* Temporary debug switches */
-#define MASK_DEBUG_STACK 0x10000
-#define MASK_DEBUG_ARG 0x20000
+/* Disable fused multiply/add operations */
+#define MASK_NO_FUSED_MADD 0x00020000
#define TARGET_POWER (target_flags & MASK_POWER)
#define TARGET_POWER2 (target_flags & MASK_POWER2)
@@ -170,10 +281,13 @@ extern int target_flags;
#define TARGET_MULTIPLE_SET (target_flags & MASK_MULTIPLE_SET)
#define TARGET_STRING (target_flags & MASK_STRING)
#define TARGET_STRING_SET (target_flags & MASK_STRING_SET)
-#define TARGET_DEBUG_STACK (target_flags & MASK_DEBUG_STACK)
-#define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG)
+#define TARGET_NO_UPDATE (target_flags & MASK_NO_UPDATE)
+#define TARGET_NO_FUSED_MADD (target_flags & MASK_NO_FUSED_MADD)
+#define TARGET_32BIT (! TARGET_64BIT)
#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
+#define TARGET_UPDATE (! TARGET_NO_UPDATE)
+#define TARGET_FUSED_MADD (! TARGET_NO_FUSED_MADD)
/* Pseudo target to indicate whether the object format is ELF
(to get around not having conditional compilation in the md file) */
@@ -187,6 +301,29 @@ extern int target_flags;
#define TARGET_TOC 1
#endif
+/* Pseudo target to say whether this is Windows NT */
+#ifndef TARGET_WINDOWS_NT
+#define TARGET_WINDOWS_NT 0
+#endif
+
+/* Pseudo target to say whether this is MAC */
+#ifndef TARGET_MACOS
+#define TARGET_MACOS 0
+#endif
+
+/* Pseudo target to say whether this is AIX */
+#ifndef TARGET_AIX
+#if (TARGET_ELF || TARGET_WINDOWS_NT || TARGET_MACOS)
+#define TARGET_AIX 0
+#else
+#define TARGET_AIX 1
+#endif
+#endif
+
+#ifndef TARGET_XL_CALL
+#define TARGET_XL_CALL 0
+#endif
+
/* Run-time compilation parameters selecting different hardware subsets.
Macro to define tables used to set the flags.
@@ -233,8 +370,10 @@ extern int target_flags;
{"string", MASK_STRING | MASK_STRING_SET}, \
{"no-string", - MASK_STRING}, \
{"no-string", MASK_STRING_SET}, \
- {"debug-stack", MASK_DEBUG_STACK}, \
- {"debug-arg", MASK_DEBUG_ARG}, \
+ {"update", - MASK_NO_UPDATE}, \
+ {"no-update", MASK_NO_UPDATE}, \
+ {"fused-madd", - MASK_NO_FUSED_MADD}, \
+ {"no-fused-madd", MASK_NO_FUSED_MADD}, \
SUBTARGET_SWITCHES \
{"", TARGET_DEFAULT}}
@@ -244,6 +383,7 @@ extern int target_flags;
enum processor_type
{PROCESSOR_RIOS1,
PROCESSOR_RIOS2,
+ PROCESSOR_MPCCORE,
PROCESSOR_PPC403,
PROCESSOR_PPC601,
PROCESSOR_PPC603,
@@ -258,7 +398,7 @@ extern enum processor_type rs6000_cpu;
/* Define generic processor types based upon current deployment. */
#define PROCESSOR_COMMON PROCESSOR_PPC601
#define PROCESSOR_POWER PROCESSOR_RIOS1
-#define PROCESSOR_POWERPC PROCESSOR_PPC601
+#define PROCESSOR_POWERPC PROCESSOR_PPC604
/* Define the default processor. This is overridden by other tm.h files. */
#define PROCESSOR_DEFAULT PROCESSOR_RIOS1
@@ -284,10 +424,38 @@ extern enum processor_type rs6000_cpu;
extern char *m88k_short_data;
#define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */
-#define TARGET_OPTIONS \
-{ {"cpu=", &rs6000_cpu_string}}
+/* This is meant to be overridden in target specific files. */
+#ifndef SUBTARGET_OPTIONS
+#define SUBTARGET_OPTIONS
+#endif
+
+#define TARGET_OPTIONS \
+{ \
+ {"cpu=", &rs6000_select[1].string}, \
+ {"tune=", &rs6000_select[2].string}, \
+ {"debug-", &rs6000_debug_name}, \
+ {"debug=", &rs6000_debug_name}, \
+ SUBTARGET_OPTIONS \
+}
+
+/* rs6000_select[0] is reserved for the default cpu defined via --with-cpu */
+struct rs6000_cpu_select
+{
+ char *string;
+ char *name;
+ int set_tune_p;
+ int set_arch_p;
+};
+
+extern struct rs6000_cpu_select rs6000_select[];
+
+/* Debug support */
+extern char *rs6000_debug_name; /* Name for -mdebug-xxxx option */
+extern int rs6000_debug_stack; /* debug stack applications */
+extern int rs6000_debug_arg; /* debug argument handling */
-extern char *rs6000_cpu_string;
+#define TARGET_DEBUG_STACK rs6000_debug_stack
+#define TARGET_DEBUG_ARG rs6000_debug_arg
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -297,7 +465,7 @@ extern char *rs6000_cpu_string;
On the RS/6000 this is used to define the target cpu type. */
-#define OVERRIDE_OPTIONS rs6000_override_options ()
+#define OVERRIDE_OPTIONS rs6000_override_options (TARGET_CPU_DEFAULT)
/* Show we can debug even without a frame pointer. */
#define CAN_DEBUG_WITHOUT_FP
@@ -308,7 +476,7 @@ extern char *rs6000_cpu_string;
#define REAL_ARITHMETIC
/* 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,
+ in a wider mode than that declared by the program. In such cases,
the value is constrained to be within the bounds of the declared
type, but kept valid in the wider mode. The signedness of the
extension may differ from that of the type. */
@@ -328,7 +496,7 @@ extern char *rs6000_cpu_string;
#define BYTES_BIG_ENDIAN 1
/* Define this if most significant word of a multiword number is lowest
- numbered.
+ numbered.
For RS/6000 we can decide arbitrarily since there are no machine
instructions for them. Might as well be consistent with bits and bytes. */
@@ -341,11 +509,11 @@ extern char *rs6000_cpu_string;
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_POWERPC64 ? 64 : 32)
+#define BITS_PER_WORD (! TARGET_POWERPC64 ? 32 : 64)
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
-#define UNITS_PER_WORD (TARGET_POWERPC64 ? 8 : 4)
+#define UNITS_PER_WORD (! TARGET_POWERPC64 ? 4 : 8)
#define MIN_UNITS_PER_WORD 4
#define UNITS_PER_FP_WORD 8
@@ -367,13 +535,12 @@ extern char *rs6000_cpu_string;
/* A C expression for the size in bits of the type `int' on the
target machine. If you don't define this, the default is one
word. */
-#define INT_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
-#define MAX_INT_TYPE_SIZE 64
+#define INT_TYPE_SIZE 32
/* A C expression for the size in bits of the type `long' on the
target machine. If you don't define this, the default is one
word. */
-#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
+#define LONG_TYPE_SIZE (TARGET_32BIT ? 32 : 64)
#define MAX_LONG_TYPE_SIZE 64
/* A C expression for the size in bits of the type `long long' on the
@@ -404,10 +571,10 @@ extern char *rs6000_cpu_string;
/* Width in bits of a pointer.
See also the macro `Pmode' defined below. */
-#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
+#define POINTER_SIZE (TARGET_32BIT ? 32 : 64)
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
-#define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32)
+#define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
/* Boundary (in *bits*) on which stack pointer should be aligned. */
#define STACK_BOUNDARY 64
@@ -416,7 +583,11 @@ extern char *rs6000_cpu_string;
#define FUNCTION_BOUNDARY 32
/* No data type wants to be aligned rounder than this. */
-#define BIGGEST_ALIGNMENT (TARGET_64BIT ? 64 : 32)
+#define BIGGEST_ALIGNMENT 64
+
+/* AIX word-aligns FP doubles but doubleword-aligns 64-bit ints. */
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
+ (DECL_MODE (FIELD) != DFmode ? (COMPUTED) : MIN ((COMPUTED), 32))
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 32
@@ -427,6 +598,17 @@ extern char *rs6000_cpu_string;
/* A bitfield declared as `int' forces `int' alignment for the struct. */
#define PCC_BITFIELD_TYPE_MATTERS 1
+/* AIX increases natural record alignment to doubleword if the first
+ field is an FP double while the FP fields remain word aligned. */
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
+ ((TREE_CODE (STRUCT) == RECORD_TYPE \
+ || TREE_CODE (STRUCT) == UNION_TYPE \
+ || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
+ && TYPE_FIELDS (STRUCT) != 0 \
+ && DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode \
+ ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
+ : MAX ((COMPUTED), (SPECIFIED)))
+
/* Make strings word-aligned so strcpy from constants will be faster. */
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
(TREE_CODE (EXP) == STRING_CST \
@@ -457,14 +639,19 @@ extern char *rs6000_cpu_string;
In addition, the difference between the frame and argument pointers is
a function of the number of registers saved, so we need to have a
register for AP that will later be eliminated in favor of SP or FP.
- This is a normal register, but it is fixed. */
+ This is a normal register, but it is fixed.
+
+ We also create a pseudo register for float/int conversions, that will
+ really represent the memory location used. It is represented here as
+ a register, in order to work around problems in allocating stack storage
+ in inline functions. */
-#define FIRST_PSEUDO_REGISTER 76
+#define FIRST_PSEUDO_REGISTER 77
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
- On RS/6000, r1 is used for the stack and r2 is used as the TOC pointer.
+ On RS/6000, r1 is used for the stack and r2 is used as the TOC pointer.
cr5 is not supposed to be used.
@@ -479,7 +666,7 @@ extern char *rs6000_cpu_string;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 1, 0, 0}
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
@@ -493,7 +680,7 @@ extern char *rs6000_cpu_string;
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, 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, 1, 1, 1}
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1}
/* List the order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS.
@@ -530,7 +717,7 @@ extern char *rs6000_cpu_string;
31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
18, 17, 16, 15, 14, 13, 12, \
64, 66, 65, \
- 73, 1, 2, 67}
+ 73, 1, 2, 67, 76}
/* True if register is floating-point. */
#define FP_REGNO_P(N) ((N) >= 32 && (N) <= 63)
@@ -541,6 +728,10 @@ extern char *rs6000_cpu_string;
/* True if register is an integer register. */
#define INT_REGNO_P(N) ((N) <= 31 || (N) == 67)
+/* True if register is the temporary memory location used for int/float
+ conversion. */
+#define FPMEM_REGNO_P(N) ((N) == FPMEM_REGNUM)
+
/* 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
@@ -549,8 +740,8 @@ extern char *rs6000_cpu_string;
On RS/6000, ordinary registers hold 32 bits worth;
a single floating point register holds 64 bits worth. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- (FP_REGNO_P (REGNO) \
+#define HARD_REGNO_NREGS(REGNO, MODE) \
+ (FP_REGNO_P (REGNO) || FPMEM_REGNO_P (REGNO) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
@@ -560,13 +751,14 @@ extern char *rs6000_cpu_string;
can hold CC modes. We cannot put TImode anywhere except general
register and it must be able to fit within the register set. */
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (FP_REGNO_P (REGNO) ? \
- (GET_MODE_CLASS (MODE) == MODE_FLOAT \
- || (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \
- : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \
- : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ (FP_REGNO_P (REGNO) ? \
+ (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ || (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \
+ : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \
+ : FPMEM_REGNO_P (REGNO) ? ((MODE) == DImode || (MODE) == DFmode) \
+ : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT \
&& GET_MODE_SIZE (MODE) <= UNITS_PER_WORD) \
: 1)
@@ -600,7 +792,7 @@ extern char *rs6000_cpu_string;
|| (CLASS1) == LINK_OR_CTR_REGS) \
&& ((CLASS2) == SPECIAL_REGS || (CLASS2) == MQ_REGS \
|| (CLASS2) == LINK_REGS || (CLASS2) == CTR_REGS \
- || (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \
+ || (CLASS2) == LINK_OR_CTR_REGS)) ? 10 \
: 2)
/* A C expressions returning the cost of moving data of MODE from a register to
@@ -670,10 +862,22 @@ extern char *rs6000_cpu_string;
/* Place to put static chain when calling a function that requires it. */
#define STATIC_CHAIN_REGNUM 11
+/* count register number for special purposes */
+#define COUNT_REGISTER_REGNUM 66
+
+/* Special register that represents memory, used for float/int conversions. */
+#define FPMEM_REGNUM 76
+
+/* Register to use as a placeholder for the GOT/allocated TOC register.
+ FINALIZE_PIC will change all uses of this register to a an appropriate
+ pseudo register when it adds the code to setup the GOT. We use r2
+ because it is a reserved register in all of the ABI's. */
+#define GOT_TOC_REGNUM 2
+
/* Place that structure value return address is placed.
On the RS/6000, it is passed as an extra parameter. */
-#define STRUCT_VALUE 0
+#define STRUCT_VALUE 0
/* Define the classes of registers for register constraints in the
machine description. Also define ranges of constants.
@@ -694,7 +898,7 @@ extern char *rs6000_cpu_string;
For any two classes, it is very desirable that there be another
class that represents their union. */
-
+
/* The RS/6000 has three types of registers, fixed-point, floating-point,
and condition registers, plus three special registers, MQ, CTR, and the
link register.
@@ -703,49 +907,103 @@ extern char *rs6000_cpu_string;
So make a class for registers valid as base registers.
Also, cr0 is the only condition code register that can be used in
- arithmetic insns, so make a separate class for it. */
+ arithmetic insns, so make a separate class for it.
-enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
- NON_SPECIAL_REGS, MQ_REGS, LINK_REGS, CTR_REGS, LINK_OR_CTR_REGS,
- SPECIAL_REGS, SPEC_OR_GEN_REGS, CR0_REGS, CR_REGS, NON_FLOAT_REGS,
- ALL_REGS, LIM_REG_CLASSES };
+ There is a special 'register' (76), which is not a register, but a
+ placeholder for memory allocated to convert between floating point and
+ integral types. This works around a problem where if we allocate memory
+ with allocate_stack_{local,temp} and the function is an inline function, the
+ memory allocated will clobber memory in the caller. So we use a special
+ register, and if that is used, we allocate stack space for it. */
+
+enum reg_class
+{
+ NO_REGS,
+ BASE_REGS,
+ GENERAL_REGS,
+ FLOAT_REGS,
+ NON_SPECIAL_REGS,
+ MQ_REGS,
+ LINK_REGS,
+ CTR_REGS,
+ LINK_OR_CTR_REGS,
+ SPECIAL_REGS,
+ SPEC_OR_GEN_REGS,
+ CR0_REGS,
+ CR_REGS,
+ NON_FLOAT_REGS,
+ FPMEM_REGS,
+ FLOAT_OR_FPMEM_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", "BASE_REGS", "GENERAL_REGS", "FLOAT_REGS", \
- "NON_SPECIAL_REGS", "MQ_REGS", "LINK_REGS", "CTR_REGS", \
- "LINK_OR_CTR_REGS", "SPECIAL_REGS", "SPEC_OR_GEN_REGS", \
- "CR0_REGS", "CR_REGS", "NON_FLOAT_REGS", "ALL_REGS" }
+#define REG_CLASS_NAMES \
+{ \
+ "NO_REGS", \
+ "BASE_REGS", \
+ "GENERAL_REGS", \
+ "FLOAT_REGS", \
+ "NON_SPECIAL_REGS", \
+ "MQ_REGS", \
+ "LINK_REGS", \
+ "CTR_REGS", \
+ "LINK_OR_CTR_REGS", \
+ "SPECIAL_REGS", \
+ "SPEC_OR_GEN_REGS", \
+ "CR0_REGS", \
+ "CR_REGS", \
+ "NON_FLOAT_REGS", \
+ "FPMEM_REGS", \
+ "FLOAT_OR_FPMEM_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}, {0xfffffffe, 0, 8}, {~0, 0, 8}, \
- {0, ~0, 0}, {~0, ~0, 8}, {0, 0, 1}, {0, 0, 2}, \
- {0, 0, 4}, {0, 0, 6}, {0, 0, 7}, {~0, 0, 15}, \
- {0, 0, 16}, {0, 0, 0xff0}, {~0, 0, 0xffff}, \
- {~0, ~0, 0xffff} }
+#define REG_CLASS_CONTENTS \
+{ \
+ { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0xfffffffe, 0x00000000, 0x00000008 }, /* BASE_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000008 }, /* GENERAL_REGS */ \
+ { 0x00000000, 0xffffffff, 0x00000000 }, /* FLOAT_REGS */ \
+ { 0xffffffff, 0xffffffff, 0x00000008 }, /* NON_SPECIAL_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000001 }, /* MQ_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000002 }, /* LINK_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000004 }, /* CTR_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000006 }, /* LINK_OR_CTR_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000007 }, /* SPECIAL_REGS */ \
+ { 0xffffffff, 0x00000000, 0x0000000f }, /* SPEC_OR_GEN_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000010 }, /* CR0_REGS */ \
+ { 0x00000000, 0x00000000, 0x00000ff0 }, /* CR_REGS */ \
+ { 0xffffffff, 0x00000000, 0x0000ffff }, /* NON_FLOAT_REGS */ \
+ { 0x00000000, 0x00000000, 0x00010000 }, /* FPMEM_REGS */ \
+ { 0x00000000, 0xffffffff, 0x00010000 }, /* FLOAT_OR_FPMEM_REGS */ \
+ { 0xffffffff, 0xffffffff, 0x0001ffff } /* ALL_REGS */ \
+}
/* 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. */
-#define REGNO_REG_CLASS(REGNO) \
- ((REGNO) == 0 ? GENERAL_REGS \
- : (REGNO) < 32 ? BASE_REGS \
- : FP_REGNO_P (REGNO) ? FLOAT_REGS \
- : (REGNO) == 68 ? CR0_REGS \
- : CR_REGNO_P (REGNO) ? CR_REGS \
- : (REGNO) == 64 ? MQ_REGS \
- : (REGNO) == 65 ? LINK_REGS \
- : (REGNO) == 66 ? CTR_REGS \
- : (REGNO) == 67 ? BASE_REGS \
+#define REGNO_REG_CLASS(REGNO) \
+ ((REGNO) == 0 ? GENERAL_REGS \
+ : (REGNO) < 32 ? BASE_REGS \
+ : FP_REGNO_P (REGNO) ? FLOAT_REGS \
+ : (REGNO) == 68 ? CR0_REGS \
+ : CR_REGNO_P (REGNO) ? CR_REGS \
+ : (REGNO) == 64 ? MQ_REGS \
+ : (REGNO) == 65 ? LINK_REGS \
+ : (REGNO) == 66 ? CTR_REGS \
+ : (REGNO) == 67 ? BASE_REGS \
+ : (REGNO) == 76 ? FPMEM_REGS \
: NO_REGS)
/* The class value for index registers, and the one for base regs. */
@@ -763,6 +1021,7 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
: (C) == 'l' ? LINK_REGS \
: (C) == 'x' ? CR0_REGS \
: (C) == 'y' ? CR_REGS \
+ : (C) == 'z' ? FPMEM_REGS \
: NO_REGS)
/* The letters I, J, K, L, M, N, and P in a register constraint string
@@ -771,7 +1030,7 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
C is the letter, and VALUE is a constant value.
Return 1 if VALUE is in the range specified by C.
- `I' is signed 16-bit constants
+ `I' is signed 16-bit constants
`J' is a constant with only the high-order 16 bits non-zero
`K' is a constant with only the low-order 16 bits non-zero
`L' is a constant that can be placed into a mask operand
@@ -780,49 +1039,61 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
`O' is the constant zero
`P' is a constant whose negation is a signed 16-bit constant */
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ( (C) == 'I' ? (unsigned) ((VALUE) + 0x8000) < 0x10000 \
- : (C) == 'J' ? ((VALUE) & 0xffff) == 0 \
- : (C) == 'K' ? ((VALUE) & 0xffff0000) == 0 \
- : (C) == 'L' ? mask_constant (VALUE) \
- : (C) == 'M' ? (VALUE) > 31 \
- : (C) == 'N' ? exact_log2 (VALUE) >= 0 \
- : (C) == 'O' ? (VALUE) == 0 \
- : (C) == 'P' ? (unsigned) ((- (VALUE)) + 0x8000) < 0x1000 \
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
+ ( (C) == 'I' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \
+ : (C) == 'J' ? ((VALUE) & 0xffff) == 0 \
+ : (C) == 'K' ? ((VALUE) & 0xffff0000) == 0 \
+ : (C) == 'L' ? mask_constant (VALUE) \
+ : (C) == 'M' ? (VALUE) > 31 \
+ : (C) == 'N' ? exact_log2 (VALUE) >= 0 \
+ : (C) == 'O' ? (VALUE) == 0 \
+ : (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x1000 \
: 0)
/* Similar, but for floating constants, and defining letters G and H.
Here VALUE is the CONST_DOUBLE rtx itself.
We flag for special constants when we can copy the constant into
- a general register in two insns for DF and one insn for SF. */
+ a general register in two insns for DF/DI and one insn for SF.
+
+ 'H' is used for DI/DF constants that take 3 insns. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? easy_fp_constant (VALUE, GET_MODE (VALUE)) : 0)
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+ ( (C) == 'G' ? (num_insns_constant (VALUE, GET_MODE (VALUE)) \
+ == ((GET_MODE (VALUE) == SFmode) ? 1 : 2)) \
+ : (C) == 'H' ? (num_insns_constant (VALUE, GET_MODE (VALUE)) == 3) \
+ : 0)
/* Optional extra constraints for this machine.
- For the RS/6000, `Q' means that this is a memory operand that is just
- an offset from a register. */
+ 'Q' means that is a memory operand that is just an offset from a reg.
+ 'R' is for AIX TOC entries.
+ 'S' is for Windows NT SYMBOL_REFs
+ 'T' is for Windows NT LABEL_REFs.
+ 'U' is for V.4 small data references. */
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
: (C) == 'R' ? LEGITIMATE_CONSTANT_POOL_ADDRESS_P (OP) \
+ : (C) == 'S' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == SYMBOL_REF)\
+ : (C) == 'T' ? (TARGET_WINDOWS_NT && DEFAULT_ABI == ABI_NT && GET_CODE (OP) == LABEL_REF) \
+ : (C) == 'U' ? ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) \
+ && small_data_operand (OP, GET_MODE (OP))) \
: 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.
+ in some cases it is preferable to use a more restrictive class.
On the RS/6000, we have to return NO_REGS when we want to reload a
floating-point CONST_DOUBLE to force it to be copied to memory. */
-#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
((GET_CODE (X) == CONST_DOUBLE \
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
? NO_REGS : (CLASS))
-
+
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
@@ -841,15 +1112,16 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
On RS/6000, this is the size of MODE in words,
except in the FP regs, where a single reg is enough for two words. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- ((CLASS) == FLOAT_REGS \
+#define CLASS_MAX_NREGS(CLASS, MODE) \
+ (((CLASS) == FLOAT_REGS || (CLASS) == FPMEM_REGS \
+ || (CLASS) == FLOAT_OR_FPMEM_REGS) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* If defined, gives a class of registers that cannot be used as the
operand of a SUBREG that changes the size of the object. */
-#define CLASS_CANNOT_CHANGE_SIZE FLOAT_REGS
+#define CLASS_CANNOT_CHANGE_SIZE FLOAT_OR_FPMEM_REGS
/* Stack layout; function entry, exit and calling. */
@@ -857,32 +1129,55 @@ enum reg_class { NO_REGS, BASE_REGS, GENERAL_REGS, FLOAT_REGS,
enum rs6000_abi {
ABI_NONE,
ABI_AIX, /* IBM's AIX */
- ABI_V4 /* System V.4/eabi */
+ ABI_AIX_NODESC, /* AIX calling sequence minus function descriptors */
+ ABI_V4, /* System V.4/eabi */
+ ABI_NT, /* Windows/NT */
+ ABI_SOLARIS /* Solaris */
};
+extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
+
+/* Default ABI to compile code for */
+#ifndef DEFAULT_ABI
+#define DEFAULT_ABI ABI_AIX
+/* The prefix to add to user-visible assembler symbols. */
+#define USER_LABEL_PREFIX "."
+#endif
+
/* Structure used to define the rs6000 stack */
typedef struct rs6000_stack {
int first_gp_reg_save; /* first callee saved GP register used */
int first_fp_reg_save; /* first callee saved FP register used */
int lr_save_p; /* true if the link reg needs to be saved */
int cr_save_p; /* true if the CR reg needs to be saved */
+ int toc_save_p; /* true if the TOC needs to be saved */
int push_p; /* true if we need to allocate stack space */
int calls_p; /* true if the function makes any calls */
+ int main_p; /* true if this is main */
+ int main_save_p; /* true if this is main and we need to save args */
+ int fpmem_p; /* true if float/int conversion temp needed */
enum rs6000_abi abi; /* which ABI to use */
int gp_save_offset; /* offset to save GP regs from initial SP */
int fp_save_offset; /* offset to save FP regs from initial SP */
int lr_save_offset; /* offset to save LR from initial SP */
int cr_save_offset; /* offset to save CR from initial SP */
+ int toc_save_offset; /* offset to save the TOC pointer */
int varargs_save_offset; /* offset to save the varargs registers */
+ int main_save_offset; /* offset to save main's args */
+ int fpmem_offset; /* offset for float/int conversion temp */
int reg_size; /* register size (4 or 8) */
int varargs_size; /* size to hold V.4 args passed in regs */
int vars_size; /* variable save area size */
int parm_size; /* outgoing parameter size */
+ int main_size; /* size to hold saving main's args */
int save_size; /* save area size */
int fixed_size; /* fixed size of stack frame */
int gp_size; /* size of saved GP registers */
int fp_size; /* size of saved FP registers */
int cr_size; /* size to hold CR if not in save_size */
+ int lr_size; /* size to hold LR if not in save_size */
+ int fpmem_size; /* size to hold float/int conversion */
+ int toc_size; /* size to hold TOC if not in save_size */
int total_size; /* total bytes allocated for stack */
} rs6000_stack_t;
@@ -900,10 +1195,18 @@ typedef struct rs6000_stack {
/* #define FRAME_GROWS_DOWNWARD */
/* Size of the outgoing register save area */
-#define RS6000_REG_SAVE (TARGET_64BIT ? 64 : 32)
+#define RS6000_REG_SAVE (TARGET_32BIT ? 32 : 64)
/* Size of the fixed area on the stack */
-#define RS6000_SAVE_AREA (TARGET_64BIT ? 48 : 24)
+#define RS6000_SAVE_AREA (TARGET_32BIT ? 24 : 48)
+
+/* Address to save the TOC register */
+#define RS6000_SAVE_TOC plus_constant (stack_pointer_rtx, 20)
+
+/* Offset & size for fpmem stack locations used for converting between
+ float and integral types. */
+extern int rs6000_fpmem_offset;
+extern int rs6000_fpmem_size;
/* Size of the V.4 varargs area if needed */
#define RS6000_VARARGS_AREA 0
@@ -912,28 +1215,44 @@ typedef struct rs6000_stack {
extern int rs6000_sysv_varargs_p;
/* Align an address */
-#define ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
+#define RS6000_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
+
+/* Initialize data used by insn expanders. This is called from
+ init_emit, once for each function, before code is generated. */
+#define INIT_EXPANDERS rs6000_init_expanders ()
/* Size of V.4 varargs area in bytes */
#define RS6000_VARARGS_SIZE \
- ((GP_ARG_NUM_REG * (TARGET_64BIT ? 8 : 4)) + (FP_ARG_NUM_REG * 8) + 8)
+ ((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8)
/* Offset of V.4 varargs area */
-#define RS6000_VARARGS_OFFSET \
- (ALIGN (current_function_outgoing_args_size, 8) + RS6000_SAVE_AREA)
+#define RS6000_VARARGS_OFFSET \
+ (RS6000_ALIGN (current_function_outgoing_args_size, 8) \
+ + RS6000_SAVE_AREA)
/* 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.
+ of the first local allocated.
On the RS/6000, the frame pointer is the same as the stack pointer,
except for dynamic allocations. So we start after the fixed area and
outgoing parameter area. */
-#define STARTING_FRAME_OFFSET (ALIGN (current_function_outgoing_args_size, 8) \
- + RS6000_VARARGS_AREA \
- + RS6000_SAVE_AREA)
+#define STARTING_FRAME_OFFSET \
+ (RS6000_ALIGN (current_function_outgoing_args_size, 8) \
+ + RS6000_VARARGS_AREA \
+ + RS6000_SAVE_AREA)
+
+/* Offset from the stack pointer register to an item dynamically
+ allocated on the stack, e.g., by `alloca'.
+
+ The default value for this macro is `STACK_POINTER_OFFSET' plus the
+ length of the outgoing arguments. The default is correct for most
+ machines. See `function.c' for details. */
+#define STACK_DYNAMIC_OFFSET(FUNDECL) \
+ (RS6000_ALIGN (current_function_outgoing_args_size, 8) \
+ + (STACK_POINTER_OFFSET))
/* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by.
@@ -978,7 +1297,7 @@ extern int rs6000_sysv_varargs_p;
If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is 0.
- On RS/6000 an integer value is in r3 and a floating-point value is in
+ On RS/6000 an integer value is in r3 and a floating-point value is in
fp1, unless -msoft-float. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
@@ -994,10 +1313,12 @@ extern int rs6000_sysv_varargs_p;
/* The definition of this macro implies that there are cases where
a scalar value cannot be returned in registers.
- For the RS/6000, any structure or union type is returned in memory. */
+ For the RS/6000, any structure or union type is returned in memory, except for
+ Solaris, which returns structures <= 8 bytes in registers. */
-#define RETURN_IN_MEMORY(TYPE) \
- (TYPE_MODE (TYPE) == BLKmode)
+#define RETURN_IN_MEMORY(TYPE) \
+ (TYPE_MODE (TYPE) == BLKmode \
+ && (DEFAULT_ABI != ABI_SOLARIS || int_size_in_bytes (TYPE) > 8))
/* Minimum and maximum general purpose registers used to hold arguments. */
#define GP_ARG_MIN_REG 3
@@ -1006,13 +1327,22 @@ extern int rs6000_sysv_varargs_p;
/* Minimum and maximum floating point registers used to hold arguments. */
#define FP_ARG_MIN_REG 33
-#define FP_ARG_MAX_REG 45
+#define FP_ARG_AIX_MAX_REG 45
+#define FP_ARG_V4_MAX_REG 40
+#define FP_ARG_MAX_REG FP_ARG_AIX_MAX_REG
#define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
/* Return registers */
#define GP_ARG_RETURN GP_ARG_MIN_REG
#define FP_ARG_RETURN FP_ARG_MIN_REG
+/* Flags for the call/call_value rtl operations set up by function_arg */
+#define CALL_NORMAL 0x00000000 /* no special processing */
+#define CALL_NT_DLLIMPORT 0x00000001 /* NT, this is a DLL import call */
+#define CALL_V4_CLEAR_FP_ARGS 0x00000002 /* V.4, no FP args passed */
+#define CALL_V4_SET_FP_ARGS 0x00000004 /* V.4, FP args were passed */
+#define CALL_LONG 0x00000008 /* always call indirect */
+
/* Define cutoff for using external functions to save floating point */
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) == 62 || (FIRST_REG) == 63)
@@ -1052,6 +1382,7 @@ typedef struct rs6000_args
int orig_nargs; /* Original value of nargs_prototype */
int varargs_offset; /* offset of the varargs save area */
int prototype; /* Whether a prototype was defined */
+ int call_cookie; /* Do special things for this call */
} CUMULATIVE_ARGS;
/* Define intermediate macro to compute the size (in registers) of an argument
@@ -1067,7 +1398,7 @@ typedef struct rs6000_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, FALSE)
/* Similar, but when scanning the definition of a procedure. We always
@@ -1130,8 +1461,24 @@ typedef struct rs6000_args
#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. */
+
+#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
+ function_arg_boundary (MODE, TYPE)
+
/* Perform any needed actions needed for a function that is receiving a
- variable number of arguments.
+ variable number of arguments.
CUM is as above.
@@ -1198,44 +1545,47 @@ typedef struct rs6000_args
#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.
-
- The trampoline should set the static chain pointer to value placed
- into the trampoline and should branch to the specified routine.
-
- On the RS/6000, this is not code at all, but merely a data area,
- since that is the way all functions are called. The first word is
- the address of the function, the second word is the TOC pointer (r2),
- and the third word is the static chain value. */
-
-#define TRAMPOLINE_TEMPLATE(FILE) { fprintf (FILE, "\t.long 0, 0, 0\n"); }
+/* TRAMPOLINE_TEMPLATE deleted */
/* Length in units of the trampoline for entering a nested function. */
-#define TRAMPOLINE_SIZE 12
+#define TRAMPOLINE_SIZE rs6000_trampoline_size ()
/* 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. */
#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, \
- memory_address (SImode, (ADDR))), \
- gen_rtx (MEM, SImode, \
- memory_address (SImode, (FNADDR)))); \
- emit_move_insn (gen_rtx (MEM, SImode, \
- memory_address (SImode, \
- plus_constant ((ADDR), 4))), \
- gen_rtx (MEM, SImode, \
- memory_address (SImode, \
- plus_constant ((FNADDR), 4)))); \
- emit_move_insn (gen_rtx (MEM, SImode, \
- memory_address (SImode, \
- plus_constant ((ADDR), 8))), \
- force_reg (SImode, (CXT))); \
-}
+ rs6000_initialize_trampoline (ADDR, FNADDR, CXT)
+
+/* If defined, a C expression whose value is nonzero if IDENTIFIER
+ with arguments ARGS is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, NAME, ARGS) \
+ (rs6000_valid_decl_attribute_p (DECL, ATTRIBUTES, NAME, ARGS))
+
+/* If defined, a C expression whose value is nonzero if IDENTIFIER
+ with arguments ARGS is a valid machine specific attribute for TYPE.
+ The attributes in ATTRIBUTES have previously been assigned to TYPE. */
+
+#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, NAME, ARGS) \
+ (rs6000_valid_type_attribute_p (TYPE, ATTRIBUTES, NAME, ARGS))
+
+/* If defined, a C expression whose value is zero if the attributes on
+ TYPE1 and TYPE2 are incompatible, one if they are compatible, and
+ two if they are nearly compatible (which causes a warning to be
+ generated). */
+
+#define COMP_TYPE_ATTRIBUTES(TYPE1, TYPE2) \
+ (rs6000_comp_type_attributes (TYPE1, TYPE2))
+
+/* If defined, a C statement that assigns default attributes to newly
+ defined TYPE. */
+
+#define SET_DEFAULT_TYPE_ATTRIBUTES(TYPE) \
+ (rs6000_set_default_type_attributes (TYPE))
+
/* Definitions for __builtin_return_address and __builtin_frame_address.
__builtin_return_address (0) should give link register (65), enable
@@ -1247,13 +1597,16 @@ typedef struct rs6000_args
(mrs) */
/* #define RETURN_ADDR_IN_PREVIOUS_FRAME */
-/* Number of bytes into the frame return addresses can be found. */
-#ifndef TARGET_V4_CALLS
-#define RETURN_ADDRESS_OFFSET 8
-#else
-#define RETURN_ADDRESS_OFFSET \
- ((TARGET_V4_CALLS) ? (TARGET_64BIT ? 8 : 4) : 8)
-#endif
+/* Number of bytes into the frame return addresses can be found. See
+ rs6000_stack_info in rs6000.c for more information on how the different
+ abi's store the return address. */
+#define RETURN_ADDRESS_OFFSET \
+ ((DEFAULT_ABI == ABI_AIX \
+ || DEFAULT_ABI == ABI_AIX_NODESC) ? 8 : \
+ (DEFAULT_ABI == ABI_V4 \
+ || DEFAULT_ABI == ABI_SOLARIS) ? (TARGET_32BIT ? 4 : 8) : \
+ (DEFAULT_ABI == ABI_NT) ? -4 : \
+ (fatal ("RETURN_ADDRESS_OFFSET not supported"), 0))
/* The current return address is in link register (65). The return address
of anything farther back is accessed normally at an offset of 8 from the
@@ -1416,13 +1769,15 @@ typedef struct rs6000_args
plus a constant), a short (16-bit signed) constant plus a register,
the sum of two registers, or a register indirect, possibly with an
auto-increment. For DFmode and DImode with an constant plus register,
- we must ensure that both words are addressable. */
+ we must ensure that both words are addressable or PowerPC64 with offset
+ word aligned. */
#define LEGITIMATE_CONSTANT_POOL_BASE_P(X) \
(TARGET_TOC && GET_CODE (X) == SYMBOL_REF \
&& CONSTANT_POOL_ADDRESS_P (X) \
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (X)))
+/* TARGET_64BIT TOC64 guaranteed to have 64 bit alignment. */
#define LEGITIMATE_CONSTANT_POOL_ADDRESS_P(X) \
(LEGITIMATE_CONSTANT_POOL_BASE_P (X) \
|| (TARGET_TOC \
@@ -1430,9 +1785,15 @@ typedef struct rs6000_args
&& GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
&& LEGITIMATE_CONSTANT_POOL_BASE_P (XEXP (XEXP (X, 0), 0))))
+#define LEGITIMATE_SMALL_DATA_P(MODE, X) \
+ ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) \
+ && !flag_pic && !TARGET_TOC \
+ && (GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == CONST) \
+ && small_data_operand (X, MODE))
+
#define LEGITIMATE_ADDRESS_INTEGER_P(X,OFFSET) \
(GET_CODE (X) == CONST_INT \
- && (unsigned) (INTVAL (X) + (OFFSET) + 0x8000) < 0x10000)
+ && (unsigned HOST_WIDE_INT) (INTVAL (X) + (OFFSET) + 0x8000) < 0x10000)
#define LEGITIMATE_OFFSET_ADDRESS_P(MODE,X) \
(GET_CODE (X) == PLUS \
@@ -1440,7 +1801,14 @@ typedef struct rs6000_args
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
&& LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0) \
&& (((MODE) != DFmode && (MODE) != DImode) \
- || LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4)))
+ || (TARGET_32BIT \
+ ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) \
+ : ! (INTVAL (XEXP (X, 1)) & 3))) \
+ && ((MODE) != TImode \
+ || (TARGET_32BIT \
+ ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 12) \
+ : (LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 8) \
+ && ! (INTVAL (XEXP (X, 1)) & 3)))))
#define LEGITIMATE_INDEXED_ADDRESS_P(X) \
(GET_CODE (X) == PLUS \
@@ -1456,6 +1824,7 @@ typedef struct rs6000_args
#define LEGITIMATE_LO_SUM_ADDRESS_P(MODE, X) \
(TARGET_ELF \
+ && !flag_pic && !TARGET_TOC \
&& (MODE) != DImode \
&& (MODE) != TImode \
&& (TARGET_HARD_FLOAT || (MODE) != DFmode) \
@@ -1467,18 +1836,19 @@ typedef struct rs6000_args
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ if (LEGITIMATE_INDIRECT_ADDRESS_P (X)) \
goto ADDR; \
- if (GET_CODE (X) == PRE_INC \
+ if ((GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \
+ && TARGET_UPDATE \
&& LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (X, 0))) \
goto ADDR; \
- if (GET_CODE (X) == PRE_DEC \
- && LEGITIMATE_INDIRECT_ADDRESS_P (XEXP (X, 0))) \
+ if (LEGITIMATE_SMALL_DATA_P (MODE, X)) \
goto ADDR; \
if (LEGITIMATE_CONSTANT_POOL_ADDRESS_P (X)) \
goto ADDR; \
if (LEGITIMATE_OFFSET_ADDRESS_P (MODE, X)) \
goto ADDR; \
- if ((MODE) != DImode && (MODE) != TImode \
- && (TARGET_HARD_FLOAT || (MODE) != DFmode) \
+ if ((MODE) != TImode \
+ && (TARGET_HARD_FLOAT || TARGET_64BIT || (MODE) != DFmode) \
+ && (TARGET_64BIT || (MODE) != DImode) \
&& LEGITIMATE_INDEXED_ADDRESS_P (X)) \
goto ADDR; \
if (LEGITIMATE_LO_SUM_ADDRESS_P (MODE, X)) \
@@ -1502,7 +1872,7 @@ typedef struct rs6000_args
integer that is out of range. If so, generate code to add the
constant with the low-order 16 bits masked to the register and force
this result into another register (this can be done with `cau').
- Then generate an address of REG+(CONST&0xffff), allowing for the
+ Then generate an address of REG+(CONST&0xffff), allowing for the
possibility of bit 16 being a one.
Then check for the sum of a register and something not constant, try to
@@ -1511,30 +1881,30 @@ typedef struct rs6000_args
#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
{ if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
&& GET_CODE (XEXP (X, 1)) == CONST_INT \
- && (unsigned) (INTVAL (XEXP (X, 1)) + 0x8000) >= 0x10000) \
- { int high_int, low_int; \
- high_int = INTVAL (XEXP (X, 1)) >> 16; \
+ && (unsigned HOST_WIDE_INT) (INTVAL (XEXP (X, 1)) + 0x8000) >= 0x10000) \
+ { HOST_WIDE_INT high_int, low_int; \
+ rtx sum; \
+ high_int = INTVAL (XEXP (X, 1)) & (~ (HOST_WIDE_INT) 0xffff); \
low_int = INTVAL (XEXP (X, 1)) & 0xffff; \
if (low_int & 0x8000) \
- high_int += 1, low_int |= 0xffff0000; \
- (X) = gen_rtx (PLUS, SImode, \
- force_operand \
- (gen_rtx (PLUS, SImode, XEXP (X, 0), \
- gen_rtx (CONST_INT, VOIDmode, \
- high_int << 16)), 0), \
- gen_rtx (CONST_INT, VOIDmode, low_int)); \
+ high_int += 0x10000, low_int |= ((HOST_WIDE_INT) -1) << 16; \
+ sum = force_operand (gen_rtx (PLUS, Pmode, XEXP (X, 0), \
+ GEN_INT (high_int)), 0); \
+ (X) = gen_rtx (PLUS, Pmode, sum, GEN_INT (low_int)); \
goto WIN; \
} \
else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \
&& GET_CODE (XEXP (X, 1)) != CONST_INT \
- && (TARGET_HARD_FLOAT || (MODE) != DFmode) \
- && (MODE) != DImode && (MODE) != TImode) \
+ && (TARGET_HARD_FLOAT || TARGET_64BIT || (MODE) != DFmode) \
+ && (TARGET_64BIT || (MODE) != DImode) \
+ && (MODE) != TImode) \
{ \
- (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \
- force_reg (SImode, force_operand (XEXP (X, 1), 0))); \
+ (X) = gen_rtx (PLUS, Pmode, XEXP (X, 0), \
+ force_reg (Pmode, force_operand (XEXP (X, 1), 0))); \
goto WIN; \
} \
- else if (TARGET_ELF && !TARGET_64BIT && TARGET_NO_TOC \
+ else if (TARGET_ELF && TARGET_32BIT && TARGET_NO_TOC \
+ && !flag_pic \
&& GET_CODE (X) != CONST_INT \
&& GET_CODE (X) != CONST_DOUBLE && CONSTANT_P (X) \
&& (TARGET_HARD_FLOAT || (MODE) != DFmode) \
@@ -1558,16 +1928,71 @@ typedef struct rs6000_args
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
{ if (GET_CODE (ADDR) == PLUS \
&& LEGITIMATE_ADDRESS_INTEGER_P (XEXP (ADDR, 1), 0) \
- && ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (ADDR, 1), 4)) \
+ && ! LEGITIMATE_ADDRESS_INTEGER_P (XEXP (ADDR, 1), \
+ (TARGET_32BIT ? 4 : 8))) \
goto LABEL; \
- if (GET_CODE (ADDR) == PRE_INC) \
+ if (TARGET_UPDATE && GET_CODE (ADDR) == PRE_INC) \
goto LABEL; \
- if (GET_CODE (ADDR) == PRE_DEC) \
+ if (TARGET_UPDATE && GET_CODE (ADDR) == PRE_DEC) \
goto LABEL; \
if (GET_CODE (ADDR) == LO_SUM) \
goto LABEL; \
}
+/* The register number of the register used to address a table of
+ static data addresses in memory. In some cases this register is
+ defined by a processor's "application binary interface" (ABI).
+ When this macro is defined, RTL is generated for this register
+ once, as with the stack pointer and frame pointer registers. If
+ this macro is not defined, it is up to the machine-dependent files
+ to allocate such a register (if necessary). */
+
+/* #define PIC_OFFSET_TABLE_REGNUM */
+
+/* Define this macro if the register defined by
+ `PIC_OFFSET_TABLE_REGNUM' is clobbered by calls. Do not define
+ this macro if `PPIC_OFFSET_TABLE_REGNUM' is not defined. */
+
+/* #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED */
+
+/* By generating position-independent code, when two different
+ programs (A and B) share a common library (libC.a), the text of
+ the library can be shared whether or not the library is linked at
+ the same address for both programs. In some of these
+ environments, position-independent code requires not only the use
+ of different addressing modes, but also special code to enable the
+ use of these addressing modes.
+
+ The `FINALIZE_PIC' macro serves as a hook to emit these special
+ codes once the function is being compiled into assembly code, but
+ not before. (It is not done before, because in the case of
+ compiling an inline function, it would lead to multiple PIC
+ prologues being included in functions which used inline functions
+ and were compiled to assembly language.) */
+
+#define FINALIZE_PIC rs6000_finalize_pic ()
+
+/* A C expression that is nonzero if X is a legitimate immediate
+ operand on the target machine when generating position independent
+ code. You can assume that X satisfies `CONSTANT_P', so you need
+ not check this. You can also assume FLAG_PIC is true, so you need
+ not check it either. You need not define this macro if all
+ constants (including `SYMBOL_REF') can be immediate operands when
+ generating position independent code. */
+
+/* #define LEGITIMATE_PIC_OPERAND_P (X) */
+
+/* In rare cases, correct code generation requires extra machine
+ dependent processing between the second jump optimization pass and
+ delayed branch scheduling. On those machines, define this macro
+ as a C statement to act on the code starting at INSN.
+
+ On the RS/6000, we use it to make sure the GOT_TOC register marker
+ that FINALIZE_PIC is supposed to remove actually got removed. */
+
+#define MACHINE_DEPENDENT_REORG(INSN) rs6000_reorg (INSN)
+
+
/* Define this if some processing needs to be done immediately before
emitting code for an insn. */
@@ -1575,7 +2000,7 @@ typedef struct rs6000_args
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
-#define CASE_VECTOR_MODE SImode
+#define CASE_VECTOR_MODE (TARGET_32BIT ? SImode : DImode)
/* Define this if the tablejump instruction expects the table
to contain offsets from the address of the table.
@@ -1598,7 +2023,7 @@ typedef struct rs6000_args
/* Max number of bytes we can move from memory to memory
in one reasonably fast instruction. */
-#define MOVE_MAX (TARGET_POWERPC64 ? 8 : 4)
+#define MOVE_MAX (! TARGET_POWERPC64 ? 4 : 8)
#define MAX_MOVE_MAX 8
/* Nonzero if access to memory by bytes is no faster than for words.
@@ -1636,10 +2061,15 @@ typedef struct rs6000_args
/* We don't have GAS for the RS/6000 yet, so don't write out special
.stabs in cc1plus. */
-
+
#define FASCIST_ASSEMBLER
+
+#ifndef ASM_OUTPUT_CONSTRUCTOR
#define ASM_OUTPUT_CONSTRUCTOR(file, name)
+#endif
+#ifndef ASM_OUTPUT_DESTRUCTOR
#define ASM_OUTPUT_DESTRUCTOR(file, name)
+#endif
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
is done just by pretending it is already truncated. */
@@ -1648,12 +2078,12 @@ typedef struct rs6000_args
/* 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_64BIT ? DImode : SImode)
+#define Pmode (TARGET_32BIT ? SImode : DImode)
/* Mode of a function address in a call instruction (for indexing purposes).
Doesn't matter on RS/6000. */
-#define FUNCTION_MODE (TARGET_64BIT ? DImode : SImode)
+#define FUNCTION_MODE (TARGET_32BIT ? SImode : DImode)
/* Define this if addresses of constant functions
shouldn't be put through pseudo regs where they can be cse'd.
@@ -1693,52 +2123,74 @@ typedef struct rs6000_args
/* 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: \
- switch (rs6000_cpu) \
- { \
- case PROCESSOR_RIOS1: \
- return (GET_CODE (XEXP (X, 1)) != CONST_INT \
- ? COSTS_N_INSNS (5) \
- : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
- ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
- case PROCESSOR_RIOS2: \
- return COSTS_N_INSNS (2); \
- case PROCESSOR_PPC601: \
- case PROCESSOR_PPC603: \
- return COSTS_N_INSNS (5); \
- case PROCESSOR_PPC403: \
- case PROCESSOR_PPC604: \
- case PROCESSOR_PPC620: \
- return COSTS_N_INSNS (4); \
- } \
- case DIV: \
- case MOD: \
- if (GET_CODE (XEXP (X, 1)) == CONST_INT \
- && exact_log2 (INTVAL (XEXP (X, 1))) >= 0) \
- return COSTS_N_INSNS (2); \
- /* otherwise fall through to normal divide. */ \
- case UDIV: \
- case UMOD: \
- switch (rs6000_cpu) \
- { \
- case PROCESSOR_RIOS1: \
- return COSTS_N_INSNS (19); \
- case PROCESSOR_RIOS2: \
- return COSTS_N_INSNS (13); \
- case PROCESSOR_PPC403: \
- return COSTS_N_INSNS (33); \
- case PROCESSOR_PPC601: \
- return COSTS_N_INSNS (36); \
- case PROCESSOR_PPC603: \
- return COSTS_N_INSNS (37); \
- case PROCESSOR_PPC604: \
- case PROCESSOR_PPC620: \
- return COSTS_N_INSNS (20); \
- } \
- case FFS: \
- return COSTS_N_INSNS (4); \
- case MEM: \
+#define RTX_COSTS(X,CODE,OUTER_CODE) \
+ case PLUS: \
+ return ((GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && (unsigned HOST_WIDE_INT) ((INTVAL (XEXP (X, 1)) \
+ + 0x8000) >= 0x10000)) \
+ ? COSTS_N_INSNS (2) \
+ : COSTS_N_INSNS (1)); \
+ case AND: \
+ return ((non_and_cint_operand (XEXP (X, 1), SImode)) \
+ ? COSTS_N_INSNS (2) \
+ : COSTS_N_INSNS (1)); \
+ case IOR: \
+ case XOR: \
+ return ((non_logical_cint_operand (XEXP (X, 1), SImode)) \
+ ? COSTS_N_INSNS (2) \
+ : COSTS_N_INSNS (1)); \
+ case MULT: \
+ switch (rs6000_cpu) \
+ { \
+ case PROCESSOR_RIOS1: \
+ return (GET_CODE (XEXP (X, 1)) != CONST_INT \
+ ? COSTS_N_INSNS (5) \
+ : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
+ ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)); \
+ case PROCESSOR_RIOS2: \
+ case PROCESSOR_MPCCORE: \
+ return COSTS_N_INSNS (2); \
+ case PROCESSOR_PPC601: \
+ return COSTS_N_INSNS (5); \
+ case PROCESSOR_PPC603: \
+ return (GET_CODE (XEXP (X, 1)) != CONST_INT \
+ ? COSTS_N_INSNS (5) \
+ : INTVAL (XEXP (X, 1)) >= -256 && INTVAL (XEXP (X, 1)) <= 255 \
+ ? COSTS_N_INSNS (2) : COSTS_N_INSNS (3)); \
+ case PROCESSOR_PPC403: \
+ case PROCESSOR_PPC604: \
+ case PROCESSOR_PPC620: \
+ return COSTS_N_INSNS (4); \
+ } \
+ case DIV: \
+ case MOD: \
+ if (GET_CODE (XEXP (X, 1)) == CONST_INT \
+ && exact_log2 (INTVAL (XEXP (X, 1))) >= 0) \
+ return COSTS_N_INSNS (2); \
+ /* otherwise fall through to normal divide. */ \
+ case UDIV: \
+ case UMOD: \
+ switch (rs6000_cpu) \
+ { \
+ case PROCESSOR_RIOS1: \
+ return COSTS_N_INSNS (19); \
+ case PROCESSOR_RIOS2: \
+ return COSTS_N_INSNS (13); \
+ case PROCESSOR_MPCCORE: \
+ return COSTS_N_INSNS (6); \
+ case PROCESSOR_PPC403: \
+ return COSTS_N_INSNS (33); \
+ case PROCESSOR_PPC601: \
+ return COSTS_N_INSNS (36); \
+ case PROCESSOR_PPC603: \
+ return COSTS_N_INSNS (37); \
+ case PROCESSOR_PPC604: \
+ case PROCESSOR_PPC620: \
+ return COSTS_N_INSNS (20); \
+ } \
+ case FFS: \
+ return COSTS_N_INSNS (4); \
+ case MEM: \
/* MEM should be slightly more expensive than (plus (reg) (const)) */ \
return 5;
@@ -1799,8 +2251,8 @@ extern int rs6000_trunc_used;
/* Function names to call to do floating point truncation. */
-#define RS6000_ITRUNC "itrunc"
-#define RS6000_UITRUNC "uitrunc"
+#define RS6000_ITRUNC "__itrunc"
+#define RS6000_UITRUNC "__uitrunc"
/* Prefix and suffix to use to saving floating point */
#ifndef SAVE_FP_PREFIX
@@ -1814,14 +2266,16 @@ extern int rs6000_trunc_used;
#define RESTORE_FP_SUFFIX ""
#endif
+/* Function name to call to do profiling. */
+#define RS6000_MCOUNT ".__mcount"
+
/* Control the assembler format that we output. */
-/* Common macro to output the options used to the asm file. */
-#define ASM_OUTPUT_OPTIONS(FILE) \
- output_options (FILE, \
- f_options, sizeof (f_options) / sizeof (f_options[0]), \
- W_options, sizeof (W_options) / sizeof (W_options[0])) \
+/* 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 at beginning of assembler file.
@@ -1834,13 +2288,12 @@ extern int rs6000_trunc_used;
[RW] section emitted.
We then switch back to text to force the gcc2_compiled. label and the space
- allocated after it (when profiling) into the text section.
+ allocated after it (when profiling) into the text section.
Finally, declare mcount when profiling to make the assembler happy. */
#define ASM_FILE_START(FILE) \
{ \
- ASM_OUTPUT_OPTIONS (FILE); \
rs6000_gen_section_name (&xcoff_bss_section_name, \
main_input_filename, ".bss_"); \
rs6000_gen_section_name (&xcoff_private_data_section_name, \
@@ -1854,7 +2307,8 @@ extern int rs6000_trunc_used;
private_data_section (); \
text_section (); \
if (profile_flag) \
- fprintf (FILE, "\t.extern .mcount\n"); \
+ fprintf (FILE, "\t.extern %s\n", RS6000_MCOUNT); \
+ rs6000_file_start (FILE, TARGET_CPU_DEFAULT); \
}
/* Output at end of assembler file.
@@ -1864,9 +2318,9 @@ extern int rs6000_trunc_used;
#define ASM_FILE_END(FILE) \
{ \
text_section (); \
- fprintf (FILE, "_section_.text:\n"); \
+ fputs ("_section_.text:\n", FILE); \
data_section (); \
- fprintf (FILE, "\t.long _section_.text\n"); \
+ fputs ("\t.long _section_.text\n", FILE); \
}
/* We define this to prevent the name mangler from putting dollar signs into
@@ -1897,6 +2351,13 @@ extern int rs6000_trunc_used;
#define READONLY_DATA_SECTION read_only_data_section
+
+/* Define the name of the section to use for the exception tables.
+ TODO: test and see if we can use read_only_data_section, if so,
+ remove this. */
+
+#define EXCEPTION_SECTION data_section
+
/* If we are referencing a function that is static or is known to be
in this file, make the SYMBOL_REF special. We can use this to indicate
that we can branch to this function without emitting a no-op after the
@@ -1954,32 +2415,33 @@ toc_section () \
{ \
if (TARGET_MINIMAL_TOC) \
{ \
- static int toc_initialized = 0; \
- \
/* toc_section is always called at least once from ASM_FILE_START, \
so this is guaranteed to always be defined once and only once \
in each file. */ \
if (! toc_initialized) \
{ \
- fprintf (asm_out_file, ".toc\nLCTOC..0:\n"); \
- fprintf (asm_out_file, "\t.tc toc_table[TC],toc_table[RW]\n"); \
+ fputs (".toc\nLCTOC..0:\n", asm_out_file); \
+ fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file); \
toc_initialized = 1; \
} \
\
if (in_section != toc) \
- fprintf (asm_out_file, ".csect toc_table[RW]\n"); \
+ fputs (".csect toc_table[RW]\n", asm_out_file); \
} \
else \
{ \
if (in_section != toc) \
- fprintf (asm_out_file, ".toc\n"); \
+ fputs (".toc\n", asm_out_file); \
} \
in_section = toc; \
}
+/* Flag to say the TOC is initialized */
+extern int toc_initialized;
+
/* This macro produces the initial definition of a function name.
On the RS/6000, we need to place an extra '.' in the function name and
- output the function descriptor.
+ output the function descriptor.
The csect for the function will have already been created by the
`text_section' call previously done. We do have to go back to that
@@ -1990,27 +2452,27 @@ toc_section () \
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
{ if (TREE_PUBLIC (DECL)) \
{ \
- fprintf (FILE, "\t.globl ."); \
+ fputs ("\t.globl .", FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
- fprintf (FILE, "\n"); \
+ putc ('\n', FILE); \
} \
else \
{ \
- fprintf (FILE, "\t.lglobl ."); \
+ fputs ("\t.lglobl .", FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
- fprintf (FILE, "\n"); \
+ putc ('\n', FILE); \
} \
- fprintf (FILE, ".csect "); \
+ fputs (".csect ", FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
- fprintf (FILE, "[DS]\n"); \
+ fputs ("[DS]\n", FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
- fprintf (FILE, ":\n"); \
- fprintf (FILE, "\t.long ."); \
+ fputs (":\n", FILE); \
+ fputs ((TARGET_32BIT) ? "\t.long ." : "\t.llong .", FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
- fprintf (FILE, ", TOC[tc0], 0\n"); \
- fprintf (FILE, ".csect .text[PR]\n."); \
+ fputs (", TOC[tc0], 0\n", FILE); \
+ fputs (".csect .text[PR]\n.", FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
- fprintf (FILE, ":\n"); \
+ fputs (":\n", FILE); \
if (write_symbols == XCOFF_DEBUG) \
xcoffout_declare_function (FILE, DECL, NAME); \
}
@@ -2106,25 +2568,23 @@ toc_section () \
do \
{ \
char *_name = (NAME); \
+ int _len; \
if (_name[0] == '*') \
- (VAR) = _name+1; \
+ _name++; \
+ _len = strlen (_name); \
+ if (_name[_len - 1] != ']') \
+ (VAR) = _name; \
else \
{ \
- int _len = strlen (_name); \
- if (_name[_len - 1] != ']') \
- (VAR) = _name; \
- else \
- { \
- (VAR) = (char *) alloca (_len + 1); \
- strcpy ((VAR), _name); \
- (VAR)[_len - 4] = '\0'; \
- } \
+ (VAR) = (char *) alloca (_len + 1); \
+ strcpy ((VAR), _name); \
+ (VAR)[_len - 4] = '\0'; \
} \
} \
while (0)
/* Output something to declare an external symbol to the assembler. Most
- assemblers don't need this.
+ assemblers don't need this.
If we haven't already, add "[RW]" (or "[DS]" for a function) to the
name. Normally we write this out along with the name. In the few cases
@@ -2134,7 +2594,6 @@ toc_section () \
{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
if ((TREE_CODE (DECL) == VAR_DECL \
|| TREE_CODE (DECL) == FUNCTION_DECL) \
- && (NAME)[0] != '*' \
&& (NAME)[strlen (NAME) - 1] != ']') \
{ \
char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
@@ -2142,23 +2601,23 @@ toc_section () \
strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
XSTR (_symref, 0) = _name; \
} \
- fprintf (FILE, "\t.extern "); \
+ fputs ("\t.extern ", FILE); \
assemble_name (FILE, XSTR (_symref, 0)); \
if (TREE_CODE (DECL) == FUNCTION_DECL) \
{ \
- fprintf (FILE, "\n\t.extern ."); \
+ fputs ("\n\t.extern .", FILE); \
RS6000_OUTPUT_BASENAME (FILE, XSTR (_symref, 0)); \
} \
- fprintf (FILE, "\n"); \
+ putc ('\n', FILE); \
}
/* Similar, but for libcall. We only have to worry about the function name,
not that of the descriptor. */
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
-{ fprintf (FILE, "\t.extern ."); \
+{ fputs ("\t.extern .", FILE); \
assemble_name (FILE, XSTR (FUN, 0)); \
- fprintf (FILE, "\n"); \
+ putc ('\n', FILE); \
}
/* Output to assembler file text saying following lines
@@ -2182,17 +2641,111 @@ toc_section () \
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
-#define REGISTER_NAMES \
- {"0", "1", "2", "3", "4", "5", "6", "7", \
- "8", "9", "10", "11", "12", "13", "14", "15", \
- "16", "17", "18", "19", "20", "21", "22", "23", \
- "24", "25", "26", "27", "28", "29", "30", "31", \
- "0", "1", "2", "3", "4", "5", "6", "7", \
- "8", "9", "10", "11", "12", "13", "14", "15", \
- "16", "17", "18", "19", "20", "21", "22", "23", \
- "24", "25", "26", "27", "28", "29", "30", "31", \
- "mq", "lr", "ctr", "ap", \
- "0", "1", "2", "3", "4", "5", "6", "7" }
+extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
+
+#define REGISTER_NAMES \
+{ \
+ &rs6000_reg_names[ 0][0], /* r0 */ \
+ &rs6000_reg_names[ 1][0], /* r1 */ \
+ &rs6000_reg_names[ 2][0], /* r2 */ \
+ &rs6000_reg_names[ 3][0], /* r3 */ \
+ &rs6000_reg_names[ 4][0], /* r4 */ \
+ &rs6000_reg_names[ 5][0], /* r5 */ \
+ &rs6000_reg_names[ 6][0], /* r6 */ \
+ &rs6000_reg_names[ 7][0], /* r7 */ \
+ &rs6000_reg_names[ 8][0], /* r8 */ \
+ &rs6000_reg_names[ 9][0], /* r9 */ \
+ &rs6000_reg_names[10][0], /* r10 */ \
+ &rs6000_reg_names[11][0], /* r11 */ \
+ &rs6000_reg_names[12][0], /* r12 */ \
+ &rs6000_reg_names[13][0], /* r13 */ \
+ &rs6000_reg_names[14][0], /* r14 */ \
+ &rs6000_reg_names[15][0], /* r15 */ \
+ &rs6000_reg_names[16][0], /* r16 */ \
+ &rs6000_reg_names[17][0], /* r17 */ \
+ &rs6000_reg_names[18][0], /* r18 */ \
+ &rs6000_reg_names[19][0], /* r19 */ \
+ &rs6000_reg_names[20][0], /* r20 */ \
+ &rs6000_reg_names[21][0], /* r21 */ \
+ &rs6000_reg_names[22][0], /* r22 */ \
+ &rs6000_reg_names[23][0], /* r23 */ \
+ &rs6000_reg_names[24][0], /* r24 */ \
+ &rs6000_reg_names[25][0], /* r25 */ \
+ &rs6000_reg_names[26][0], /* r26 */ \
+ &rs6000_reg_names[27][0], /* r27 */ \
+ &rs6000_reg_names[28][0], /* r28 */ \
+ &rs6000_reg_names[29][0], /* r29 */ \
+ &rs6000_reg_names[30][0], /* r30 */ \
+ &rs6000_reg_names[31][0], /* r31 */ \
+ \
+ &rs6000_reg_names[32][0], /* fr0 */ \
+ &rs6000_reg_names[33][0], /* fr1 */ \
+ &rs6000_reg_names[34][0], /* fr2 */ \
+ &rs6000_reg_names[35][0], /* fr3 */ \
+ &rs6000_reg_names[36][0], /* fr4 */ \
+ &rs6000_reg_names[37][0], /* fr5 */ \
+ &rs6000_reg_names[38][0], /* fr6 */ \
+ &rs6000_reg_names[39][0], /* fr7 */ \
+ &rs6000_reg_names[40][0], /* fr8 */ \
+ &rs6000_reg_names[41][0], /* fr9 */ \
+ &rs6000_reg_names[42][0], /* fr10 */ \
+ &rs6000_reg_names[43][0], /* fr11 */ \
+ &rs6000_reg_names[44][0], /* fr12 */ \
+ &rs6000_reg_names[45][0], /* fr13 */ \
+ &rs6000_reg_names[46][0], /* fr14 */ \
+ &rs6000_reg_names[47][0], /* fr15 */ \
+ &rs6000_reg_names[48][0], /* fr16 */ \
+ &rs6000_reg_names[49][0], /* fr17 */ \
+ &rs6000_reg_names[50][0], /* fr18 */ \
+ &rs6000_reg_names[51][0], /* fr19 */ \
+ &rs6000_reg_names[52][0], /* fr20 */ \
+ &rs6000_reg_names[53][0], /* fr21 */ \
+ &rs6000_reg_names[54][0], /* fr22 */ \
+ &rs6000_reg_names[55][0], /* fr23 */ \
+ &rs6000_reg_names[56][0], /* fr24 */ \
+ &rs6000_reg_names[57][0], /* fr25 */ \
+ &rs6000_reg_names[58][0], /* fr26 */ \
+ &rs6000_reg_names[59][0], /* fr27 */ \
+ &rs6000_reg_names[60][0], /* fr28 */ \
+ &rs6000_reg_names[61][0], /* fr29 */ \
+ &rs6000_reg_names[62][0], /* fr30 */ \
+ &rs6000_reg_names[63][0], /* fr31 */ \
+ \
+ &rs6000_reg_names[64][0], /* mq */ \
+ &rs6000_reg_names[65][0], /* lr */ \
+ &rs6000_reg_names[66][0], /* ctr */ \
+ &rs6000_reg_names[67][0], /* ap */ \
+ \
+ &rs6000_reg_names[68][0], /* cr0 */ \
+ &rs6000_reg_names[69][0], /* cr1 */ \
+ &rs6000_reg_names[70][0], /* cr2 */ \
+ &rs6000_reg_names[71][0], /* cr3 */ \
+ &rs6000_reg_names[72][0], /* cr4 */ \
+ &rs6000_reg_names[73][0], /* cr5 */ \
+ &rs6000_reg_names[74][0], /* cr6 */ \
+ &rs6000_reg_names[75][0], /* cr7 */ \
+ \
+ &rs6000_reg_names[76][0], /* fpmem */ \
+}
+
+/* print-rtl can't handle the above REGISTER_NAMES, so define the
+ following for it. Switch to use the alternate names since
+ they are more mnemonic. */
+
+#define DEBUG_REGISTER_NAMES \
+{ \
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", \
+ "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", \
+ "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", \
+ "mq", "lr", "ctr", "ap", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "fpmem" \
+}
/* Table of additional register names to use in user input. */
@@ -2216,7 +2769,7 @@ toc_section () \
/* no additional names for: mq, lr, ctr, ap */ \
"cr0", 68, "cr1", 69, "cr2", 70, "cr3", 71, \
"cr4", 72, "cr5", 73, "cr6", 74, "cr7", 75, \
- "cc", 68 }
+ "cc", 68, "sp", 1, "toc", 2 }
/* How to renumber registers for dbx and gdb. */
@@ -2243,7 +2796,7 @@ toc_section () \
`assemble_name' uses this. */
#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, NAME)
+ fputs (NAME, FILE)
/* This is how to output an internal numbered label where
PREFIX is the class of label and NUM is the number within the class. */
@@ -2270,7 +2823,7 @@ toc_section () \
This is suitable for output with `assemble_name'. */
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "%s..%d", PREFIX, NUM)
+ sprintf (LABEL, "*%s..%d", PREFIX, NUM)
/* This is how to output an assembler line defining a `double' constant. */
@@ -2315,22 +2868,39 @@ toc_section () \
/* This is how to output an assembler line defining an `int' constant. */
+#define ASM_OUTPUT_DOUBLE_INT(FILE,VALUE) \
+do { \
+ if (TARGET_32BIT) \
+ { \
+ assemble_integer (operand_subword ((VALUE), 0, 0, DImode), \
+ UNITS_PER_WORD, 1); \
+ assemble_integer (operand_subword ((VALUE), 1, 0, DImode), \
+ UNITS_PER_WORD, 1); \
+ } \
+ else \
+ { \
+ fputs ("\t.llong ", FILE); \
+ output_addr_const (FILE, (VALUE)); \
+ putc ('\n', FILE); \
+ } \
+} while (0)
+
#define ASM_OUTPUT_INT(FILE,VALUE) \
-( fprintf (FILE, "\t.long "), \
+( fputs ("\t.long ", FILE), \
output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
+ putc ('\n', FILE))
/* Likewise for `char' and `short' constants. */
#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "\t.short "), \
+( fputs ("\t.short ", FILE), \
output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
+ putc ('\n', FILE))
#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "\t.byte "), \
+( fputs ("\t.byte ", FILE), \
output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
+ putc ('\n', FILE))
/* This is how to output an assembler line for a numeric constant byte. */
@@ -2343,12 +2913,17 @@ toc_section () \
#define ASM_OUTPUT_ASCII(FILE, P, N) output_ascii ((FILE), (P), (N))
/* This is how to output code to push a register on the stack.
- It need not be very fast code. */
+ It need not be very fast code.
+
+ On the rs6000, we must keep the backchain up to date. In order
+ to simplify things, always allocate 16 bytes for a push (System V
+ wants to keep stack aligned to a 16 byte boundary). */
#define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \
do { \
extern char *reg_names[]; \
- asm_fprintf (FILE, "\{tstu|stwu} %s,-4(%s)\n", reg_names[REGNO], \
+ asm_fprintf (FILE, "\t{stu|stwu} %s,-16(%s)\n\t{st|stw} %s,8(%s)\n", \
+ reg_names[1], reg_names[1], reg_names[REGNO], \
reg_names[1]); \
} while (0)
@@ -2358,34 +2933,34 @@ do { \
#define ASM_OUTPUT_REG_POP(FILE,REGNO) \
do { \
extern char *reg_names[]; \
- asm_fprintf (FILE, "\t{l|lwz} %s,0(%s)\n\t{ai|addic} %s,%s,4\n", \
+ asm_fprintf (FILE, "\t{l|lwz} %s,8(%s)\n\t{ai|addic} %s,%s,16\n", \
reg_names[REGNO], reg_names[1], reg_names[1], \
reg_names[1]); \
} while (0)
-/* This is how to output an element of a case-vector that is absolute.
+/* This is how to output an element of a case-vector that is absolute.
(RS/6000 does not use such vectors, but we must define this macro
anyway.) */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
do { char buf[100]; \
- fprintf (FILE, "\t.long "); \
+ fputs ((TARGET_32BIT) ? "\t.long " : "\t.llong ", FILE); \
ASM_GENERATE_INTERNAL_LABEL (buf, "L", VALUE); \
assemble_name (FILE, buf); \
- fprintf (FILE, "\n"); \
+ putc ('\n', FILE); \
} while (0)
/* This is how to output an element of a case-vector that is relative. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
do { char buf[100]; \
- fprintf (FILE, "\t.long "); \
+ fputs ((TARGET_32BIT) ? "\t.long " : "\t.llong ", FILE); \
ASM_GENERATE_INTERNAL_LABEL (buf, "L", VALUE); \
assemble_name (FILE, buf); \
- fprintf (FILE, "-"); \
+ putc ('-', FILE); \
ASM_GENERATE_INTERNAL_LABEL (buf, "L", REL); \
assemble_name (FILE, buf); \
- fprintf (FILE, "\n"); \
+ putc ('\n', FILE); \
} while (0)
/* This is how to output an assembler line
@@ -2402,10 +2977,14 @@ do { \
/* This says how to output an assembler line
to define a global common symbol. */
-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \
do { fputs (".comm ", (FILE)); \
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- fprintf ((FILE), ",%d\n", (SIZE)); } while (0)
+ if ( (SIZE) > 4) \
+ fprintf ((FILE), ",%d,3\n", (SIZE)); \
+ else \
+ fprintf( (FILE), ",%d\n", (SIZE)); \
+ } while (0)
/* This says how to output an assembler line
to define a local common symbol. */
@@ -2447,7 +3026,8 @@ do { \
/* Define which CODE values are valid. */
-#define PRINT_OPERAND_PUNCT_VALID_P(CODE) ((CODE) == '.' || (CODE) == '*')
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
+ ((CODE) == '.' || (CODE) == '*' || (CODE) == '$')
/* Print a memory address as an operand to reference that memory location. */
@@ -2455,7 +3035,7 @@ do { \
/* Define the codes that are matched by predicates in rs6000.c. */
-#define PREDICATE_CODES \
+#define PREDICATE_CODES \
{"short_cint_operand", {CONST_INT}}, \
{"u_short_cint_operand", {CONST_INT}}, \
{"non_short_cint_operand", {CONST_INT}}, \
@@ -2465,11 +3045,13 @@ do { \
{"reg_or_neg_short_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_u_short_operand", {SUBREG, REG, CONST_INT}}, \
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
+ {"got_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
+ {"got_no_const_operand", {SYMBOL_REF, LABEL_REF}}, \
{"easy_fp_constant", {CONST_DOUBLE}}, \
{"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
{"lwa_operand", {SUBREG, MEM, REG}}, \
+ {"volatile_mem_operand", {MEM}}, \
{"offsettable_addr_operand", {REG, SUBREG, PLUS}}, \
- {"fp_reg_or_mem_operand", {SUBREG, MEM, REG}}, \
{"mem_or_easy_const_operand", {SUBREG, MEM, CONST_DOUBLE}}, \
{"add_operand", {SUBREG, REG, CONST_INT}}, \
{"non_add_cint_operand", {CONST_INT}}, \
@@ -2478,6 +3060,8 @@ do { \
{"logical_operand", {SUBREG, REG, CONST_INT}}, \
{"non_logical_cint_operand", {CONST_INT}}, \
{"mask_operand", {CONST_INT}}, \
+ {"count_register_operand", {REG}}, \
+ {"fpmem_operand", {REG}}, \
{"call_operand", {SYMBOL_REF, REG}}, \
{"current_file_function_operand", {SYMBOL_REF}}, \
{"input_operand", {SUBREG, MEM, REG, CONST_INT, SYMBOL_REF}}, \
@@ -2488,11 +3072,29 @@ do { \
{"scc_comparison_operator", {EQ, NE, LE, LT, GE, \
GT, LEU, LTU, GEU, GTU}},
+
+/* uncomment for disabling the corresponding default options */
+/* #define MACHINE_no_sched_interblock */
+/* #define MACHINE_no_sched_speculative */
+/* #define MACHINE_no_sched_speculative_load */
+
+/* indicate that issue rate is defined for this machine
+ (no need to use the default) */
+#define ISSUE_RATE get_issue_rate ()
+
+/* General flags. */
+extern int flag_pic;
+extern int optimize;
+extern int flag_expensive_optimizations;
+extern int frame_pointer_needed;
+
/* Declare functions in rs6000.c */
extern void output_options ();
extern void rs6000_override_options ();
+extern void rs6000_file_start ();
extern struct rtx_def *rs6000_float_const ();
extern struct rtx_def *rs6000_immed_double_const ();
+extern struct rtx_def *rs6000_got_register ();
extern int direct_return ();
extern int any_operand ();
extern int short_cint_operand ();
@@ -2504,10 +3106,12 @@ extern int reg_or_short_operand ();
extern int reg_or_neg_short_operand ();
extern int reg_or_u_short_operand ();
extern int reg_or_cint_operand ();
+extern int got_operand ();
+extern int got_no_const_operand ();
+extern int num_insns_constant ();
extern int easy_fp_constant ();
extern int volatile_mem_operand ();
extern int offsettable_addr_operand ();
-extern int fp_reg_or_mem_operand ();
extern int mem_or_easy_const_operand ();
extern int add_operand ();
extern int non_add_cint_operand ();
@@ -2516,14 +3120,18 @@ extern int non_logical_operand ();
extern int mask_constant ();
extern int mask_operand ();
extern int and_operand ();
+extern int count_register_operand ();
+extern int fpmem_operand ();
extern int non_and_cint_operand ();
extern int reg_or_mem_operand ();
extern int lwa_operand ();
extern int call_operand ();
extern int current_file_function_operand ();
extern int input_operand ();
+extern int small_data_operand ();
extern void init_cumulative_args ();
extern void function_arg_advance ();
+extern int function_arg_boundary ();
extern struct rtx_def *function_arg ();
extern int function_arg_partial_nregs ();
extern int function_arg_pass_by_reference ();
@@ -2541,13 +3149,17 @@ extern int registers_ok_for_quad_peep ();
extern int addrs_ok_for_quad_peep ();
extern enum reg_class secondary_reload_class ();
extern int ccr_bit ();
+extern void rs6000_finalize_pic ();
+extern void rs6000_reorg ();
+extern void rs6000_save_machine_status ();
+extern void rs6000_restore_machine_status ();
+extern void rs6000_init_expanders ();
extern void print_operand ();
extern void print_operand_address ();
extern int first_reg_to_save ();
extern int first_fp_reg_to_save ();
extern int rs6000_makes_calls ();
extern rs6000_stack_t *rs6000_stack_info ();
-extern void svr4_traceback ();
extern void output_prolog ();
extern void output_epilog ();
extern void output_toc ();
@@ -2555,3 +3167,16 @@ extern void output_ascii ();
extern void rs6000_gen_section_name ();
extern void output_function_profiler ();
extern int rs6000_adjust_cost ();
+extern void rs6000_trampoline_template ();
+extern int rs6000_trampoline_size ();
+extern void rs6000_initialize_trampoline ();
+extern int rs6000_comp_type_attributes ();
+extern int rs6000_valid_decl_attribute_p ();
+extern int rs6000_valid_type_attribute_p ();
+extern void rs6000_set_default_type_attributes ();
+extern struct rtx_def *rs6000_dll_import_ref ();
+extern struct rtx_def *rs6000_longcall_ref ();
+
+/* See nonlocal_goto_receiver for when this must be set. */
+
+#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (TARGET_TOC && TARGET_MINIMAL_TOC)
diff --git a/gnu/usr.bin/gcc/config/rs6000/sysv4.h b/gnu/usr.bin/gcc/config/rs6000/sysv4.h
index 1c54c6fc5a6..1fdd2f032d8 100644
--- a/gnu/usr.bin/gcc/config/rs6000/sysv4.h
+++ b/gnu/usr.bin/gcc/config/rs6000/sysv4.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for PowerPC running System V.4
- Copyright (C) 1995, Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GNU CC.
@@ -19,36 +19,44 @@ 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. */
-/* eABI local switches -- put here rather than eabi.h, so the switches
- can be tested in macros. */
+/* Small data support types */
+enum rs6000_sdata_type {
+ SDATA_NONE, /* no small data support */
+ SDATA_DATA, /* just put data in .sbss/.sdata, don't use relocs */
+ SDATA_SYSV, /* Use r13 to point to .sdata/.sbss */
+ SDATA_EABI /* Use r13 like above, r2 points to .sdata2/.sbss2 */
+};
+extern enum rs6000_sdata_type rs6000_sdata;
+
+/* V.4/eabi switches */
#define MASK_NO_BITFIELD_TYPE 0x40000000 /* Set PCC_BITFIELD_TYPE_MATTERS to 0 */
#define MASK_STRICT_ALIGN 0x20000000 /* Set STRICT_ALIGNMENT to 1. */
#define MASK_RELOCATABLE 0x10000000 /* GOT pointers are PC relative */
-#define MASK_NO_TRACEBACK 0x08000000 /* eliminate traceback words */
+#define MASK_EABI 0x08000000 /* Adhere to eabi, not System V spec */
#define MASK_LITTLE_ENDIAN 0x04000000 /* target is little endian */
-#define MASK_AIX_CALLS 0x02000000 /* Use AIX calling sequence */
+#define MASK_REGNAMES 0x02000000 /* use alternate register names. */
#define MASK_PROTOTYPE 0x01000000 /* Only prototyped fcns pass variable args */
#define TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE)
#define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN)
#define TARGET_RELOCATABLE (target_flags & MASK_RELOCATABLE)
-#define TARGET_NO_TRACEBACK (target_flags & MASK_NO_TRACEBACK)
+#define TARGET_EABI (target_flags & MASK_EABI)
#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
-#define TARGET_AIX_CALLS (target_flags & MASK_AIX_CALLS)
+#define TARGET_REGNAMES (target_flags & MASK_REGNAMES)
#define TARGET_PROTOTYPE (target_flags & MASK_PROTOTYPE)
-#define TARGET_TOC (target_flags & (MASK_64BIT \
- | MASK_RELOCATABLE \
- | MASK_MINIMAL_TOC))
+#define TARGET_TOC ((target_flags & MASK_64BIT) \
+ || ((target_flags & (MASK_RELOCATABLE \
+ | MASK_MINIMAL_TOC)) \
+ && flag_pic > 1) \
+ || DEFAULT_ABI == ABI_AIX \
+ || DEFAULT_ABI == ABI_NT)
#define TARGET_BITFIELD_TYPE (! TARGET_NO_BITFIELD_TYPE)
-#define TARGET_TRACEBACK (! TARGET_NO_TRACEBACK)
#define TARGET_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
-#define TARGET_NO_AIX_CALLS (! TARGET_AIX_CALLS)
#define TARGET_NO_PROTOTYPE (! TARGET_PROTOTYPE)
#define TARGET_NO_TOC (! TARGET_TOC)
-
-#define TARGET_V4_CALLS TARGET_NO_AIX_CALLS
+#define TARGET_NO_EABI (! TARGET_EABI)
/* Pseudo target to indicate whether the object format is ELF
(to get around not having conditional compilation in the md file) */
@@ -64,8 +72,8 @@ Boston, MA 02111-1307, USA. */
{ "no-strict-align", -MASK_STRICT_ALIGN }, \
{ "relocatable", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
{ "no-relocatable", -MASK_RELOCATABLE }, \
- { "traceback", -MASK_NO_TRACEBACK }, \
- { "no-traceback", MASK_NO_TRACEBACK }, \
+ { "relocatable-lib", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC }, \
+ { "no-relocatable-lib", -MASK_RELOCATABLE }, \
{ "little-endian", MASK_LITTLE_ENDIAN }, \
{ "little", MASK_LITTLE_ENDIAN }, \
{ "big-endian", -MASK_LITTLE_ENDIAN }, \
@@ -73,10 +81,47 @@ Boston, MA 02111-1307, USA. */
{ "no-toc", 0 }, \
{ "toc", MASK_MINIMAL_TOC }, \
{ "full-toc", MASK_MINIMAL_TOC }, \
- { "call-aix", MASK_AIX_CALLS }, \
- { "call-sysv", -MASK_AIX_CALLS }, \
{ "prototype", MASK_PROTOTYPE }, \
- { "no-prototype", -MASK_PROTOTYPE },
+ { "no-prototype", -MASK_PROTOTYPE }, \
+ { "no-traceback", 0 }, \
+ { "eabi", MASK_EABI }, \
+ { "no-eabi", -MASK_EABI }, \
+ { "regnames", MASK_REGNAMES }, \
+ { "no-regnames", -MASK_REGNAMES }, \
+ { "sdata", 0 }, \
+ { "no-sdata", 0 }, \
+ { "sim", 0 }, \
+ { "ads", 0 }, \
+ { "yellowknife", 0 }, \
+ { "mvme", 0 }, \
+ { "emb", 0 }, \
+ { "solaris-cclib", 0 }, \
+ { "shlib", 0 }, \
+ EXTRA_SUBTARGET_SWITCHES \
+ { "newlib", 0 },
+
+/* This is meant to be redefined in the host dependent files */
+#define EXTRA_SUBTARGET_SWITCHES
+
+/* Default ABI to use */
+#define RS6000_ABI_NAME "sysv"
+
+/* Strings provided by SUBTARGET_OPTIONS */
+extern char *rs6000_abi_name;
+extern char *rs6000_sdata_name;
+
+#define SUBTARGET_OPTIONS \
+ { "call-", &rs6000_abi_name}, \
+ { "sdata=", &rs6000_sdata_name}
+
+/* Max # of bytes for variables to automatically be put into the .sdata
+ or .sdata2 sections. */
+extern int g_switch_value; /* value of the -G xx switch */
+extern int g_switch_set; /* whether -G xx was passed. */
+
+#ifndef SDATA_DEFAULT_SIZE
+#define SDATA_DEFAULT_SIZE 8
+#endif
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -89,13 +134,138 @@ Boston, MA 02111-1307, USA. */
#define SUBTARGET_OVERRIDE_OPTIONS \
do { \
+ if (!g_switch_set) \
+ g_switch_value = SDATA_DEFAULT_SIZE; \
+ \
+ if (!strcmp (rs6000_abi_name, "sysv")) \
+ rs6000_current_abi = ABI_V4; \
+ else if (!strcmp (rs6000_abi_name, "sysv-noeabi")) \
+ { \
+ rs6000_current_abi = ABI_V4; \
+ target_flags &= ~ MASK_EABI; \
+ } \
+ else if (!strcmp (rs6000_abi_name, "sysv-eabi") \
+ || !strcmp (rs6000_abi_name, "eabi")) \
+ { \
+ rs6000_current_abi = ABI_V4; \
+ target_flags |= MASK_EABI; \
+ } \
+ else if (!strcmp (rs6000_abi_name, "aix")) \
+ { \
+ rs6000_current_abi = ABI_AIX_NODESC; \
+ target_flags |= MASK_EABI; \
+ } \
+ else if (!strcmp (rs6000_abi_name, "aixdesc")) \
+ rs6000_current_abi = ABI_AIX; \
+ else if (!strcmp (rs6000_abi_name, "nt")) \
+ rs6000_current_abi = ABI_NT; \
+ else if (!strcmp (rs6000_abi_name, "linux")) \
+ rs6000_current_abi = ABI_V4; \
+ else if (!strcmp (rs6000_abi_name, "solaris")) \
+ rs6000_current_abi = ABI_SOLARIS; \
+ else \
+ { \
+ rs6000_current_abi = ABI_V4; \
+ error ("Bad value for -mcall-%s", rs6000_abi_name); \
+ } \
+ \
+ if (rs6000_sdata_name) \
+ { \
+ if (!strcmp (rs6000_sdata_name, "none")) \
+ rs6000_sdata = SDATA_NONE; \
+ else if (!strcmp (rs6000_sdata_name, "data")) \
+ rs6000_sdata = SDATA_DATA; \
+ else if (!strcmp (rs6000_sdata_name, "default")) \
+ rs6000_sdata = (TARGET_EABI) ? SDATA_EABI : SDATA_SYSV; \
+ else if (!strcmp (rs6000_sdata_name, "sysv")) \
+ rs6000_sdata = SDATA_SYSV; \
+ else if (!strcmp (rs6000_sdata_name, "eabi")) \
+ rs6000_sdata = SDATA_EABI; \
+ else \
+ error ("Bad value for -msdata=%s", rs6000_sdata_name); \
+ } \
+ else if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS) \
+ { \
+ rs6000_sdata = SDATA_DATA; \
+ rs6000_sdata_name = "data"; \
+ } \
+ else \
+ { \
+ rs6000_sdata = SDATA_NONE; \
+ rs6000_sdata_name = "none"; \
+ } \
+ \
+ if (TARGET_RELOCATABLE && \
+ (rs6000_sdata == SDATA_EABI || rs6000_sdata == SDATA_SYSV)) \
+ { \
+ rs6000_sdata = SDATA_DATA; \
+ error ("-mrelocatable and -msdata=%s are incompatible.", \
+ rs6000_sdata_name); \
+ } \
+ \
+ else if (flag_pic && \
+ (rs6000_sdata == SDATA_EABI || rs6000_sdata == SDATA_SYSV)) \
+ { \
+ rs6000_sdata = SDATA_DATA; \
+ error ("-f%s and -msdata=%s are incompatible.", \
+ (flag_pic > 1) ? "PIC" : "pic", \
+ rs6000_sdata_name); \
+ } \
+ \
+ if (rs6000_sdata != SDATA_NONE && DEFAULT_ABI != ABI_V4 \
+ && DEFAULT_ABI != ABI_SOLARIS) \
+ { \
+ rs6000_sdata = SDATA_NONE; \
+ error ("-msdata=%s and -mcall-%s are incompatible.", \
+ rs6000_sdata_name, rs6000_abi_name); \
+ } \
+ \
if (TARGET_RELOCATABLE && !TARGET_MINIMAL_TOC) \
{ \
target_flags |= MASK_MINIMAL_TOC; \
error ("-mrelocatable and -mno-minimal-toc are incompatible."); \
} \
+ \
+ if (TARGET_RELOCATABLE && \
+ (rs6000_current_abi == ABI_AIX || rs6000_current_abi == ABI_NT)) \
+ { \
+ target_flags &= ~MASK_RELOCATABLE; \
+ error ("-mrelocatable and -mcall-%s are incompatible.", \
+ rs6000_abi_name); \
+ } \
+ \
+ if (flag_pic > 1 && \
+ (rs6000_current_abi == ABI_AIX || rs6000_current_abi == ABI_NT)) \
+ { \
+ flag_pic = 0; \
+ error ("-fPIC and -mcall-%s are incompatible.", \
+ rs6000_abi_name); \
+ } \
+ \
+ if (rs6000_current_abi == ABI_AIX && TARGET_LITTLE_ENDIAN) \
+ { \
+ target_flags &= ~MASK_LITTLE_ENDIAN; \
+ error ("-mcall-aixdesc must be big endian"); \
+ } \
+ \
+ if (rs6000_current_abi == ABI_NT && TARGET_BIG_ENDIAN) \
+ { \
+ target_flags |= MASK_LITTLE_ENDIAN; \
+ error ("-mcall-nt must be little endian"); \
+ } \
+ \
+ /* Treat -fPIC the same as -mrelocatable */ \
+ if (flag_pic > 1) \
+ target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC; \
+ \
+ else if (TARGET_RELOCATABLE) \
+ flag_pic = 2; \
+ \
} while (0)
+/* Default ABI to compile code for */
+#define DEFAULT_ABI rs6000_current_abi
+
#include "rs6000/powerpc.h"
/* System V.4 uses register 13 as a pointer to the small data area,
@@ -107,9 +277,8 @@ do { \
/* System V.4 passes the first 8 floating arguments in registers,
instead of the first 13 like AIX does. */
#undef FP_ARG_MAX_REG
-#define FP_ARG_AIX_MAX_REG 45
-#define FP_ARG_V4_MAX_REG 40
-#define FP_ARG_MAX_REG ((TARGET_AIX_CALLS) ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
+#define FP_ARG_MAX_REG ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_AIX_NODESC) \
+ ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
/* Size of the V.4 varargs area if needed */
#undef RS6000_VARARGS_AREA
@@ -123,7 +292,7 @@ do { \
/* Define this to set the endianness to use in libgcc2.c, which can
not depend on target_flags. */
-#ifndef _LITTLE_ENDIAN
+#if !defined(_LITTLE_ENDIAN) && !defined(__sun__)
#define LIBGCC2_WORDS_BIG_ENDIAN 1
#else
#define LIBGCC2_WORDS_BIG_ENDIAN 0
@@ -131,13 +300,16 @@ do { \
/* Size of the outgoing register save area */
#undef RS6000_REG_SAVE
-#define RS6000_REG_SAVE (TARGET_AIX_CALLS ? (TARGET_64BIT ? 64 : 32) : 0)
+#define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX \
+ || DEFAULT_ABI == ABI_AIX_NODESC) \
+ ? (TARGET_64BIT ? 64 : 32) \
+ : 0)
/* Size of the fixed area on the stack. For AIX, use the standard 6 word
area, otherwise use 2 words to store back chain & LR. */
#undef RS6000_SAVE_AREA
#define RS6000_SAVE_AREA \
- ((TARGET_AIX_CALLS ? 24 : 8) << (TARGET_64BIT ? 1 : 0))
+ (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_AIX_NODESC) ? 24 : 8) << (TARGET_64BIT ? 1 : 0))
/* Define cutoff for using external functions to save floating point.
Currently on V.4, always use inline stores */
@@ -152,17 +324,14 @@ do { \
#undef OBJECT_FORMAT_COFF
-/* The XCOFF support uses weird symbol suffixes, which we don't want
- for ELF. */
-
-#undef RS6000_OUTPUT_BASENAME
-#define RS6000_OUTPUT_BASENAME(FILE, NAME) assemble_name (FILE, NAME)
-
/* Don't bother to output .extern pseudo-ops. They are not needed by
ELF assemblers. */
#undef ASM_OUTPUT_EXTERNAL
+/* Put jump tables in read-only memory, rather than in .text. */
+#undef JUMP_TABLES_IN_TEXT_SECTION
+
/* Undefine some things which are defined by the generic svr4.h. */
#undef ASM_FILE_END
@@ -195,71 +364,242 @@ do { \
/* Type used for wchar_t, as a string used in a declaration. */
#undef WCHAR_TYPE
-#define WCHAR_TYPE "short unsigned int"
+#define WCHAR_TYPE "long int"
/* Width of wchar_t in bits. */
#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 16
+#define WCHAR_TYPE_SIZE 32
+
+/* Make int foo : 8 not cause structures to be aligned to an int boundary */
+
+#undef PCC_BITFIELD_TYPE_MATTERS
+#define PCC_BITFIELD_TYPE_MATTERS (TARGET_BITFIELD_TYPE)
+
+/* Define this macro to be the value 1 if instructions will fail to
+ work if given data not on the nominal alignment. If instructions
+ will merely go slower in that case, define this macro as 0.
+
+ Note, little endian systems trap on unaligned addresses, so never
+ turn off strict alignment in that case. */
+#undef STRICT_ALIGNMENT
+#define STRICT_ALIGNMENT (TARGET_STRICT_ALIGN || TARGET_LITTLE_ENDIAN)
-/* Align stack to 16 byte boundaries */
+/* Alignment in bits of the stack boundary. Note, in order to allow building
+ one set of libraries with -mno-eabi instead of eabi libraries and non-eabi
+ versions, just use 64 as the stack boundary. */
#undef STACK_BOUNDARY
-#define STACK_BOUNDARY 128
+#define STACK_BOUNDARY 64
+
+/* Real stack boundary as mandated by the appropriate ABI */
+#define ABI_STACK_BOUNDARY ((TARGET_EABI) ? 64 : 128)
/* No data type wants to be aligned rounder than this. */
#undef BIGGEST_ALIGNMENT
-#define BIGGEST_ALIGNMENT 128
+#define BIGGEST_ALIGNMENT ((TARGET_EABI) ? 64 : 128)
+
+#undef BIGGEST_FIELD_ALIGNMENT
+#undef ADJUST_FIELD_ALIGN
+#undef ROUND_TYPE_ALIGN
/* Use ELF style section commands. */
#undef TEXT_SECTION_ASM_OP
-#define TEXT_SECTION_ASM_OP "\t.section\t\".text\""
+#define TEXT_SECTION_ASM_OP "\t.section \".text\""
#undef DATA_SECTION_ASM_OP
-#define DATA_SECTION_ASM_OP "\t.section\t\".data\""
+#define DATA_SECTION_ASM_OP "\t.section \".data\""
+
+#undef BSS_SECTION_ASM_OP
+#define BSS_SECTION_ASM_OP "\t.section \".bss\""
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP "\t.section \".init\",\"ax\""
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP "\t.section \".fini\",\"ax\""
+
+#define TOC_SECTION_ASM_OP "\t.section \".got\",\"aw\""
+
+/* Put PC relative got entries in .got2 */
+#define MINIMAL_TOC_SECTION_ASM_OP \
+ ((TARGET_RELOCATABLE || flag_pic) ? "\t.section\t\".got2\",\"aw\"" : "\t.section\t\".got1\",\"aw\"")
+
+/* Put relocatable data in .data, not .rodata so initialized pointers can be updated */
+#undef CONST_SECTION_ASM_OP
+#define CONST_SECTION_ASM_OP \
+ ((TARGET_RELOCATABLE || flag_pic) ? "\t.section\t\".data\"\t# .rodata" : "\t.section\t\".rodata\"")
+
+
+#define SDATA_SECTION_ASM_OP "\t.section \".sdata\",\"aw\""
+#define SDATA2_SECTION_ASM_OP "\t.section \".sdata2\",\"a\""
+#define SBSS_SECTION_ASM_OP \
+ ((DEFAULT_ABI == ABI_SOLARIS) ? "\t.section \".sbss\",\"aw\"" : "\t.section \".sbss\",\"aw\",@nobits")
+
/* Besides the usual ELF sections, we need a toc section. */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_toc
+#define EXTRA_SECTIONS in_const, in_ctors, in_dtors, in_toc, in_sdata, in_sdata2, in_sbss, in_init, in_fini
#undef EXTRA_SECTION_FUNCTIONS
#define EXTRA_SECTION_FUNCTIONS \
CONST_SECTION_FUNCTION \
CTORS_SECTION_FUNCTION \
DTORS_SECTION_FUNCTION \
- TOC_SECTION_FUNCTION
+ TOC_SECTION_FUNCTION \
+ SDATA_SECTION_FUNCTION \
+ SDATA2_SECTION_FUNCTION \
+ SBSS_SECTION_FUNCTION \
+ INIT_SECTION_FUNCTION \
+ FINI_SECTION_FUNCTION
+
+extern void toc_section (), sdata_section (), sdata2_section ();
+extern void sbss_section ();
#define TOC_SECTION_FUNCTION \
void \
toc_section () \
{ \
- static int toc_initialized = 0; \
- \
if (in_section != in_toc) \
{ \
in_section = in_toc; \
- fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
- if (! toc_initialized) \
+ if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) \
+ && TARGET_MINIMAL_TOC \
+ && !TARGET_RELOCATABLE) \
{ \
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
- fprintf (asm_out_file, " = .+32768\n"); \
- toc_initialized = 1; \
+ if (! toc_initialized) \
+ { \
+ toc_initialized = 1; \
+ fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LCTOC", 0); \
+ fprintf (asm_out_file, "\t.tc "); \
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],"); \
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
+ fprintf (asm_out_file, "\n"); \
+ \
+ fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
+ fprintf (asm_out_file, " = .+32768\n"); \
+ } \
+ else \
+ fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
+ } \
+ else if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) \
+ && !TARGET_RELOCATABLE) \
+ fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \
+ else \
+ { \
+ fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
+ if (! toc_initialized) \
+ { \
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
+ fprintf (asm_out_file, " = .+32768\n"); \
+ toc_initialized = 1; \
+ } \
} \
} \
}
-#define TOC_SECTION_ASM_OP "\t.section\t\".got\",\"aw\""
-#define MINIMAL_TOC_SECTION_ASM_OP "\t.section\t\".got1\",\"aw\""
+#define SDATA_SECTION_FUNCTION \
+void \
+sdata_section () \
+{ \
+ if (in_section != in_sdata) \
+ { \
+ in_section = in_sdata; \
+ fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
+ } \
+}
-/* Use the TOC section for TOC entries. */
+#define SDATA2_SECTION_FUNCTION \
+void \
+sdata2_section () \
+{ \
+ if (in_section != in_sdata2) \
+ { \
+ in_section = in_sdata2; \
+ fprintf (asm_out_file, "%s\n", SDATA2_SECTION_ASM_OP); \
+ } \
+}
-#undef SELECT_RTX_SECTION
-#define SELECT_RTX_SECTION(MODE, X) \
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X)) \
- toc_section (); \
- else \
- const_section (); \
+#define SBSS_SECTION_FUNCTION \
+void \
+sbss_section () \
+{ \
+ if (in_section != in_sbss) \
+ { \
+ in_section = in_sbss; \
+ fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
+ } \
+}
+
+#define INIT_SECTION_FUNCTION \
+void \
+init_section () \
+{ \
+ if (in_section != in_init) \
+ { \
+ in_section = in_init; \
+ fprintf (asm_out_file, "%s\n", INIT_SECTION_ASM_OP); \
+ } \
+}
+
+#define FINI_SECTION_FUNCTION \
+void \
+fini_section () \
+{ \
+ if (in_section != in_fini) \
+ { \
+ in_section = in_fini; \
+ fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \
+ } \
}
+/* A C statement or statements to switch to the appropriate section
+ for output of RTX in mode MODE. You can assume that RTX is some
+ kind of constant in RTL. The argument MODE is redundant except in
+ the case of a `const_int' rtx. Select the section by calling
+ `text_section' or one of the alternatives for other sections.
+
+ Do not define this macro if you put all constants in the read-only
+ data section. */
+
+extern void rs6000_select_rtx_section (), rs6000_select_section ();
+
+#undef SELECT_RTX_SECTION
+#define SELECT_RTX_SECTION(MODE, X) rs6000_select_rtx_section (MODE, X)
+
+/* 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. */
+
+#undef SELECT_SECTION
+#define SELECT_SECTION(DECL,RELOC) rs6000_select_section (DECL, RELOC)
+
+/* Return non-zero if this entry is to be written into the constant pool
+ in a special way. We do so if this is a SYMBOL_REF, LABEL_REF or a CONST
+ containing one of them. If -mfp-in-toc (the default), we also do
+ this for floating-point constants. We actually can only do this
+ if the FP formats of the target and host machines are the same, but
+ we can't check that since not every file that uses
+ GO_IF_LEGITIMATE_ADDRESS_P includes real.h.
+
+ Unlike AIX, we don't key off of -mminimal-toc, but instead do not
+ allow floating point constants in the TOC if -mrelocatable. */
+
+#undef ASM_OUTPUT_SPECIAL_POOL_ENTRY_P
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X) \
+ (TARGET_TOC \
+ && (GET_CODE (X) == SYMBOL_REF \
+ || (GET_CODE (X) == CONST && GET_CODE (XEXP (X, 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF) \
+ || GET_CODE (X) == LABEL_REF \
+ || (!TARGET_NO_FP_IN_TOC \
+ && !TARGET_RELOCATABLE \
+ && GET_CODE (X) == CONST_DOUBLE \
+ && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ && BITS_PER_WORD == HOST_BITS_PER_INT)))
+
/* 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
@@ -269,37 +609,53 @@ toc_section () \
Some svr4 assemblers need to also have something extra said about the
function's return value. We allow for that here. */
-extern void svr4_traceback ();
extern int rs6000_pic_labelno;
#undef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do { \
- if (TARGET_RELOCATABLE && get_pool_size () != 0) \
+ char *orig_name; \
+ char *init_ptr = (TARGET_64BIT) ? ".quad" : ".long"; \
+ STRIP_NAME_ENCODING (orig_name, NAME); \
+ \
+ if (TARGET_RELOCATABLE && (get_pool_size () != 0 || profile_flag)) \
{ \
- char buf[256]; \
+ char buf[256], *buf_ptr; \
\
ASM_OUTPUT_INTERNAL_LABEL (FILE, "LCL", rs6000_pic_labelno); \
\
ASM_GENERATE_INTERNAL_LABEL (buf, "LCTOC", 1); \
- fprintf (FILE, (TARGET_POWERPC64) ? "\t.quad " : "\t.long "); \
- assemble_name (FILE, buf); \
- putc ('-', FILE); \
+ STRIP_NAME_ENCODING (buf_ptr, buf); \
+ fprintf (FILE, "\t%s %s-", init_ptr, buf_ptr); \
\
ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno); \
- assemble_name (FILE, buf); \
- putc ('\n', FILE); \
+ fprintf (FILE, "%s\n", buf_ptr); \
} \
\
- fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
- assemble_name (FILE, NAME); \
- putc (',', FILE); \
+ fprintf (FILE, "\t%s\t %s,", TYPE_ASM_OP, orig_name); \
fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
putc ('\n', FILE); \
- if (TARGET_TRACEBACK) \
- svr4_traceback (FILE, NAME, DECL); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- ASM_OUTPUT_LABEL(FILE, NAME); \
+ \
+ if (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT) \
+ { \
+ char *desc_name = orig_name; \
+ \
+ while (*desc_name == '.') \
+ desc_name++; \
+ \
+ if (TREE_PUBLIC (DECL)) \
+ fprintf (FILE, "\t.globl %s\n", desc_name); \
+ \
+ fprintf (FILE, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
+ fprintf (FILE, "%s:\n", desc_name); \
+ fprintf (FILE, "\t%s %s\n", init_ptr, orig_name); \
+ fprintf (FILE, "\t%s _GLOBAL_OFFSET_TABLE_\n", init_ptr); \
+ if (DEFAULT_ABI == ABI_AIX) \
+ fprintf (FILE, "\t%s 0\n", init_ptr); \
+ fprintf (FILE, "\t.previous\n"); \
+ } \
+ fprintf (FILE, "%s:\n", orig_name); \
} while (0)
/* How to renumber registers for dbx and gdb. */
@@ -312,196 +668,769 @@ extern int rs6000_pic_labelno;
#define ASM_OUTPUT_INTERNAL_LABEL_PREFIX(FILE,PREFIX) \
fprintf (FILE, ".%s", PREFIX)
-/* Pass -mppc to the assembler, since that is what powerpc.h currently
- implies. */
-#undef ASM_SPEC
-#define ASM_SPEC \
- "-u \
-%{mcpu=601: -m601} %{!mcpu=601: -mppc} \
-%{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
-%{mrelocatable} \
-%{mlittle} %{mlittle-endian} %{mbig} %{mbig-endian}"
-
-/* Output .file and comments listing what options there are */
+/* This is how to allocate empty space in some section. Use .space
+ instead of .zero because the Solaris PowerPC assembler doesn't
+ like it, and gas accepts either syntax. */
+
+#undef SKIP_ASM_OP
+#define SKIP_ASM_OP ".space"
+
+/* 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. */
+
+#ifndef LOCAL_ASM_OP
+#define LOCAL_ASM_OP ".local"
+#endif
+
+#ifndef LCOMM_ASM_OP
+#define LCOMM_ASM_OP ".lcomm"
+#endif
+
+#undef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+do { \
+ if (rs6000_sdata != SDATA_NONE && (SIZE) > 0 \
+ && (SIZE) <= g_switch_value) \
+ { \
+ sdata_section (); \
+ ASM_OUTPUT_ALIGN (FILE, exact_log2 (ALIGN / BITS_PER_UNIT)); \
+ ASM_OUTPUT_LABEL (FILE, NAME); \
+ ASM_OUTPUT_SKIP (FILE, SIZE); \
+ if (!flag_inhibit_size_directive && (SIZE) > 0) \
+ { \
+ fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ fprintf (FILE, ",%d\n", SIZE); \
+ } \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\t%s\t", LCOMM_ASM_OP); \
+ assemble_name ((FILE), (NAME)); \
+ fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
+ } \
+} while (0)
+
+/* Describe how to emit uninitialized external linkage items */
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+do { \
+ ASM_GLOBALIZE_LABEL (FILE, NAME); \
+ ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \
+} while (0)
+
+/* Switch Recognition by gcc.c. Add -G xx support */
+
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ ((CHAR) == 'D' || (CHAR) == 'U' || (CHAR) == 'o' \
+ || (CHAR) == 'e' || (CHAR) == 'T' || (CHAR) == 'u' \
+ || (CHAR) == 'I' || (CHAR) == 'm' || (CHAR) == 'x' \
+ || (CHAR) == 'L' || (CHAR) == 'A' || (CHAR) == 'V' \
+ || (CHAR) == 'B' || (CHAR) == 'b' || (CHAR) == 'G')
+
+/* Output .file. */
#undef ASM_FILE_START
#define ASM_FILE_START(FILE) \
do { \
- ASM_OUTPUT_OPTIONS (FILE); \
output_file_directive ((FILE), main_input_filename); \
+ rs6000_file_start (FILE, TARGET_CPU_DEFAULT); \
+} while (0)
+
+
+/* This is how to output an assembler line defining an `int' constant.
+ For -mrelocatable, we mark all addresses that need to be fixed up
+ in the .fixup section. */
+#undef ASM_OUTPUT_INT
+#define ASM_OUTPUT_INT(FILE,VALUE) \
+do { \
+ static int recurse = 0; \
+ if ((TARGET_RELOCATABLE || flag_pic) \
+ && in_section != in_toc \
+ && in_section != in_text \
+ && in_section != in_ctors \
+ && in_section != in_dtors \
+ && !recurse \
+ && GET_CODE (VALUE) != CONST_INT \
+ && GET_CODE (VALUE) != CONST_DOUBLE \
+ && CONSTANT_P (VALUE)) \
+ { \
+ static int labelno = 0; \
+ char buf[256], *p; \
+ \
+ recurse = 1; \
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCP", labelno++); \
+ STRIP_NAME_ENCODING (p, buf); \
+ fprintf (FILE, "%s:\n", p); \
+ fprintf (FILE, "\t.long ("); \
+ output_addr_const (FILE, (VALUE)); \
+ fprintf (FILE, ")@fixup\n"); \
+ fprintf (FILE, "\t.section \".fixup\",\"aw\"\n"); \
+ ASM_OUTPUT_ALIGN (FILE, 2); \
+ fprintf (FILE, "\t.long\t%s\n", p); \
+ fprintf (FILE, "\t.previous\n"); \
+ recurse = 0; \
+ } \
+ /* Remove initial .'s to turn a -mcall-aixdesc or -mcall-nt function \
+ address into the address of the descriptor, not the function \
+ itself. */ \
+ else if (GET_CODE (VALUE) == SYMBOL_REF \
+ && XSTR (VALUE, 0)[0] == '.' \
+ && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_NT)) \
+ { \
+ char *name = XSTR (VALUE, 0); \
+ while (*name == '.') \
+ name++; \
+ \
+ fprintf (FILE, "\t.long %s\n", name); \
+ } \
+ else \
+ { \
+ fprintf (FILE, "\t.long "); \
+ output_addr_const (FILE, (VALUE)); \
+ fprintf (FILE, "\n"); \
+ } \
} while (0)
/* This is the end of what might become sysv4.h. */
-/* Allow stabs and dwarf, prefer dwarf. */
-#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG
+/* Allow stabs and dwarf, for now, make stabs the default debugging type,
+ not dwarf since G++ doesn't support dwarf. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
#define DBX_DEBUGGING_INFO
#define DWARF_DEBUGGING_INFO
-/* This macro gets just the user-specified name
- out of the string in a SYMBOL_REF. Discard
- a leading * */
-#undef STRIP_NAME_ENCODING
-#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
- (VAR) = ((SYMBOL_NAME) + ((SYMBOL_NAME)[0] == '*'))
-
-/* Like block addresses, stabs line numbers are relative to the
- current function. */
-
-#undef ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(file, line) \
-do \
- { \
- static int sym_lineno = 1; \
- char *_p; \
- fprintf (file, "\t.stabn 68,0,%d,.LM%d-", \
- line, sym_lineno); \
- STRIP_NAME_ENCODING (_p, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
- assemble_name (file, _p); \
- fprintf (file, "\n.LM%d:\n", sym_lineno); \
- sym_lineno += 1; \
- } \
-while (0)
-
-/* But, to make this work, we have to output the stabs for the function
- name *first*... */
+/* If we are referencing a function that is static or is known to be
+ in this file, make the SYMBOL_REF special. We can use this to indicate
+ that we can branch to this function without emitting a no-op after the
+ call. For real AIX and NT calling sequences, we also replace the
+ function name with the real name (1 or 2 leading .'s), rather than
+ the function descriptor name. This saves a lot of overriding code
+ to readd the prefixes. */
-#define DBX_FUNCTION_FIRST
-
-/* This is the end of what might become sysv4dbx.h. */
+#undef ENCODE_SECTION_INFO
+#define ENCODE_SECTION_INFO(DECL) rs6000_encode_section_info (DECL)
-#undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (PowerPC System V.4)");
-
+extern void rs6000_encode_section_info ();
-/* Output assembler code for a block containing the constant parts
- of a trampoline, leaving space for the variable parts.
+/* This macro gets just the user-specified name
+ out of the string in a SYMBOL_REF. Discard
+ a leading * or @. */
+#undef STRIP_NAME_ENCODING
+#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
+do { \
+ char *_name = SYMBOL_NAME; \
+ while (*_name == '*' || *_name == '@') \
+ _name++; \
+ (VAR) = _name; \
+} while (0)
- The trampoline should set the static chain pointer to value placed
- into the trampoline and should branch to the specified routine.
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
- Unlike AIX, this needs real code. */
+#undef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+do { \
+ char *_name = NAME; \
+ while (*_name == '*' || *_name == '@') \
+ _name++; \
+ fputs (_name, FILE); \
+} while (0)
-#undef TRAMPOLINE_TEMPLATE
-#define TRAMPOLINE_TEMPLATE(FILE) \
+/*
+ * Switch into a generic 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.
+ *
+ * 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.
+ *
+ * Note, Solaris as doesn't like @nobits, and gas can handle .sbss without
+ * needing @nobits.
+ */
+
+#undef ASM_OUTPUT_SECTION_NAME
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
do { \
- char *sc = reg_names[STATIC_CHAIN_REGNUM]; \
- char *r0 = reg_names[0]; \
+ 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 (STATIC_CHAIN_REGNUM == 0 || !TARGET_NEW_MNEMONICS) \
- abort (); \
+ if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
+ type = SECT_EXEC, mode = "ax"; \
+ else if (DECL && DECL_READONLY_SECTION (DECL, RELOC) && !TARGET_RELOCATABLE && !flag_pic) \
+ type = SECT_RO, mode = "a"; \
+ else \
+ type = SECT_RW, mode = "aw"; \
\
- if (TARGET_64BIT) \
+ if (s == 0) \
{ \
- fprintf (FILE, "\tmflr %s\n", r0); /* offset 0 */ \
- fprintf (FILE, "\tbl .LTRAMP1\n"); /* offset 4 */ \
- fprintf (FILE, "\t.long 0,0,0,0\n"); /* offset 8 */ \
- fprintf (FILE, ".LTRAMP1:\n"); \
- fprintf (FILE, "\tmflr %s\n", sc); /* offset 28 */ \
- fprintf (FILE, "\tmtlr %s\n", r0); /* offset 32 */ \
- fprintf (FILE, "\tld %s,0(%s)\n", r0, sc); /* offset 36 */ \
- fprintf (FILE, "\tld %s,8(%s)\n", sc, sc); /* offset 40 */ \
- fprintf (FILE, "\tmtctr %s\n", r0); /* offset 44 */ \
- fprintf (FILE, "\tbctr\n"); /* offset 48 */ \
+ 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\"\n", NAME, mode); \
} \
else \
{ \
- fprintf (FILE, "\tmflr %s\n", r0); /* offset 0 */ \
- fprintf (FILE, "\tbl .LTRAMP1\n"); /* offset 4 */ \
- fprintf (FILE, "\t.long 0,0\n"); /* offset 8 */ \
- fprintf (FILE, ".LTRAMP1:\n"); \
- fprintf (FILE, "\tmflr %s\n", sc); /* offset 20 */ \
- fprintf (FILE, "\tmtlr %s\n", r0); /* offset 24 */ \
- fprintf (FILE, "\tlwz %s,0(%s)\n", r0, sc); /* offset 28 */ \
- fprintf (FILE, "\tlwz %s,4(%s)\n", sc, sc); /* offset 32 */ \
- fprintf (FILE, "\tmtctr %s\n", r0); /* offset 36 */ \
- fprintf (FILE, "\tbctr\n"); /* offset 40 */ \
+ if (DECL && s->type != type) \
+ error_with_decl (DECL, "%s causes a section type conflict"); \
+ \
+ fprintf (FILE, ".section\t%s\n", NAME); \
} \
} while (0)
-/* Length in units of the trampoline for entering a nested function. */
+#undef ASM_OUTPUT_CONSTRUCTOR
+#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
+ do { \
+ if (DEFAULT_ABI != ABI_SOLARIS) \
+ { \
+ ctors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ } \
+ else \
+ { \
+ init_section (); \
+ fputs ("\tbl ", FILE); \
+ assemble_name (FILE, NAME); \
+ } \
+ fputs ("\n", FILE); \
+ } while (0)
-#undef TRAMPOLINE_SIZE
-#define TRAMPOLINE_SIZE (TARGET_64BIT ? 48 : 40)
+/* 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 { \
+ if (DEFAULT_ABI != ABI_SOLARIS) \
+ { \
+ dtors_section (); \
+ fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
+ assemble_name (FILE, NAME); \
+ } \
+ else \
+ { \
+ fini_section (); \
+ fputs ("\tbl ", FILE); \
+ assemble_name (FILE, NAME); \
+ } \
+ fputs ("\n", FILE); \
+ } while (0)
-/* 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. */
+/* But, to make this work, we have to output the stabs for the function
+ name *first*... */
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
-{ \
- rtx reg = gen_reg_rtx (Pmode); \
- \
- emit_move_insn (reg, FNADDR); \
- emit_move_insn (gen_rtx (MEM, Pmode, \
- plus_constant (ADDR, 8)), \
- reg); \
- emit_move_insn (gen_rtx (MEM, Pmode, \
- plus_constant (ADDR, (TARGET_64BIT ? 16 : 12))), \
- CXT); \
- emit_insn (gen_sync_isync (gen_rtx (MEM, BLKmode, ADDR))); \
-}
+#define DBX_FUNCTION_FIRST
+/* This is the end of what might become sysv4dbx.h. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (PowerPC System V.4)");
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
"-DPPC -Dunix -D__svr4__ -Asystem(unix) -Asystem(svr4) -Acpu(powerpc) -Amachine(powerpc)"
+/* Pass various options to the assembler */
+#undef ASM_SPEC
+#define ASM_SPEC "%(asm_cpu) \
+%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
+%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+%{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} \
+%{memb} %{!memb: %{msdata: -memb} %{msdata=eabi: -memb}} \
+%{mlittle} %{mlittle-endian} %{mbig} %{mbig-endian} \
+%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
+ %{mcall-solaris: -mlittle -msolaris} %{mcall-linux: -mbig} }}}}"
+
+#undef CC1_SPEC
+/* Pass -G xxx to the compiler and set correct endian mode */
+#define CC1_SPEC "%{G*} \
+%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
+ %{mcall-nt: -mlittle } \
+ %{mcall-aixdesc: -mbig } \
+ %{mcall-solaris: -mlittle } \
+ %{mcall-linux: -mbig} }}}} \
+%{mcall-solaris: -mregnames } \
+%{mno-sdata: -msdata=none } \
+%{meabi: %{!mcall-*: -mcall-sysv }} \
+%{!meabi: %{!mno-eabi: \
+ %{mrelocatable: -meabi } \
+ %{mcall-solaris: -mno-eabi } \
+ %{mcall-linux: -mno-eabi }}} \
+%{msdata: -msdata=default} \
+%{mno-sdata: -msdata=none}"
+
/* Don't put -Y P,<path> for cross compilers */
+#undef LINK_PATH_SPEC
+#ifndef CROSS_COMPILE
+#define LINK_PATH_SPEC "\
+%{!R*:%{L*:-R %*}} \
+%{!nostdlib: %{!YP,*: \
+ %{compat-bsd: \
+ %{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*: %{!L*: -R /usr/ucblib}} \
+ %{!compat-bsd: \
+ %{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \
+ %{!p:-Y P,/usr/ccs/lib:/usr/lib}}}}"
+
+#else
+#define LINK_PATH_SPEC ""
+#endif
+
+/* Default starting address if specified */
+#ifndef LINK_START_SPEC
+#define LINK_START_SPEC "\
+%{mads: %(link_start_ads) } \
+%{myellowknife: %(link_start_yellowknife) } \
+%{mmvme: %(link_start_mvme) } \
+%{msim: %(link_start_sim) } \
+%{mcall-linux: %(link_start_linux) } \
+%{mcall-solaris: %(link_start_solaris) } \
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-solaris: %(link_start_default) }}}}}}"
+#endif
+
+#ifndef LINK_START_DEFAULT_SPEC
+#define LINK_START_DEFAULT_SPEC ""
+#endif
+
#undef LINK_SPEC
-#ifdef CROSS_COMPILE
#define LINK_SPEC "\
-%{h*} %{V} %{v:%{!V:-V}} \
-%{b} %{Wl,*:%*} \
-%{static:-dn -Bstatic} \
-%{shared:-G -dy -z text %{!h*:%{o*:-h %*}}} \
-%{symbolic:-Bsymbolic -G -dy -z text %{!h*:%{o*:-h %*}}} \
-%{G:-G} \
-%{YP,*} \
+%{h*} %{v:-V} %{G*} \
+%{Wl,*:%*} %{YP,*} %{R*} \
%{Qy:} %{!Qn:-Qy} \
-%{mlittle: -oformat elf32-powerpcle } %{mlittle-endian: -oformat elf32-powerpcle } \
-%{mbig: -oformat elf32-powerpc } %{mbig-endian: -oformat elf32-powerpc }"
-#else
+%(link_shlib) \
+%{!Ttext*: %(link_start) } \
+%(link_target) \
+%(link_os)"
+
+/* For now, turn off shared libraries by default. */
+#ifndef SHARED_LIB_SUPPORT
+#define NO_SHARED_LIB_SUPPORT
+#endif
-#define LINK_SPEC "\
-%{h*} %{V} %{v:%{!V:-V}} \
-%{b} %{Wl,*:%*} \
+#undef LINK_SHLIB_SPEC
+#ifndef NO_SHARED_LIB_SUPPORT
+/* Shared libraries are default. */
+#define LINK_SHLIB_SPEC "\
+%{!static: %(link_path) %{!R*:%{L*:-R %*}}} \
+%{mshlib: } \
%{static:-dn -Bstatic} \
-%{shared:-G -dy -z text %{!h*:%{o*:-h %*}}} \
-%{symbolic:-Bsymbolic -G -dy -z text %{!h*:%{o*:-h %*}}} \
-%{G:-G} \
-%{YP,*} \
-%{!nostdlib: %{!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} \
+%{shared:-G -dy -z text} \
+%{symbolic:-Bsymbolic -G -dy -z text}"
+
+#else
+/* Shared libraries are not default. */
+#define LINK_SHLIB_SPEC "\
+%{mshlib: %(link_path) } \
+%{!mshlib: %{!shared: %{!symbolic: -dn -Bstatic}}} \
+%{static: } \
+%{shared:-G -dy -z text %(link_path) } \
+%{symbolic:-Bsymbolic -G -dy -z text %(link_path) }"
+#endif
+
+/* Override the default target of the linker. */
+#undef LINK_TARGET_SPEC
+#define LINK_TARGET_SPEC "\
%{mlittle: -oformat elf32-powerpcle } %{mlittle-endian: -oformat elf32-powerpcle } \
-%{mbig: -oformat elf32-powerpc } %{mbig-endian: -oformat elf32-powerpc }"
-#endif /* CROSS_COMPILE */
+%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: %{mcall-solaris: -oformat elf32-powerpcle}}}}}"
+
+/* Any specific OS flags */
+#ifndef LINK_OS_SPEC
+#define LINK_OS_SPEC "\
+%{mads: %(link_os_ads) } \
+%{myellowknife: %(link_os_yellowknife) } \
+%{mmvme: %(link_os_mvme) } \
+%{msim: %(link_os_sim) } \
+%{mcall-linux: %(link_os_linux) } \
+%{mcall-solaris: %(link_os_solaris) } \
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-solaris: %(link_os_default) }}}}}}"
+#endif
+
+#ifndef LINK_OS_DEFAULT_SPEC
+#define LINK_OS_DEFAULT_SPEC ""
+#endif
+
+#undef CPP_SYSV_SPEC
+#define CPP_SYSV_SPEC \
+"%{mrelocatable*: -D_RELOCATABLE} \
+%{fpic: -D__PIC__=1 -D__pic__=1} \
+%{fPIC: -D__PIC__=2 -D__pic__=2} \
+%{mcall-sysv: -D_CALL_SYSV} %{mcall-nt: -D_CALL_NT} \
+%{mcall-aix: -D_CALL_AIX} %{mcall-aixdesc: -D_CALL_AIX -D_CALL_AIXDESC} \
+%{!mcall-sysv: %{!mcall-aix: %{!mcall-aixdesc: %{!mcall-nt: %(cpp_sysv_default) }}}} \
+%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT}"
+
+#undef CPP_SYSV_DEFAULT_SPEC
+#define CPP_SYSV_DEFAULT_SPEC "-D_CALL_SYSV"
+
+#ifndef CPP_ENDIAN_BIG_SPEC
+#define CPP_ENDIAN_BIG_SPEC "-D_BIG_ENDIAN -D__BIG_ENDIAN__ -Amachine(bigendian)"
+#endif
+
+#ifndef CPP_ENDIAN_LITTLE_SPEC
+#define CPP_ENDIAN_LITTLE_SPEC "-D_LITTLE_ENDIAN -D__LITTLE_ENDIAN__ -Amachine(littleendian)"
+#endif
+
+#ifndef CPP_ENDIAN_SOLARIS_SPEC
+#define CPP_ENDIAN_SOLARIS_SPEC "-D__LITTLE_ENDIAN__ -Amachine(littleendian)"
+#endif
+
+/* For solaris, don't define _LITTLE_ENDIAN, it conflicts with a header file. */
+#undef CPP_ENDIAN_SPEC
+#define CPP_ENDIAN_SPEC \
+"%{mlittle: %(cpp_endian_little) } \
+%{mlittle-endian: %(cpp_endian_little) } \
+%{mbig: %(cpp_endian_big) } \
+%{mbig-endian: %(cpp_endian_big) } \
+%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: \
+ %{mcall-solaris: %(cpp_endian_solaris) } \
+ %{mcall-nt: %(cpp_endian_little) } \
+ %{mcall-linux: %(cpp_endian_big) } \
+ %{mcall-aixdesc: %(cpp_endian_big) } \
+ %{!mcall-solaris: %{!mcall-linux: %{!mcall-nt: %{!mcall-aixdesc: %(cpp_endian_default) }}}}}}}}"
+
+#undef CPP_ENDIAN_DEFAULT_SPEC
+#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_big)"
#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
-%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
-%{mlittle: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{mlittle-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)} \
-%{!mlittle: %{!mlittle-endian: -D_BIG_ENDIAN -Amachine(bigendian)}} \
-%{!mcpu*: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
- %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} %(cpp_sysv) %(cpp_endian) %(cpp_cpu) \
+%{mads: %(cpp_os_ads) } \
+%{myellowknife: %(cpp_os_yellowknife) } \
+%{mmvme: %(cpp_os_mvme) } \
+%{msim: %(cpp_os_sim) } \
+%{mcall-linux: %(cpp_os_linux) } \
+%{mcall-solaris: %(cpp_os_solaris) } \
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-solaris: %(cpp_os_default) }}}}}}"
+
+#ifndef CPP_OS_DEFAULT_SPEC
+#define CPP_OS_DEFAULT_SPEC ""
+#endif
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "\
+%{mads: %(startfile_ads) } \
+%{myellowknife: %(startfile_yellowknife) } \
+%{mmvme: %(startfile_mvme) } \
+%{msim: %(startfile_sim) } \
+%{mcall-linux: %(startfile_linux) } \
+%{mcall-solaris: %(startfile_solaris) } \
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-solaris: %(startfile_default) }}}}}}"
+
+#undef STARTFILE_DEFAULT_SPEC
+#define STARTFILE_DEFAULT_SPEC ""
+
+#undef LIB_SPEC
+#define LIB_SPEC "\
+%{mads: %(lib_ads) } \
+%{myellowknife: %(lib_yellowknife) } \
+%{mmvme: %(lib_mvme) } \
+%{msim: %(lib_sim) } \
+%{mcall-linux: %(lib_linux) } \
+%{mcall-solaris: %(lib_solaris) } \
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-solaris: %(lib_default) }}}}}}"
+
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "libgcc.a%s"
+
+#ifndef LIB_DEFAULT_SPEC
+#define LIB_DEFAULT_SPEC ""
+#endif
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "\
+%{mads: ecrtn.o%s} \
+%{myellowknife: ecrtn.o%s} \
+%{mmvme: ecrtn.o%s} \
+%{msim: ecrtn.o%s} \
+%{mcall-linux: } \
+%{mcall-solaris: scrtn.o%s} \
+%{!mads: %{!myellowknife: %{!mmvme: %{!msim: %{!mcall-linux: %{!mcall-solaris: %(endfile_default) }}}}}}"
+
+#undef ENDFILE_DEFAULT_SPEC
+#define ENDFILE_DEFAULT_SPEC ""
+
+/* Motorola ADS support. */
+#ifndef LIB_ADS_SPEC
+#define LIB_ADS_SPEC "--start-group -lads -lc --end-group"
+#endif
+
+#ifndef STARTFILE_ADS_SPEC
+#define STARTFILE_ADS_SPEC "ecrti.o%s crt0.o%s"
+#endif
+
+#ifndef ENDFILE_ADS_SPEC
+#define ENDFILE_ADS_SPEC "ecrtn.o%s"
+#endif
+
+#ifndef LINK_START_ADS_SPEC
+#define LINK_START_ADS_SPEC "-T ads.ld%s"
+#endif
+
+#ifndef LINK_OS_ADS_SPEC
+#define LINK_OS_ADS_SPEC ""
+#endif
+
+#ifndef CPP_OS_ADS_SPEC
+#define CPP_OS_ADS_SPEC ""
+#endif
+
+/* Motorola Yellowknife support. */
+#ifndef LIB_YELLOWKNIFE_SPEC
+#define LIB_YELLOWKNIFE_SPEC "--start-group -lyk -lc --end-group"
+#endif
+
+#ifndef STARTFILE_YELLOWKNIFE_SPEC
+#define STARTFILE_YELLOWKNIFE_SPEC "ecrti.o%s crt0.o%s"
+#endif
+
+#ifndef ENDFILE_YELLOWKNIFE_SPEC
+#define ENDFILE_YELLOWKNIFE_SPEC "ecrtn.o%s"
+#endif
+
+#ifndef LINK_START_YELLOWKNIFE_SPEC
+#define LINK_START_YELLOWKNIFE_SPEC "-T yellowknife.ld%s"
+#endif
+
+#ifndef LINK_OS_YELLOWKNIFE_SPEC
+#define LINK_OS_YELLOWKNIFE_SPEC ""
+#endif
+
+#ifndef CPP_OS_YELLOWKNIFE_SPEC
+#define CPP_OS_YELLOWKNIFE_SPEC ""
+#endif
+
+/* Motorola MVME support. */
+#ifndef LIB_MVME_SPEC
+#define LIB_MVME_SPEC "--start-group -lmvme -lc --end-group"
+#endif
+
+#ifndef STARTFILE_MVME_SPEC
+#define STARTFILE_MVME_SPEC "ecrti.o%s crt0.o%s"
+#endif
+
+#ifndef ENDFILE_MVME_SPEC
+#define ENDFILE_MVME_SPEC "ecrtn.o%s"
+#endif
+
+#ifndef LINK_START_MVME_SPEC
+#define LINK_START_MVME_SPEC "%{!Wl,-T*: %{!T*: -Ttext 0x40000}}"
+#endif
+
+#ifndef LINK_OS_MVME_SPEC
+#define LINK_OS_MVME_SPEC ""
+#endif
+
+#ifndef CPP_OS_MVME_SPEC
+#define CPP_OS_MVME_SPEC ""
+#endif
+
+/* PowerPC simulator based on netbsd system calls support. */
+#ifndef LIB_SIM_SPEC
+#define LIB_SIM_SPEC "--start-group -lsim -lc --end-group"
+#endif
+
+#ifndef STARTFILE_SIM_SPEC
+#define STARTFILE_SIM_SPEC "ecrti.o%s sim-crt0.o%s"
+#endif
+
+#ifndef ENDFILE_SIM_SPEC
+#define ENDFILE_SIM_SPEC "ecrtn.o%s"
+#endif
+
+#ifndef LINK_START_SIM_SPEC
+#define LINK_START_SIM_SPEC "-Ttext 0x10000074"
+#endif
+
+#ifndef LINK_OS_SIM_SPEC
+#define LINK_OS_SIM_SPEC ""
+#endif
+
+#ifndef CPP_OS_SIM_SPEC
+#define CPP_OS_SIM_SPEC ""
+#endif
+
+/* GNU/Linux support. */
+#ifndef LIB_LINUX_SPEC
+#define LIB_LINUX_SPEC "%{mnewlib: --start-group -llinux -lc --end-group } %{!mnewlib: -lc }"
+#endif
+
+#ifndef STARTFILE_LINUX_SPEC
+#define STARTFILE_LINUX_SPEC "\
+%{!shared: %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \
+%{mnewlib: ecrti.o%s} \
+%{!mnewlib: crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
+#endif
+
+#ifndef ENDFILE_LINUX_SPEC
+#define ENDFILE_LINUX_SPEC "\
+%{mnewlib: ecrtn.o%s} \
+%{!mnewlib: %{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s}"
+#endif
+
+#ifndef LINK_START_LINUX_SPEC
+#define LINK_START_LINUX_SPEC "-Ttext 0x400074"
+#endif
+
+#ifndef LINK_OS_LINUX_SPEC
+#define LINK_OS_LINUX_SPEC ""
+#endif
+
+#ifndef CPP_OS_LINUX_SPEC
+#define CPP_OS_LINUX_SPEC "-D__unix__ -D__linux__ \
+%{!ansi: -Dunix -Dlinux } \
+-Asystem(unix) -Asystem(linux)"
+#endif
+
+#ifndef CPP_OS_LINUX_SPEC
+#define CPP_OS_LINUX_SPEC ""
+#endif
+
+/* Solaris support. */
+/* For Solaris, 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 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. */
+
+#ifndef LIB_SOLARIS_SPEC
+#define LIB_SOLARIS_SPEC "\
+%{mnewlib: --start-group -lsolaris -lc --end-group } \
+%{!mnewlib: \
+ %{ansi:values-Xc.o%s} \
+ %{!ansi: \
+ %{traditional:values-Xt.o%s} \
+ %{!traditional:values-Xa.o%s}} \
+ %{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
+ %{solaris-cclib: /opt/SUNWspro/SC4.0/lib/libabi.a} \
+ %{!shared: %{!symbolic: -lc }}}"
+#endif
+
+#ifndef STARTFILE_SOLARIS_SPEC
+#define STARTFILE_SOLARIS_SPEC "\
+%{!msolaris-cclib: scrti.o%s scrt0.o%s} \
+%{msolaris-cclib: /opt/SUNWspro/SC4.0/lib/crti.o%s /opt/SUNWspro/SC4.0/lib/crt1.o%s}"
+#endif
+
+#ifndef ENDFILE_SOLARIS_SPEC
+#define ENDFILE_SOLARIS_SPEC "\
+%{!msolaris-cclib: scrtn.o%s} \
+%{msolaris-cclib: /opt/SUNWspro/SC4.0/lib/crtn.o%s}"
+#endif
+
+#ifndef LINK_START_SOLARIS_SPEC
+#ifdef CROSS_COMPILER
+#define LINK_START_SOLARIS_SPEC "-Ttext 0x2000074"
+#else
+#define LINK_START_SOLARIS_SPEC ""
+#endif
+#endif
+
+#ifndef LINK_OS_SOLARIS_SPEC
+#define LINK_OS_SOLARIS_SPEC ""
+#endif
+
+#ifndef CPP_OS_SOLARIS_SPEC
+#define CPP_OS_SOLARIS_SPEC "-D__ppc -D__sun__=1 -D__unix__ -D__svr4__ -D__SVR4__ \
+%{!ansi: -Dsun=1 -Dunix -DSVR4 -D__EXTENSIONS__ } \
+-Amachine(prep)"
+#endif
+
+/* Define any extra SPECS that the compiler needs to generate. */
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "lib_ads", LIB_ADS_SPEC }, \
+ { "lib_yellowknife", LIB_YELLOWKNIFE_SPEC }, \
+ { "lib_mvme", LIB_MVME_SPEC }, \
+ { "lib_sim", LIB_SIM_SPEC }, \
+ { "lib_linux", LIB_LINUX_SPEC }, \
+ { "lib_solaris", LIB_SOLARIS_SPEC }, \
+ { "lib_default", LIB_DEFAULT_SPEC }, \
+ { "startfile_ads", STARTFILE_ADS_SPEC }, \
+ { "startfile_yellowknife", STARTFILE_YELLOWKNIFE_SPEC }, \
+ { "startfile_mvme", STARTFILE_MVME_SPEC }, \
+ { "startfile_sim", STARTFILE_SIM_SPEC }, \
+ { "startfile_linux", STARTFILE_LINUX_SPEC }, \
+ { "startfile_solaris", STARTFILE_SOLARIS_SPEC }, \
+ { "startfile_default", STARTFILE_DEFAULT_SPEC }, \
+ { "endfile_ads", ENDFILE_ADS_SPEC }, \
+ { "endfile_yellowknife", ENDFILE_YELLOWKNIFE_SPEC }, \
+ { "endfile_mvme", ENDFILE_MVME_SPEC }, \
+ { "endfile_sim", ENDFILE_SIM_SPEC }, \
+ { "endfile_linux", ENDFILE_LINUX_SPEC }, \
+ { "endfile_solaris", ENDFILE_SOLARIS_SPEC }, \
+ { "endfile_default", ENDFILE_DEFAULT_SPEC }, \
+ { "link_path", LINK_PATH_SPEC }, \
+ { "link_shlib", LINK_SHLIB_SPEC }, \
+ { "link_target", LINK_TARGET_SPEC }, \
+ { "link_start", LINK_START_SPEC }, \
+ { "link_start_ads", LINK_START_ADS_SPEC }, \
+ { "link_start_yellowknife", LINK_START_YELLOWKNIFE_SPEC }, \
+ { "link_start_mvme", LINK_START_MVME_SPEC }, \
+ { "link_start_sim", LINK_START_SIM_SPEC }, \
+ { "link_start_linux", LINK_START_LINUX_SPEC }, \
+ { "link_start_solaris", LINK_START_SOLARIS_SPEC }, \
+ { "link_start_default", LINK_START_DEFAULT_SPEC }, \
+ { "link_os", LINK_OS_SPEC }, \
+ { "link_os_ads", LINK_OS_ADS_SPEC }, \
+ { "link_os_yellowknife", LINK_OS_YELLOWKNIFE_SPEC }, \
+ { "link_os_mvme", LINK_OS_MVME_SPEC }, \
+ { "link_os_sim", LINK_OS_SIM_SPEC }, \
+ { "link_os_linux", LINK_OS_LINUX_SPEC }, \
+ { "link_os_solaris", LINK_OS_SOLARIS_SPEC }, \
+ { "link_os_default", LINK_OS_DEFAULT_SPEC }, \
+ { "cpp_endian_big", CPP_ENDIAN_BIG_SPEC }, \
+ { "cpp_endian_little", CPP_ENDIAN_LITTLE_SPEC }, \
+ { "cpp_endian_solaris", CPP_ENDIAN_SOLARIS_SPEC }, \
+ { "cpp_os_ads", CPP_OS_ADS_SPEC }, \
+ { "cpp_os_yellowknife", CPP_OS_YELLOWKNIFE_SPEC }, \
+ { "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
+ { "cpp_os_sim", CPP_OS_SIM_SPEC }, \
+ { "cpp_os_linux", CPP_OS_LINUX_SPEC }, \
+ { "cpp_os_solaris", CPP_OS_SOLARIS_SPEC }, \
+ { "cpp_os_default", CPP_OS_DEFAULT_SPEC },
+
+/* Define this macro as a C expression for the initializer of an
+ array of string to tell the driver program which options are
+ defaults for this target and thus do not need to be handled
+ specially when using `MULTILIB_OPTIONS'.
+
+ Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+ the target makefile fragment or if none of the options listed in
+ `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
+
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mbig", "mcall-sysv" }
+
+/* Define this macro if the code for function profiling should come
+ before the function prologue. Normally, the profiling code comes
+ after. */
+#define PROFILE_BEFORE_PROLOGUE 1
+
+/* Function name to call to do profiling. */
+#undef RS6000_MCOUNT
+#define RS6000_MCOUNT "_mcount"
diff --git a/gnu/usr.bin/gcc/config/rs6000/sysv4le.h b/gnu/usr.bin/gcc/config/rs6000/sysv4le.h
index 59bd1b72c83..0cf2ec49019 100644
--- a/gnu/usr.bin/gcc/config/rs6000/sysv4le.h
+++ b/gnu/usr.bin/gcc/config/rs6000/sysv4le.h
@@ -25,30 +25,22 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN)
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{posix: -D_POSIX_SOURCE} \
-%{mrelocatable: -D_RELOCATABLE} \
-%{mcall-sysv: -D_CALL_SYSV} %{mcall-aix: -D_CALL_AIX} %{!mcall-sysv: %{!mcall-aix: -D_CALL_SYSV}} \
-%{msoft-float: -D_SOFT_FLOAT} %{mcpu=403: -D_SOFT_FLOAT} \
-%{mbig: -D_BIG_ENDIAN -Amachine(bigendian)} \
-%{mbig-endian: -D_BIG_ENDIAN -Amachine(bigendian)} \
-%{!mbig: %{!mbig-endian: -D_LITTLE_ENDIAN -Amachine(littleendian)}} \
-%{!mcpu*: \
- %{mpower: %{!mpower2: -D_ARCH_PWR}} \
- %{mpower2: -D_ARCH_PWR2} \
- %{mpowerpc*: -D_ARCH_PPC} \
- %{mno-powerpc: %{!mpower: %{!mpower2: -D_ARCH_COM}}} \
- %{!mno-powerpc: -D_ARCH_PPC}} \
-%{mcpu=common: -D_ARCH_COM} \
-%{mcpu=power: -D_ARCH_PWR} \
-%{mcpu=powerpc: -D_ARCH_PPC} \
-%{mcpu=rios: -D_ARCH_PWR} \
-%{mcpu=rios1: -D_ARCH_PWR} \
-%{mcpu=rios2: -D_ARCH_PWR2} \
-%{mcpu=rsc: -D_ARCH_PWR} \
-%{mcpu=rsc1: -D_ARCH_PWR} \
-%{mcpu=403: -D_ARCH_PPC} \
-%{mcpu=601: -D_ARCH_PPC -D_ARCH_PWR} \
-%{mcpu=603: -D_ARCH_PPC} \
-%{mcpu=604: -D_ARCH_PPC}"
+#undef CPP_ENDIAN_DEFAULT_SPEC
+#define CPP_ENDIAN_DEFAULT_SPEC "%(cpp_endian_little)"
+
+#undef LINK_TARGET_SPEC
+#define LINK_TARGET_SPEC "\
+%{mbig: -oformat elf32-powerpc } %{mbig-endian: -oformat elf32-powerpc } \
+%{!mlittle: %{!mlittle-endian: %{!mbig: %{!mbig-endian: %{mcall-linux: -oformat elf32-powerpc}}}}}"
+
+/* Define this macro as a C expression for the initializer of an
+ array of string to tell the driver program which options are
+ defaults for this target and thus do not need to be handled
+ specially when using `MULTILIB_OPTIONS'.
+
+ Do not define this macro if `MULTILIB_OPTIONS' is not defined in
+ the target makefile fragment or if none of the options listed in
+ `MULTILIB_OPTIONS' are set by default. *Note Target Fragment::. */
+
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mlittle", "mcall-sysv" }
diff --git a/gnu/usr.bin/gcc/config/rs6000/t-newas b/gnu/usr.bin/gcc/config/rs6000/t-newas
index 382d15b7975..823b03b4b56 100644
--- a/gnu/usr.bin/gcc/config/rs6000/t-newas
+++ b/gnu/usr.bin/gcc/config/rs6000/t-newas
@@ -13,10 +13,34 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define FLOAT' > fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-# Build the libraries for both hard and soft floating point
+# Build the libraries for both hard and soft floating point and all of the
+# different processor models
-MULTILIB_OPTIONS = msoft-float mcpu=common
-MULTILIB_DIRNAMES = soft-float common
+MULTILIB_OPTIONS = msoft-float \
+ mcpu=common/mcpu=power/mcpu=powerpc
+
+MULTILIB_DIRNAMES = soft-float \
+ common power powerpc
+
+MULTILIB_MATCHES = msoft-float=mcpu?403 \
+ mcpu?power=mpower \
+ mcpu?power=mrios1 \
+ mcpu?power=mcpu?rios1 \
+ mcpu?power=mcpu?rsc \
+ mcpu?power=mcpu?rsc1 \
+ mcpu?power=mpower2 \
+ mcpu?power=mrios2 \
+ mcpu?power=mcpu=rios2 \
+ mcpu?powerpc=mcpu?601 \
+ mcpu?powerpc=mcpu?602 \
+ mcpu?powerpc=mcpu?603 \
+ mcpu?powerpc=mcpu?603e \
+ mcpu?powerpc=mcpu?604 \
+ mcpu?powerpc=mcpu?620 \
+ mcpu?powerpc=mcpu?403 \
+ mcpu?powerpc=mpowerpc \
+ mcpu?powerpc=mpowerpc-gpopt \
+ mcpu?powerpc=mpowerpc-gfxopt
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/rs6000/t-ppc b/gnu/usr.bin/gcc/config/rs6000/t-ppc
index 5fcb3d870e3..8143488a5d6 100644
--- a/gnu/usr.bin/gcc/config/rs6000/t-ppc
+++ b/gnu/usr.bin/gcc/config/rs6000/t-ppc
@@ -1,27 +1,12 @@
-# Do not build libgcc1.
-LIBGCC1 =
-CROSS_LIBGCC1 =
-
-# These are really part of libgcc1, but this will cause them to be
-# built correctly, so... [taken from t-sparclite]
-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
+# PowerPC support without gas
# Build libgcc.a with different options. If no gas support, don't build
# explicit little endian or big endian libraries, since it depends on the
-# -mbig/-mlittle switches passed to gas.
+# -mbig/-mlittle switches passed to gas. The -mrelocatable support also needs
+# -mrelocatable passed to gas, so don't use it either.
MULTILIB_OPTIONS = msoft-float
-MULTILIB_DIRNAMES = soft-float
-MULTILIB_MATCHES = msoft-float=mcpu?403 \
- msoft-float=mcpu?mpc403 \
- msoft-float=mcpu?ppc403
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
+MULTILIB_DIRNAMES = nof
+MULTILIB_EXCEPTIONS =
+MULTILIB_EXTRA_OPTS = mstrict-align
+MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT}
diff --git a/gnu/usr.bin/gcc/config/rs6000/t-ppcgas b/gnu/usr.bin/gcc/config/rs6000/t-ppcgas
index db4b936dcbf..9fb5e4ec328 100644
--- a/gnu/usr.bin/gcc/config/rs6000/t-ppcgas
+++ b/gnu/usr.bin/gcc/config/rs6000/t-ppcgas
@@ -1,30 +1,22 @@
-# Do not build libgcc1.
-LIBGCC1 =
-CROSS_LIBGCC1 =
-
-# These are really part of libgcc1, but this will cause them to be
-# built correctly, so... [taken from t-sparclite]
-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
-
+# PowerPC embedded support with gas.
# Build libgcc.a with different options.
MULTILIB_OPTIONS = msoft-float \
- mlittle
-
-MULTILIB_DIRNAMES = soft-float \
- little-endian
-
-MULTILIB_MATCHES = mlittle=mlittle-endian \
- msoft-float=mcpu?403 \
- msoft-float=mcpu?mpc403 \
- msoft-float=mcpu?ppc403
-
-LIBGCC = stmp-multilib
-INSTALL_LIBGCC = install-multilib
+ mlittle/mbig \
+ mcall-sysv/mcall-aix/mcall-solaris/mcall-linux
+
+MULTILIB_DIRNAMES = nof \
+ le be \
+ cs ca sol lin
+
+MULTILIB_EXTRA_OPTS = mrelocatable-lib mno-eabi mstrict-align
+MULTILIB_EXCEPTIONS = *mbig/*mcall-solaris* \
+ *mlittle/*mcall-solaris* \
+ *msoft-float/*mcall-solaris* \
+ *mbig/*mcall-linux* \
+ *mlittle/*mcall-linux* \
+ *msoft-float/*mcall-linux*
+
+MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT} \
+ ${MULTILIB_MATCHES_ENDIAN} \
+ ${MULTILIB_MATCHES_SYSV}
diff --git a/gnu/usr.bin/gcc/config/rs6000/x-rs6000 b/gnu/usr.bin/gcc/config/rs6000/x-rs6000
index ecfc0899079..0d8f3113fb5 100644
--- a/gnu/usr.bin/gcc/config/rs6000/x-rs6000
+++ b/gnu/usr.bin/gcc/config/rs6000/x-rs6000
@@ -1,5 +1,4 @@
# configuration for IBM rs6000 running aix
-INSTALL=/usr/ucb/install -c
# Show we need to use the C version of ALLOCA
ALLOCA=alloca.o
diff --git a/gnu/usr.bin/gcc/config/rs6000/xm-rs6000.h b/gnu/usr.bin/gcc/config/rs6000/xm-rs6000.h
index 9dbd41ed7ba..a027e3a63cd 100644
--- a/gnu/usr.bin/gcc/config/rs6000/xm-rs6000.h
+++ b/gnu/usr.bin/gcc/config/rs6000/xm-rs6000.h
@@ -44,7 +44,11 @@ Boston, MA 02111-1307, USA. */
/* If not compiled with GNU C, use the C alloca and use only int bitfields. */
#ifndef __GNUC__
#define USE_C_ALLOCA
+#if __STDC__
+extern void *alloca ();
+#else
extern char *alloca ();
+#endif
#define ONLY_INT_FIELDS
#endif
diff --git a/gnu/usr.bin/gcc/config/rs6000/xm-sysv4.h b/gnu/usr.bin/gcc/config/rs6000/xm-sysv4.h
index d67ae662e23..bc8f4bf299b 100644
--- a/gnu/usr.bin/gcc/config/rs6000/xm-sysv4.h
+++ b/gnu/usr.bin/gcc/config/rs6000/xm-sysv4.h
@@ -48,6 +48,23 @@ Boston, MA 02111-1307, USA. */
#include "xm-svr4.h"
+/* if not compiled with GNU C, use the C alloca and use only int bitfields. */
#ifndef __GNUC__
+#define USE_C_ALLOCA
+#ifdef __STDC__
+extern void *alloca ();
+#else
+extern char *alloca ();
+#endif
+#undef ONLY_INT_FIELDS
#define ONLY_INT_FIELDS
#endif
+
+#ifdef __PPC__
+#ifndef __STDC__
+extern char *malloc (), *realloc (), *calloc ();
+#else
+extern void *malloc (), *realloc (), *calloc ();
+#endif
+extern void free ();
+#endif
diff --git a/gnu/usr.bin/gcc/config/sh/lib1funcs.asm b/gnu/usr.bin/gcc/config/sh/lib1funcs.asm
index 6d8d3e8ffb4..923fa38c9f5 100644
--- a/gnu/usr.bin/gcc/config/sh/lib1funcs.asm
+++ b/gnu/usr.bin/gcc/config/sh/lib1funcs.asm
@@ -1,4 +1,4 @@
-/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1994, 1995, 1997 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
@@ -39,6 +39,16 @@ Boston, MA 02111-1307, USA. */
!! recoded in assembly by Toshiyasu Morita
!! tm@netcom.com
+/* SH2 optimizations for ___ashrsi3, ___ashlsi3, ___lshrsi3 and
+ ELF local label prefixes by J"orn Rennecke
+ amylaar@cygnus.com */
+
+#ifdef __ELF__
+#define LOCAL(X) .L_##X
+#else
+#define LOCAL(X) L_##X
+#endif
+
#ifdef L_ashiftrt
.global ___ashiftrt_r4_0
.global ___ashiftrt_r4_1
@@ -178,123 +188,127 @@ ___ashiftrt_r4_0:
.align 2
___ashrsi3:
mov #31,r0
- cmp/hi r0,r5
- bt L_ashrsi3_31
- mova L_ashrsi3_table,r0
+ and r0,r5
+ mova LOCAL(ashrsi3_table),r0
mov.b @(r0,r5),r5
- add r5,r0 ! Change to braf when gas is fixed
+#ifdef __sh1__
+ add r5,r0
jmp @r0
+#else
+ braf r5
+#endif
mov r4,r0
-L_ashrsi3_table:
- .byte L_ashrsi3_0-L_ashrsi3_table
- .byte L_ashrsi3_1-L_ashrsi3_table
- .byte L_ashrsi3_2-L_ashrsi3_table
- .byte L_ashrsi3_3-L_ashrsi3_table
- .byte L_ashrsi3_4-L_ashrsi3_table
- .byte L_ashrsi3_5-L_ashrsi3_table
- .byte L_ashrsi3_6-L_ashrsi3_table
- .byte L_ashrsi3_7-L_ashrsi3_table
- .byte L_ashrsi3_8-L_ashrsi3_table
- .byte L_ashrsi3_9-L_ashrsi3_table
- .byte L_ashrsi3_10-L_ashrsi3_table
- .byte L_ashrsi3_11-L_ashrsi3_table
- .byte L_ashrsi3_12-L_ashrsi3_table
- .byte L_ashrsi3_13-L_ashrsi3_table
- .byte L_ashrsi3_14-L_ashrsi3_table
- .byte L_ashrsi3_15-L_ashrsi3_table
- .byte L_ashrsi3_16-L_ashrsi3_table
- .byte L_ashrsi3_17-L_ashrsi3_table
- .byte L_ashrsi3_18-L_ashrsi3_table
- .byte L_ashrsi3_19-L_ashrsi3_table
- .byte L_ashrsi3_20-L_ashrsi3_table
- .byte L_ashrsi3_21-L_ashrsi3_table
- .byte L_ashrsi3_22-L_ashrsi3_table
- .byte L_ashrsi3_23-L_ashrsi3_table
- .byte L_ashrsi3_24-L_ashrsi3_table
- .byte L_ashrsi3_25-L_ashrsi3_table
- .byte L_ashrsi3_26-L_ashrsi3_table
- .byte L_ashrsi3_27-L_ashrsi3_table
- .byte L_ashrsi3_28-L_ashrsi3_table
- .byte L_ashrsi3_29-L_ashrsi3_table
- .byte L_ashrsi3_30-L_ashrsi3_table
- .byte L_ashrsi3_31-L_ashrsi3_table
-
-L_ashrsi3_31:
+ .align 2
+LOCAL(ashrsi3_table):
+ .byte LOCAL(ashrsi3_0)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_1)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_2)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_3)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_4)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_5)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_6)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_7)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_8)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_9)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_10)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_11)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_12)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_13)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_14)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_15)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_16)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_17)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_18)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_19)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_20)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_21)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_22)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_23)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_24)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_25)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_26)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_27)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_28)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_29)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_30)-LOCAL(ashrsi3_table)
+ .byte LOCAL(ashrsi3_31)-LOCAL(ashrsi3_table)
+
+LOCAL(ashrsi3_31):
rotcl r0
rts
subc r0,r0
-L_ashrsi3_30:
+LOCAL(ashrsi3_30):
shar r0
-L_ashrsi3_29:
+LOCAL(ashrsi3_29):
shar r0
-L_ashrsi3_28:
+LOCAL(ashrsi3_28):
shar r0
-L_ashrsi3_27:
+LOCAL(ashrsi3_27):
shar r0
-L_ashrsi3_26:
+LOCAL(ashrsi3_26):
shar r0
-L_ashrsi3_25:
+LOCAL(ashrsi3_25):
shar r0
-L_ashrsi3_24:
+LOCAL(ashrsi3_24):
shlr16 r0
shlr8 r0
rts
exts.b r0,r0
-L_ashrsi3_23:
+LOCAL(ashrsi3_23):
shar r0
-L_ashrsi3_22:
+LOCAL(ashrsi3_22):
shar r0
-L_ashrsi3_21:
+LOCAL(ashrsi3_21):
shar r0
-L_ashrsi3_20:
+LOCAL(ashrsi3_20):
shar r0
-L_ashrsi3_19:
+LOCAL(ashrsi3_19):
shar r0
-L_ashrsi3_18:
+LOCAL(ashrsi3_18):
shar r0
-L_ashrsi3_17:
+LOCAL(ashrsi3_17):
shar r0
-L_ashrsi3_16:
+LOCAL(ashrsi3_16):
shlr16 r0
rts
exts.w r0,r0
-L_ashrsi3_15:
+LOCAL(ashrsi3_15):
shar r0
-L_ashrsi3_14:
+LOCAL(ashrsi3_14):
shar r0
-L_ashrsi3_13:
+LOCAL(ashrsi3_13):
shar r0
-L_ashrsi3_12:
+LOCAL(ashrsi3_12):
shar r0
-L_ashrsi3_11:
+LOCAL(ashrsi3_11):
shar r0
-L_ashrsi3_10:
+LOCAL(ashrsi3_10):
shar r0
-L_ashrsi3_9:
+LOCAL(ashrsi3_9):
shar r0
-L_ashrsi3_8:
+LOCAL(ashrsi3_8):
shar r0
-L_ashrsi3_7:
+LOCAL(ashrsi3_7):
shar r0
-L_ashrsi3_6:
+LOCAL(ashrsi3_6):
shar r0
-L_ashrsi3_5:
+LOCAL(ashrsi3_5):
shar r0
-L_ashrsi3_4:
+LOCAL(ashrsi3_4):
shar r0
-L_ashrsi3_3:
+LOCAL(ashrsi3_3):
shar r0
-L_ashrsi3_2:
+LOCAL(ashrsi3_2):
shar r0
-L_ashrsi3_1:
+LOCAL(ashrsi3_1):
rts
shar r0
-L_ashrsi3_0:
+LOCAL(ashrsi3_0):
rts
nop
@@ -322,136 +336,136 @@ L_ashrsi3_0:
.align 2
___ashlsi3:
mov #31,r0
- cmp/hi r0,r5
- bt L_ashlsi3_32
- mova L_ashlsi3_table,r0
+ and r0,r5
+ mova LOCAL(ashlsi3_table),r0
mov.b @(r0,r5),r5
- add r5,r0 ! Change to braf when gas is fixed
+#ifdef __sh1__
+ add r5,r0
jmp @r0
+#else
+ braf r5
+#endif
mov r4,r0
-L_ashlsi3_table:
- .byte L_ashlsi3_0-L_ashlsi3_table
- .byte L_ashlsi3_1-L_ashlsi3_table
- .byte L_ashlsi3_2-L_ashlsi3_table
- .byte L_ashlsi3_3-L_ashlsi3_table
- .byte L_ashlsi3_4-L_ashlsi3_table
- .byte L_ashlsi3_5-L_ashlsi3_table
- .byte L_ashlsi3_6-L_ashlsi3_table
- .byte L_ashlsi3_7-L_ashlsi3_table
- .byte L_ashlsi3_8-L_ashlsi3_table
- .byte L_ashlsi3_9-L_ashlsi3_table
- .byte L_ashlsi3_10-L_ashlsi3_table
- .byte L_ashlsi3_11-L_ashlsi3_table
- .byte L_ashlsi3_12-L_ashlsi3_table
- .byte L_ashlsi3_13-L_ashlsi3_table
- .byte L_ashlsi3_14-L_ashlsi3_table
- .byte L_ashlsi3_15-L_ashlsi3_table
- .byte L_ashlsi3_16-L_ashlsi3_table
- .byte L_ashlsi3_17-L_ashlsi3_table
- .byte L_ashlsi3_18-L_ashlsi3_table
- .byte L_ashlsi3_19-L_ashlsi3_table
- .byte L_ashlsi3_20-L_ashlsi3_table
- .byte L_ashlsi3_21-L_ashlsi3_table
- .byte L_ashlsi3_22-L_ashlsi3_table
- .byte L_ashlsi3_23-L_ashlsi3_table
- .byte L_ashlsi3_24-L_ashlsi3_table
- .byte L_ashlsi3_25-L_ashlsi3_table
- .byte L_ashlsi3_26-L_ashlsi3_table
- .byte L_ashlsi3_27-L_ashlsi3_table
- .byte L_ashlsi3_28-L_ashlsi3_table
- .byte L_ashlsi3_29-L_ashlsi3_table
- .byte L_ashlsi3_30-L_ashlsi3_table
- .byte L_ashlsi3_31-L_ashlsi3_table
-
-L_ashlsi3_6:
+ .align 2
+LOCAL(ashlsi3_table):
+ .byte LOCAL(ashlsi3_0)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_1)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_2)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_3)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_4)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_5)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_6)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_7)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_8)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_9)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_10)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_11)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_12)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_13)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_14)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_15)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_16)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_17)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_18)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_19)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_20)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_21)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_22)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_23)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_24)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_25)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_26)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_27)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_28)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_29)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_30)-LOCAL(ashlsi3_table)
+ .byte LOCAL(ashlsi3_31)-LOCAL(ashlsi3_table)
+
+LOCAL(ashlsi3_6):
shll2 r0
-L_ashlsi3_4:
+LOCAL(ashlsi3_4):
shll2 r0
-L_ashlsi3_2:
+LOCAL(ashlsi3_2):
rts
shll2 r0
-L_ashlsi3_7:
+LOCAL(ashlsi3_7):
shll2 r0
-L_ashlsi3_5:
+LOCAL(ashlsi3_5):
shll2 r0
-L_ashlsi3_3:
+LOCAL(ashlsi3_3):
shll2 r0
-L_ashlsi3_1:
+LOCAL(ashlsi3_1):
rts
shll r0
-L_ashlsi3_14:
+LOCAL(ashlsi3_14):
shll2 r0
-L_ashlsi3_12:
+LOCAL(ashlsi3_12):
shll2 r0
-L_ashlsi3_10:
+LOCAL(ashlsi3_10):
shll2 r0
-L_ashlsi3_8:
+LOCAL(ashlsi3_8):
rts
shll8 r0
-L_ashlsi3_15:
+LOCAL(ashlsi3_15):
shll2 r0
-L_ashlsi3_13:
+LOCAL(ashlsi3_13):
shll2 r0
-L_ashlsi3_11:
+LOCAL(ashlsi3_11):
shll2 r0
-L_ashlsi3_9:
+LOCAL(ashlsi3_9):
shll8 r0
rts
shll r0
-L_ashlsi3_22:
+LOCAL(ashlsi3_22):
shll2 r0
-L_ashlsi3_20:
+LOCAL(ashlsi3_20):
shll2 r0
-L_ashlsi3_18:
+LOCAL(ashlsi3_18):
shll2 r0
-L_ashlsi3_16:
+LOCAL(ashlsi3_16):
rts
shll16 r0
-L_ashlsi3_23:
+LOCAL(ashlsi3_23):
shll2 r0
-L_ashlsi3_21:
+LOCAL(ashlsi3_21):
shll2 r0
-L_ashlsi3_19:
+LOCAL(ashlsi3_19):
shll2 r0
-L_ashlsi3_17:
+LOCAL(ashlsi3_17):
shll16 r0
rts
shll r0
-L_ashlsi3_30:
+LOCAL(ashlsi3_30):
shll2 r0
-L_ashlsi3_28:
+LOCAL(ashlsi3_28):
shll2 r0
-L_ashlsi3_26:
+LOCAL(ashlsi3_26):
shll2 r0
-L_ashlsi3_24:
+LOCAL(ashlsi3_24):
shll16 r0
rts
shll8 r0
-L_ashlsi3_31:
+LOCAL(ashlsi3_31):
shll2 r0
-L_ashlsi3_29:
+LOCAL(ashlsi3_29):
shll2 r0
-L_ashlsi3_27:
+LOCAL(ashlsi3_27):
shll2 r0
-L_ashlsi3_25:
+LOCAL(ashlsi3_25):
shll16 r0
shll8 r0
rts
shll r0
-L_ashlsi3_32:
- rts
- mov #0,r0
-
-L_ashlsi3_0:
+LOCAL(ashlsi3_0):
rts
nop
@@ -479,136 +493,136 @@ L_ashlsi3_0:
.align 2
___lshrsi3:
mov #31,r0
- cmp/hi r0,r5
- bt L_lshrsi3_32
- mova L_lshrsi3_table,r0
+ and r0,r5
+ mova LOCAL(lshrsi3_table),r0
mov.b @(r0,r5),r5
- add r5,r0 ! Change to braf when gas is fixed
+#ifdef __sh1__
+ add r5,r0
jmp @r0
+#else
+ braf r5
+#endif
mov r4,r0
-L_lshrsi3_table:
- .byte L_lshrsi3_0-L_lshrsi3_table
- .byte L_lshrsi3_1-L_lshrsi3_table
- .byte L_lshrsi3_2-L_lshrsi3_table
- .byte L_lshrsi3_3-L_lshrsi3_table
- .byte L_lshrsi3_4-L_lshrsi3_table
- .byte L_lshrsi3_5-L_lshrsi3_table
- .byte L_lshrsi3_6-L_lshrsi3_table
- .byte L_lshrsi3_7-L_lshrsi3_table
- .byte L_lshrsi3_8-L_lshrsi3_table
- .byte L_lshrsi3_9-L_lshrsi3_table
- .byte L_lshrsi3_10-L_lshrsi3_table
- .byte L_lshrsi3_11-L_lshrsi3_table
- .byte L_lshrsi3_12-L_lshrsi3_table
- .byte L_lshrsi3_13-L_lshrsi3_table
- .byte L_lshrsi3_14-L_lshrsi3_table
- .byte L_lshrsi3_15-L_lshrsi3_table
- .byte L_lshrsi3_16-L_lshrsi3_table
- .byte L_lshrsi3_17-L_lshrsi3_table
- .byte L_lshrsi3_18-L_lshrsi3_table
- .byte L_lshrsi3_19-L_lshrsi3_table
- .byte L_lshrsi3_20-L_lshrsi3_table
- .byte L_lshrsi3_21-L_lshrsi3_table
- .byte L_lshrsi3_22-L_lshrsi3_table
- .byte L_lshrsi3_23-L_lshrsi3_table
- .byte L_lshrsi3_24-L_lshrsi3_table
- .byte L_lshrsi3_25-L_lshrsi3_table
- .byte L_lshrsi3_26-L_lshrsi3_table
- .byte L_lshrsi3_27-L_lshrsi3_table
- .byte L_lshrsi3_28-L_lshrsi3_table
- .byte L_lshrsi3_29-L_lshrsi3_table
- .byte L_lshrsi3_30-L_lshrsi3_table
- .byte L_lshrsi3_31-L_lshrsi3_table
-
-L_lshrsi3_6:
+ .align 2
+LOCAL(lshrsi3_table):
+ .byte LOCAL(lshrsi3_0)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_1)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_2)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_3)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_4)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_5)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_6)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_7)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_8)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_9)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_10)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_11)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_12)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_13)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_14)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_15)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_16)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_17)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_18)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_19)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_20)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_21)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_22)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_23)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_24)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_25)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_26)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_27)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_28)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_29)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_30)-LOCAL(lshrsi3_table)
+ .byte LOCAL(lshrsi3_31)-LOCAL(lshrsi3_table)
+
+LOCAL(lshrsi3_6):
shlr2 r0
-L_lshrsi3_4:
+LOCAL(lshrsi3_4):
shlr2 r0
-L_lshrsi3_2:
+LOCAL(lshrsi3_2):
rts
shlr2 r0
-L_lshrsi3_7:
+LOCAL(lshrsi3_7):
shlr2 r0
-L_lshrsi3_5:
+LOCAL(lshrsi3_5):
shlr2 r0
-L_lshrsi3_3:
+LOCAL(lshrsi3_3):
shlr2 r0
-L_lshrsi3_1:
+LOCAL(lshrsi3_1):
rts
shlr r0
-L_lshrsi3_14:
+LOCAL(lshrsi3_14):
shlr2 r0
-L_lshrsi3_12:
+LOCAL(lshrsi3_12):
shlr2 r0
-L_lshrsi3_10:
+LOCAL(lshrsi3_10):
shlr2 r0
-L_lshrsi3_8:
+LOCAL(lshrsi3_8):
rts
shlr8 r0
-L_lshrsi3_15:
+LOCAL(lshrsi3_15):
shlr2 r0
-L_lshrsi3_13:
+LOCAL(lshrsi3_13):
shlr2 r0
-L_lshrsi3_11:
+LOCAL(lshrsi3_11):
shlr2 r0
-L_lshrsi3_9:
+LOCAL(lshrsi3_9):
shlr8 r0
rts
shlr r0
-L_lshrsi3_22:
+LOCAL(lshrsi3_22):
shlr2 r0
-L_lshrsi3_20:
+LOCAL(lshrsi3_20):
shlr2 r0
-L_lshrsi3_18:
+LOCAL(lshrsi3_18):
shlr2 r0
-L_lshrsi3_16:
+LOCAL(lshrsi3_16):
rts
shlr16 r0
-L_lshrsi3_23:
+LOCAL(lshrsi3_23):
shlr2 r0
-L_lshrsi3_21:
+LOCAL(lshrsi3_21):
shlr2 r0
-L_lshrsi3_19:
+LOCAL(lshrsi3_19):
shlr2 r0
-L_lshrsi3_17:
+LOCAL(lshrsi3_17):
shlr16 r0
rts
shlr r0
-L_lshrsi3_30:
+LOCAL(lshrsi3_30):
shlr2 r0
-L_lshrsi3_28:
+LOCAL(lshrsi3_28):
shlr2 r0
-L_lshrsi3_26:
+LOCAL(lshrsi3_26):
shlr2 r0
-L_lshrsi3_24:
+LOCAL(lshrsi3_24):
shlr16 r0
rts
shlr8 r0
-L_lshrsi3_31:
+LOCAL(lshrsi3_31):
shlr2 r0
-L_lshrsi3_29:
+LOCAL(lshrsi3_29):
shlr2 r0
-L_lshrsi3_27:
+LOCAL(lshrsi3_27):
shlr2 r0
-L_lshrsi3_25:
+LOCAL(lshrsi3_25):
shlr16 r0
shlr8 r0
rts
shlr r0
-L_lshrsi3_32:
- rts
- mov #0,r0
-
-L_lshrsi3_0:
+LOCAL(lshrsi3_0):
rts
nop
diff --git a/gnu/usr.bin/gcc/config/sh/sh.c b/gnu/usr.bin/gcc/config/sh/sh.c
index bbb708c10a1..b4be01e76ec 100644
--- a/gnu/usr.bin/gcc/config/sh/sh.c
+++ b/gnu/usr.bin/gcc/config/sh/sh.c
@@ -1,5 +1,5 @@
/* Output routines for GCC for Hitachi Super-H.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -33,6 +33,9 @@ Boston, MA 02111-1307, USA. */
#include "regs.h"
#include "hard-reg-set.h"
#include "output.h"
+#include "insn-attr.h"
+
+int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
#define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
#define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
@@ -42,10 +45,27 @@ Boston, MA 02111-1307, USA. */
output code for the next function appropriate for an interrupt handler. */
int pragma_interrupt;
+/* This is set by the trap_exit attribute for functions. It specifies
+ a trap number to be used in a trapa instruction at function exit
+ (instead of an rte instruction). */
+int trap_exit;
+
+/* This is used by the sp_switch attribute for functions. It specifies
+ a variable holding the address of the stack the interrupt function
+ should switch to/from at entry/exit. */
+rtx sp_switch;
+
/* This is set by #pragma trapa, and is similar to the above, except that
the compiler doesn't emit code to preserve all registers. */
static int pragma_trapa;
+/* This is set by #pragma nosave_low_regs. This is useful on the SH3,
+ which has a separate set of low regs for User and Supervisor modes.
+ This should only be used for the lowest level of interrupts. Higher levels
+ of interrupts must save the registers in case they themselves are
+ interrupted. */
+int pragma_nosave_low_regs;
+
/* This is used for communication between SETUP_INCOMING_VARARGS and
sh_expand_prologue. */
int current_function_anonymous_args;
@@ -66,6 +86,10 @@ enum processor_type sh_cpu;
rtx sh_compare_op0;
rtx sh_compare_op1;
+enum machine_mode sh_addr_diff_vec_mode;
+rtx *uid_align;
+int uid_align_max;
+
/* Provides the class number of the smallest class containing
reg number. */
@@ -76,7 +100,11 @@ int regno_reg_class[FIRST_PSEUDO_REGISTER] =
GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
GENERAL_REGS, PR_REGS, T_REGS, NO_REGS,
- MAC_REGS, MAC_REGS,
+ MAC_REGS, MAC_REGS, FPUL_REGS, GENERAL_REGS,
+ FP0_REGS,FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
};
/* Provide reg_class from a letter such as appears in the machine
@@ -85,13 +113,15 @@ int regno_reg_class[FIRST_PSEUDO_REGISTER] =
enum reg_class reg_class_from_letter[] =
{
/* a */ NO_REGS, /* b */ NO_REGS, /* c */ NO_REGS, /* d */ NO_REGS,
- /* e */ NO_REGS, /* f */ NO_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
+ /* e */ NO_REGS, /* f */ FP_REGS, /* g */ NO_REGS, /* h */ NO_REGS,
/* i */ NO_REGS, /* j */ NO_REGS, /* k */ NO_REGS, /* l */ PR_REGS,
/* m */ NO_REGS, /* n */ NO_REGS, /* o */ NO_REGS, /* p */ NO_REGS,
/* q */ NO_REGS, /* r */ NO_REGS, /* s */ NO_REGS, /* t */ T_REGS,
- /* u */ NO_REGS, /* v */ NO_REGS, /* w */ NO_REGS, /* x */ MAC_REGS,
- /* y */ NO_REGS, /* z */ R0_REGS
+ /* u */ NO_REGS, /* v */ NO_REGS, /* w */ FP0_REGS, /* x */ MAC_REGS,
+ /* y */ FPUL_REGS, /* z */ R0_REGS
};
+
+static void split_branches PROTO ((rtx));
/* Print the operand address in x to the stream. */
@@ -148,7 +178,8 @@ print_operand_address (stream, x)
according to modifier code.
'.' print a .s if insn needs delay slot
- '@' print rte or rts depending upon pragma interruptness
+ ',' print LOCAL_LABEL_PREFIX
+ '@' print trap, rte or rts depending upon pragma interruptness
'#' output a nop if there is nothing to put in the delay slot
'O' print a constant without the #
'R' print the LSW of a dp value - changes if in little endian
@@ -166,10 +197,15 @@ print_operand (stream, x, code)
case '.':
if (final_sequence
&& ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
- fprintf (stream, ".s");
+ fprintf (stream, ASSEMBLER_DIALECT ? "/s" : ".s");
+ break;
+ case ',':
+ fprintf (stream, "%s", LOCAL_LABEL_PREFIX);
break;
case '@':
- if (pragma_interrupt)
+ if (trap_exit)
+ fprintf (stream, "trapa #%d", trap_exit);
+ else if (pragma_interrupt)
fprintf (stream, "rte");
else
fprintf (stream, "rts");
@@ -303,11 +339,23 @@ prepare_move_operands (operands, mode)
rtx operands[];
enum machine_mode mode;
{
- /* Copy the source to a register if both operands aren't registers. */
- if (! reload_in_progress && ! reload_completed
- && ! register_operand (operands[0], mode)
- && ! register_operand (operands[1], mode))
- operands[1] = copy_to_mode_reg (mode, operands[1]);
+ if (! reload_in_progress && ! reload_completed)
+ {
+ /* Copy the source to a register if both operands aren't registers. */
+ if (! register_operand (operands[0], mode)
+ && ! register_operand (operands[1], mode))
+ operands[1] = copy_to_mode_reg (mode, operands[1]);
+
+ /* This case can happen while generating code to move the result
+ of a library call to the target. Reject `st r0,@(rX,rY)' because
+ reload will fail to find a spill register for rX, since r0 is already
+ being used for the source. */
+ else if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 0
+ && GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == REG)
+ operands[1] = copy_to_mode_reg (mode, operands[1]);
+ }
return 0;
}
@@ -353,9 +401,10 @@ prepare_scc_operands (code)
mode = GET_MODE (sh_compare_op1);
sh_compare_op0 = force_reg (mode, sh_compare_op0);
- if (code != EQ && code != NE
- && (sh_compare_op1 != const0_rtx
- || code == GTU || code == GEU || code == LTU || code == LEU))
+ if ((code != EQ && code != NE
+ && (sh_compare_op1 != const0_rtx
+ || code == GTU || code == GEU || code == LTU || code == LEU))
+ || TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT)
sh_compare_op1 = force_reg (mode, sh_compare_op1);
emit_insn (gen_rtx (SET, VOIDmode, t_reg,
@@ -372,16 +421,31 @@ from_compare (operands, code)
rtx *operands;
int code;
{
- if (code != EQ && code != NE)
+ enum machine_mode mode = GET_MODE (sh_compare_op0);
+ rtx insn;
+ if (mode == VOIDmode)
+ mode = GET_MODE (sh_compare_op1);
+ if (code != EQ
+ || mode == DImode
+ || (TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT))
{
/* Force args into regs, since we can't use constants here. */
- sh_compare_op0 = force_reg (SImode, sh_compare_op0);
+ sh_compare_op0 = force_reg (mode, sh_compare_op0);
if (sh_compare_op1 != const0_rtx
- || code == GTU || code == GEU || code == LTU || code == LEU)
- sh_compare_op1 = force_reg (SImode, sh_compare_op1);
+ || code == GTU || code == GEU
+ || (TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT))
+ sh_compare_op1 = force_reg (mode, sh_compare_op1);
+ }
+ if (TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT && code == GE)
+ {
+ from_compare (operands, GT);
+ insn = gen_ieee_ccmpeqsf_t (sh_compare_op0, sh_compare_op1);
}
- operands[1] = sh_compare_op0;
- operands[2] = sh_compare_op1;
+ else
+ insn = gen_rtx (SET, VOIDmode,
+ gen_rtx (REG, SImode, 18),
+ gen_rtx (code, SImode, sh_compare_op0, sh_compare_op1));
+ emit_insn (insn);
}
/* Functions to output assembly code. */
@@ -478,33 +542,54 @@ print_slot (insn)
INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
}
-/* We can't tell if we need a register as a scratch for the jump
- until after branch shortening, and then it's too late to allocate a
- register the 'proper' way. These instruction sequences are rare
- anyway, so to avoid always using a reg up from our limited set, we'll
- grab one when we need one on output. */
-
-/* ??? Should fix compiler so that using a clobber scratch in jump
- instructions works, and then this will be unnecessary. */
-
char *
output_far_jump (insn, op)
rtx insn;
rtx op;
{
- rtx thislab = gen_label_rtx ();
+ struct { rtx lab, reg, op; } this;
+ char *jump;
+ int far;
- /* Output the delay slot insn first if any. */
- if (dbr_sequence_length ())
- print_slot (final_sequence);
+ this.lab = gen_label_rtx ();
- output_asm_insn ("mov.l r13,@-r15", 0);
- output_asm_insn ("mov.l %O0,r13", &thislab);
- output_asm_insn ("jmp @r13", 0);
- output_asm_insn ("mov.l @r15+,r13", 0);
- output_asm_insn (".align 2", 0);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (thislab));
- output_asm_insn (".long %O0", &op);
+ if (braf_branch_p (insn, 0))
+ {
+ far = 0;
+ jump = "mov.w %O0,%1;braf %1";
+ }
+ else
+ {
+ far = 1;
+ jump = "mov.l %O0,%1;jmp @%1";
+ }
+ /* If we have a scratch register available, use it. */
+ if (GET_CODE (PREV_INSN (insn)) == INSN
+ && INSN_CODE (PREV_INSN (insn)) == CODE_FOR_indirect_jump_scratch)
+ {
+ this.reg = SET_DEST (PATTERN (PREV_INSN (insn)));
+ output_asm_insn (jump, &this.lab);
+ if (dbr_sequence_length ())
+ print_slot (final_sequence);
+ else
+ output_asm_insn ("nop", 0);
+ }
+ else
+ {
+ /* Output the delay slot insn first if any. */
+ if (dbr_sequence_length ())
+ print_slot (final_sequence);
+
+ this.reg = gen_rtx (REG, SImode, 13);
+ output_asm_insn ("mov.l r13,@-r15", 0);
+ output_asm_insn (jump, &this.lab);
+ output_asm_insn ("mov.l @r15+,r13", 0);
+ }
+ if (far)
+ output_asm_insn (".align 2", 0);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (this.lab));
+ this.op = op;
+ output_asm_insn (far ? ".long %O2" : ".word %O2-%O0", &this.lab);
return "";
}
@@ -521,177 +606,107 @@ output_branch (logic, insn, operands)
rtx insn;
rtx *operands;
{
- int label = lf++;
+ int offset
+ = (insn_addresses[INSN_UID (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0))]
+ - insn_addresses[INSN_UID (insn)]);
- switch (get_attr_length (insn))
+ if (offset == 260
+ && final_sequence
+ && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
{
- case 2:
- /* A branch with an unfilled delay slot. */
- case 4:
- /* Simple branch in range -252..+258 bytes */
- return logic ? "bt%. %l0" : "bf%. %l0";
-
- case 6:
- /* A branch with an unfilled delay slot. */
- case 8:
- /* Branch in range -4092..+4098 bytes. */
- {
- /* The call to print_slot will clobber the operands. */
- rtx op0 = operands[0];
-
- /* If the instruction in the delay slot is annulled (true), then
- there is no delay slot where we can put it now. The only safe
- place for it is after the label. */
+ /* The filling of the delay slot has caused a forward branch to exceed
+ its range.
+ Just emit the insn from the delay slot in front of the branch. */
+ /* The call to print_slot will clobber the operands. */
+ rtx op0 = operands[0];
+ print_slot (final_sequence);
+ operands[0] = op0;
+ }
+ else if (offset < -252 || offset > 258)
+ {
+ /* This can happen when other condbranches hoist delay slot insn
+ from their destination, thus leading to code size increase.
+ But the branch will still be in the range -4092..+4098 bytes. */
- if (final_sequence)
- {
- fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't',
- INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
- ? "" : ".s", label);
- if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
- print_slot (final_sequence);
- }
- else
- fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
+ int label = lf++;
+ /* The call to print_slot will clobber the operands. */
+ rtx op0 = operands[0];
- output_asm_insn ("bra %l0", &op0);
- fprintf (asm_out_file, "\tnop\n");
- fprintf (asm_out_file, "LF%d:\n", label);
+ /* If the instruction in the delay slot is annulled (true), then
+ there is no delay slot where we can put it now. The only safe
+ place for it is after the label. final will do that by default. */
- if (final_sequence
- && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
+ if (final_sequence
+ && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
+ {
+ asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n", logic ? "f" : "t",
+ ASSEMBLER_DIALECT ? "/" : ".", label);
print_slot (final_sequence);
- }
- return "";
-
- case 16:
- /* A branch with an unfilled delay slot. */
- case 18:
- /* Branches a long way away. */
- {
- /* The call to print_slot will clobber the operands. */
- rtx op0 = operands[0];
-
- /* If the instruction in the delay slot is annulled (true), then
- there is no delay slot where we can put it now. The only safe
- place for it is after the label. */
-
- if (final_sequence)
- {
- fprintf (asm_out_file, "\tb%c%s\tLF%d\n", logic ? 'f' : 't',
- INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))
- ? "" : ".s", label);
- if (! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
- print_slot (final_sequence);
- }
- else
- fprintf (asm_out_file, "\tb%c\tLF%d\n", logic ? 'f' : 't', label);
+ }
+ else
+ asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t", label);
- output_far_jump (insn, op0);
- fprintf (asm_out_file, "LF%d:\n", label);
+ output_asm_insn ("bra\t%l0", &op0);
+ fprintf (asm_out_file, "\tnop\n");
+ ASM_OUTPUT_INTERNAL_LABEL(asm_out_file, "LF", label);
- if (final_sequence
- && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
- print_slot (final_sequence);
- }
return "";
}
- return "bad";
+ return logic ? "bt%.\t%l0" : "bf%.\t%l0";
}
-
-/* A copy of the option structure defined in toplev.c. */
-
-struct option
-{
- char *string;
- int *variable;
- int on_value;
-};
-/* Output a single output option string NAME to FILE, without generating
- lines longer than MAX. */
+int branch_offset ();
-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;
+char *
+output_branchy_insn (code, template, insn, operands)
+ char *template;
+ enum rtx_code code;
+ rtx insn;
+ rtx *operands;
{
- if (strlen (sep) + strlen (type) + strlen (name) + pos > max)
+ rtx next_insn = NEXT_INSN (insn);
+ int label_nr;
+
+ if (next_insn && GET_CODE (next_insn) == JUMP_INSN && condjump_p (next_insn))
{
- fprintf (file, indent);
- return fprintf (file, "%s%s", type, name);
+ rtx src = SET_SRC (PATTERN (next_insn));
+ if (GET_CODE (src) == IF_THEN_ELSE && GET_CODE (XEXP (src, 0)) != code)
+ {
+ /* Following branch not taken */
+ operands[9] = gen_label_rtx ();
+ emit_label_after (operands[9], next_insn);
+ return template;
+ }
+ else
+ {
+ int offset = branch_offset (next_insn) + 4;
+ if (offset >= -252 && offset <= 256)
+ {
+ if (GET_CODE (src) == IF_THEN_ELSE)
+ /* branch_true */
+ src = XEXP (src, 1);
+ operands[9] = src;
+ return template;
+ }
+ }
}
- return pos + fprintf (file, "%s%s%s", sep, type, name);
+ operands[9] = gen_label_rtx ();
+ emit_label_after (operands[9], insn);
+ return template;
}
-/* A copy of the target_switches variable in toplev.c. */
-
-static struct
-{
- char *name;
- int value;
-} m_options[] = TARGET_SWITCHES;
-
-/* Output all options to the assembly language file. */
-
-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 *sep;
- char *indent;
- char *term;
+char *
+output_ieee_ccmpeq (insn, operands)
+ rtx insn, operands;
{
- 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 (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);
-
- fprintf (file, term);
+ output_branchy_insn (NE, "bt\t%l9\\;fcmp/eq\t%1,%0", insn, operands);
}
-
+
/* Output to FILE the start of the assembler file. */
void
-output_file_start (file, f_options, f_len, W_options, W_len)
+output_file_start (file)
FILE *file;
- struct option *f_options;
- struct option *W_options;
- int f_len, W_len;
{
register int pos;
@@ -701,10 +716,6 @@ output_file_start (file, f_options, f_len, W_options, W_len)
gcc2_compiled. symbol aren't in the text section. */
data_section ();
- pos = fprintf (file, "\n! Hitachi SH cc1 (%s) arguments:", version_string);
- output_options (file, f_options, f_len, W_options, W_len,
- pos, 75, " ", "\n! ", "\n\n");
-
if (TARGET_LITTLE_ENDIAN)
fprintf (file, "\t.little\n");
}
@@ -731,6 +742,28 @@ static short shift_amounts[32][5] = {
{16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},
{16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};
+/* Likewise, but for shift amounts < 16, up to three highmost bits
+ might be clobbered. This is typically used when combined with some
+ kind of sign or zero extension. */
+
+static char ext_shift_insns[] =
+ { 0,1,1,2,2,3,2,2,1,2,2,3,3,3,2,2,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};
+
+static short ext_shift_amounts[32][4] = {
+ {0}, {1}, {2}, {2, 1},
+ {2, 2}, {2, 1, 2}, {8, -2}, {8, -1},
+ {8}, {8, 1}, {8, 2}, {8, 1, 2},
+ {8, 2, 2}, {16, -2, -1}, {16, -2}, {16, -1},
+ {16}, {16, 1}, {16, 2}, {16, 1, 2},
+ {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},
+ {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},
+ {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};
+
+/* Assuming we have a value that has been sign-extended by at least one bit,
+ can we use the ext_shift_amounts with the last shift turned to an arithmetic shift
+ to shift it by N without data loss, and quicker than by other means? */
+#define EXT_SHIFT_SIGNED(n) (((n) | 8) == 15)
+
/* This is used in length attributes in sh.md to help compute the length
of arbitrary constant shift instructions. */
@@ -764,16 +797,17 @@ shiftcosts (x)
/* If shift by a non constant, then this will be expensive. */
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
- {
- if (TARGET_SH3)
- return 2;
- /* If not an sh3 then we don't even have an instruction for it. */
- return 20;
- }
+ return SH_DYNAMIC_SHIFT_COST;
/* Otherwise, return the true cost in instructions. */
if (GET_CODE (x) == ASHIFTRT)
- return ashiftrt_insns[value];
+ {
+ int cost = ashiftrt_insns[value];
+ /* If SH3, then we put the constant in a reg and use shad. */
+ if (cost > 1 + SH_DYNAMIC_SHIFT_COST)
+ cost = 1 + SH_DYNAMIC_SHIFT_COST;
+ return cost;
+ }
else
return shift_insns[value];
}
@@ -866,12 +900,44 @@ gen_ashift (type, n, reg)
}
}
+/* Same for HImode */
+
+void
+gen_ashift_hi (type, n, reg)
+ int type;
+ int n;
+ rtx reg;
+{
+ /* Negative values here come from the shift_amounts array. */
+ if (n < 0)
+ {
+ if (type == ASHIFT)
+ type = LSHIFTRT;
+ else
+ type = ASHIFT;
+ n = -n;
+ }
+
+ switch (type)
+ {
+ case ASHIFTRT:
+ emit_insn (gen_ashrhi3_k (reg, reg, GEN_INT (n)));
+ break;
+ case LSHIFTRT:
+ if (n == 1)
+ emit_insn (gen_lshrhi3_m (reg, reg, GEN_INT (n)));
+ else
+ emit_insn (gen_lshrhi3_k (reg, reg, GEN_INT (n)));
+ break;
+ case ASHIFT:
+ emit_insn (gen_ashlhi3_k (reg, reg, GEN_INT (n)));
+ break;
+ }
+}
+
/* Output RTL to split a constant shift into its component SH constant
shift instructions. */
-/* ??? For SH3, should reject constant shifts when slower than loading the
- shift count into a register? */
-
int
gen_shifty_op (code, operands)
int code;
@@ -880,6 +946,9 @@ gen_shifty_op (code, operands)
int value = INTVAL (operands[2]);
int max, i;
+ /* Truncate the shift count in case it is out of bounds. */
+ value = value & 0x1f;
+
if (value == 31)
{
if (code == LSHIFTRT)
@@ -900,11 +969,54 @@ gen_shifty_op (code, operands)
}
}
}
+ else if (value == 0)
+ {
+ /* This can happen when not optimizing. We must output something here
+ to prevent the compiler from aborting in final.c after the try_split
+ call. */
+ emit_insn (gen_nop ());
+ return;
+ }
max = shift_insns[value];
for (i = 0; i < max; i++)
gen_ashift (code, shift_amounts[value][i], operands[0]);
}
+
+/* Same as above, but optimized for values where the topmost bits don't
+ matter. */
+
+int
+gen_shifty_hi_op (code, operands)
+ int code;
+ rtx *operands;
+{
+ int value = INTVAL (operands[2]);
+ int max, i;
+ void (*gen_fun)();
+
+ /* This operation is used by and_shl for SImode values with a few
+ high bits known to be cleared. */
+ value &= 31;
+ if (value == 0)
+ {
+ emit_insn (gen_nop ());
+ return;
+ }
+
+ gen_fun = GET_MODE (operands[0]) == HImode ? gen_ashift_hi : gen_ashift;
+ if (code == ASHIFT)
+ {
+ max = ext_shift_insns[value];
+ for (i = 0; i < max; i++)
+ gen_fun (code, ext_shift_amounts[value][i], operands[0]);
+ }
+ else
+ /* When shifting right, emit the shifts in reverse order, so that
+ solitary negative values come first. */
+ for (i = ext_shift_insns[value] - 1; i >= 0; i--)
+ gen_fun (code, ext_shift_amounts[value][i], operands[0]);
+}
/* Output RTL for an arithmetic right shift. */
@@ -919,17 +1031,28 @@ expand_ashiftrt (operands)
tree func_name;
int value;
- if (TARGET_SH3 && GET_CODE (operands[2]) != CONST_INT)
+ if (TARGET_SH3)
{
- rtx count = copy_to_mode_reg (SImode, operands[2]);
- emit_insn (gen_negsi2 (count, count));
- emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
- return 1;
+ if (GET_CODE (operands[2]) != CONST_INT)
+ {
+ rtx count = copy_to_mode_reg (SImode, operands[2]);
+ emit_insn (gen_negsi2 (count, count));
+ emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
+ return 1;
+ }
+ else if (ashiftrt_insns[INTVAL (operands[2]) & 31]
+ > 1 + SH_DYNAMIC_SHIFT_COST)
+ {
+ rtx count
+ = force_reg (SImode, GEN_INT (- (INTVAL (operands[2]) & 31)));
+ emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
+ return 1;
+ }
}
if (GET_CODE (operands[2]) != CONST_INT)
return 0;
- value = INTVAL (operands[2]);
+ value = INTVAL (operands[2]) & 31;
if (value == 31)
{
@@ -969,6 +1092,539 @@ expand_ashiftrt (operands)
emit_move_insn (operands[0], gen_rtx (REG, SImode, 4));
return 1;
}
+
+int sh_dynamicalize_shift_p (count)
+ rtx count;
+{
+ return shift_insns[INTVAL (count)] > 1 + SH_DYNAMIC_SHIFT_COST;
+}
+
+/* Try to find a good way to implement the combiner pattern
+ [(set (match_operand:SI 0 "register_operand" "r")
+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n"))) .
+ LEFT_RTX is operand 2 in the above pattern, and MASK_RTX is operand 3.
+ return 0 for simple right / left or left/right shift combination.
+ return 1 for a combination of shifts with zero_extend.
+ return 2 for a combination of shifts with an AND that needs r0.
+ return 3 for a combination of shifts with an AND that needs an extra
+ scratch register, when the three highmost bits of the AND mask are clear.
+ return 4 for a combination of shifts with an AND that needs an extra
+ scratch register, when any of the three highmost bits of the AND mask
+ is set.
+ If ATTRP is set, store an initial right shift width in ATTRP[0],
+ and the instruction length in ATTRP[1] . These values are not valid
+ when returning 0.
+ When ATTRP is set and returning 1, ATTRP[2] gets set to the index into
+ shift_amounts for the last shift value that is to be used before the
+ sign extend. */
+int
+shl_and_kind (left_rtx, mask_rtx, attrp)
+ rtx left_rtx, mask_rtx;
+ int *attrp;
+{
+ unsigned HOST_WIDE_INT mask, lsb, mask2, lsb2;
+ int left = INTVAL (left_rtx), right;
+ int best = 0;
+ int cost, best_cost = 10000;
+ int best_right = 0, best_len = 0;
+ int i;
+ int can_ext;
+
+ if (left < 0 || left > 31)
+ return 0;
+ if (GET_CODE (mask_rtx) == CONST_INT)
+ mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> left;
+ else
+ mask = (unsigned HOST_WIDE_INT) GET_MODE_MASK (SImode) >> left;
+ /* Can this be expressed as a right shift / left shift pair ? */
+ lsb = ((mask ^ (mask - 1)) >> 1) + 1;
+ right = exact_log2 (lsb);
+ mask2 = ~(mask + lsb - 1);
+ lsb2 = ((mask2 ^ (mask2 - 1)) >> 1) + 1;
+ /* mask has no zeroes but trailing zeroes <==> ! mask2 */
+ if (! mask2)
+ best_cost = shift_insns[right] + shift_insns[right + left];
+ /* mask has no trailing zeroes <==> ! right */
+ else if (! right && mask2 == ~(lsb2 - 1))
+ {
+ int late_right = exact_log2 (lsb2);
+ best_cost = shift_insns[left + late_right] + shift_insns[late_right];
+ }
+ /* Try to use zero extend */
+ if (mask2 == ~(lsb2 - 1))
+ {
+ int width, first;
+
+ for (width = 8; width <= 16; width += 8)
+ {
+ /* Can we zero-extend right away? */
+ if (lsb2 == (HOST_WIDE_INT)1 << width)
+ {
+ cost
+ = 1 + ext_shift_insns[right] + ext_shift_insns[left + right];
+ if (cost < best_cost)
+ {
+ best = 1;
+ best_cost = cost;
+ best_right = right;
+ best_len = cost;
+ if (attrp)
+ attrp[2] = -1;
+ }
+ continue;
+ }
+ /* ??? Could try to put zero extend into initial right shift,
+ or even shift a bit left before the right shift. */
+ /* Determine value of first part of left shift, to get to the
+ zero extend cut-off point. */
+ first = width - exact_log2 (lsb2) + right;
+ if (first >= 0 && right + left - first >= 0)
+ {
+ cost = ext_shift_insns[right] + ext_shift_insns[first] + 1
+ + ext_shift_insns[right + left - first];
+ if (cost < best_cost)
+ {
+ best = 1;
+ best_cost = cost;
+ best_right = right;
+ best_len = cost;
+ if (attrp)
+ attrp[2] = first;
+ }
+ }
+ }
+ }
+ /* Try to use r0 AND pattern */
+ for (i = 0; i <= 2; i++)
+ {
+ if (i > right)
+ break;
+ if (! CONST_OK_FOR_L (mask >> i))
+ continue;
+ cost = (i != 0) + 2 + ext_shift_insns[left + i];
+ if (cost < best_cost)
+ {
+ best = 2;
+ best_cost = cost;
+ best_right = i;
+ best_len = cost - 1;
+ }
+ }
+ /* Try to use a scratch register to hold the AND operand. */
+ can_ext = ((mask << left) & 0xe0000000) == 0;
+ for (i = 0; i <= 2; i++)
+ {
+ if (i > right)
+ break;
+ cost = (i != 0) + (CONST_OK_FOR_I (mask >> i) ? 2 : 3)
+ + (can_ext ? ext_shift_insns : shift_insns)[left + i];
+ if (cost < best_cost)
+ {
+ best = 4 - can_ext;
+ best_cost = cost;
+ best_right = i;
+ best_len = cost - 1 - ! CONST_OK_FOR_I (mask >> i);
+ }
+ }
+
+ if (attrp)
+ {
+ attrp[0] = best_right;
+ attrp[1] = best_len;
+ }
+ return best;
+}
+
+/* This is used in length attributes of the unnamed instructions
+ corresponding to shl_and_kind return values of 1 and 2. */
+int
+shl_and_length (insn)
+ rtx insn;
+{
+ rtx set_src, left_rtx, mask_rtx;
+ int attributes[3];
+
+ set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+ left_rtx = XEXP (XEXP (set_src, 0), 1);
+ mask_rtx = XEXP (set_src, 1);
+ shl_and_kind (left_rtx, mask_rtx, attributes);
+ return attributes[1];
+}
+
+/* This is used in length attribute of the and_shl_scratch instruction. */
+
+int
+shl_and_scr_length (insn)
+ rtx insn;
+{
+ rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+ int len = shift_insns[INTVAL (XEXP (set_src, 1))];
+ rtx op = XEXP (set_src, 0);
+ len += shift_insns[INTVAL (XEXP (op, 1))] + 1;
+ op = XEXP (XEXP (op, 0), 0);
+ return len + shift_insns[INTVAL (XEXP (op, 1))];
+}
+
+/* Generating rtl? */
+extern int rtx_equal_function_value_matters;
+
+/* Generate rtl for instructions for which shl_and_kind advised a particular
+ method of generating them, i.e. returned zero. */
+
+int
+gen_shl_and (dest, left_rtx, mask_rtx, source)
+ rtx dest, left_rtx, mask_rtx, source;
+{
+ int attributes[3];
+ unsigned HOST_WIDE_INT mask;
+ int kind = shl_and_kind (left_rtx, mask_rtx, attributes);
+ int right, total_shift;
+ int (*shift_gen_fun) PROTO((int, rtx*)) = gen_shifty_hi_op;
+
+ right = attributes[0];
+ total_shift = INTVAL (left_rtx) + right;
+ mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> total_shift;
+ switch (kind)
+ {
+ default:
+ return -1;
+ case 1:
+ {
+ int first = attributes[2];
+ rtx operands[3];
+
+ if (first < 0)
+ {
+ emit_insn ((mask << right) == 0xff
+ ? gen_zero_extendqisi2(dest,
+ gen_lowpart (QImode, source))
+ : gen_zero_extendhisi2(dest,
+ gen_lowpart (HImode, source)));
+ source = dest;
+ }
+ if (source != dest)
+ emit_insn (gen_movsi (dest, source));
+ operands[0] = dest;
+ if (right)
+ {
+ operands[2] = GEN_INT (right);
+ gen_shifty_hi_op (LSHIFTRT, operands);
+ }
+ if (first > 0)
+ {
+ operands[2] = GEN_INT (first);
+ gen_shifty_hi_op (ASHIFT, operands);
+ total_shift -= first;
+ mask <<= first;
+ }
+ if (first >= 0)
+ emit_insn (mask == 0xff
+ ? gen_zero_extendqisi2(dest, gen_lowpart (QImode, dest))
+ : gen_zero_extendhisi2(dest, gen_lowpart (HImode, dest)));
+ if (total_shift > 0)
+ {
+ operands[2] = GEN_INT (total_shift);
+ gen_shifty_hi_op (ASHIFT, operands);
+ }
+ break;
+ }
+ case 4:
+ shift_gen_fun = gen_shifty_op;
+ case 2:
+ case 3:
+ /* If the topmost bit that matters is set, set the topmost bits
+ that don't matter. This way, we might be able to get a shorter
+ signed constant. */
+ if (mask & ((HOST_WIDE_INT)1 << 31 - total_shift))
+ mask |= (HOST_WIDE_INT)~0 << (31 - total_shift);
+ /* Don't expand fine-grained when combining, because that will
+ make the pattern fail. */
+ if (rtx_equal_function_value_matters
+ || reload_in_progress || reload_completed)
+ {
+ rtx operands[3];
+
+ if (right)
+ {
+ emit_insn (gen_lshrsi3 (dest, source, GEN_INT (right)));
+ source = dest;
+ }
+ emit_insn (gen_andsi3 (dest, source, GEN_INT (mask)));
+ if (total_shift)
+ {
+ operands[0] = dest;
+ operands[1] = dest;
+ operands[2] = GEN_INT (total_shift);
+ shift_gen_fun (ASHIFT, operands);
+ }
+ break;
+ }
+ else
+ {
+ int neg = 0;
+ if (kind != 4 && total_shift < 16)
+ {
+ neg = -ext_shift_amounts[total_shift][1];
+ if (neg > 0)
+ neg -= ext_shift_amounts[total_shift][2];
+ else
+ neg = 0;
+ }
+ emit_insn (gen_and_shl_scratch (dest, source,
+ GEN_INT (right),
+ GEN_INT (mask),
+ GEN_INT (total_shift + neg),
+ GEN_INT (neg)));
+ emit_insn (gen_movsi (dest, dest));
+ break;
+ }
+ }
+ return 0;
+}
+
+/* Try to find a good way to implement the combiner pattern
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:SI 18))]
+ LEFT_RTX is operand 2 in the above pattern, and SIZE_RTX is operand 3.
+ return 0 for simple left / right shift combination.
+ return 1 for left shift / 8 bit sign extend / left shift.
+ return 2 for left shift / 16 bit sign extend / left shift.
+ return 3 for left shift / 8 bit sign extend / shift / sign extend.
+ return 4 for left shift / 16 bit sign extend / shift / sign extend.
+ return 5 for left shift / 16 bit sign extend / right shift
+ return 6 for < 8 bit sign extend / left shift.
+ return 7 for < 8 bit sign extend / left shift / single right shift.
+ If COSTP is nonzero, assign the calculated cost to *COSTP. */
+
+int
+shl_sext_kind (left_rtx, size_rtx, costp)
+ rtx left_rtx, size_rtx;
+ int *costp;
+{
+ int left, size, insize, ext;
+ int cost, best_cost;
+ int kind;
+
+ left = INTVAL (left_rtx);
+ size = INTVAL (size_rtx);
+ insize = size - left;
+ if (insize <= 0)
+ abort ();
+ /* Default to left / right shift. */
+ kind = 0;
+ best_cost = shift_insns[32 - insize] + ashiftrt_insns[32 - size];
+ if (size <= 16)
+ {
+ /* 16 bit shift / sign extend / 16 bit shift */
+ cost = shift_insns[16 - insize] + 1 + ashiftrt_insns[16 - size];
+ /* If ashiftrt_insns[16 - size] is 8, this choice will be overridden
+ below, by alternative 3 or something even better. */
+ if (cost < best_cost)
+ {
+ kind = 5;
+ best_cost = cost;
+ }
+ }
+ /* Try a plain sign extend between two shifts. */
+ for (ext = 16; ext >= insize; ext -= 8)
+ {
+ if (ext <= size)
+ {
+ cost = ext_shift_insns[ext - insize] + 1 + shift_insns[size - ext];
+ if (cost < best_cost)
+ {
+ kind = ext / 8U;
+ best_cost = cost;
+ }
+ }
+ /* Check if we can do a sloppy shift with a final signed shift
+ restoring the sign. */
+ if (EXT_SHIFT_SIGNED (size - ext))
+ cost = ext_shift_insns[ext - insize] + ext_shift_insns[size - ext] + 1;
+ /* If not, maybe it's still cheaper to do the second shift sloppy,
+ and do a final sign extend? */
+ else if (size <= 16)
+ cost = ext_shift_insns[ext - insize] + 1
+ + ext_shift_insns[size > ext ? size - ext : ext - size] + 1;
+ else
+ continue;
+ if (cost < best_cost)
+ {
+ kind = ext / 8U + 2;
+ best_cost = cost;
+ }
+ }
+ /* Check if we can sign extend in r0 */
+ if (insize < 8)
+ {
+ cost = 3 + shift_insns[left];
+ if (cost < best_cost)
+ {
+ kind = 6;
+ best_cost = cost;
+ }
+ /* Try the same with a final signed shift. */
+ if (left < 31)
+ {
+ cost = 3 + ext_shift_insns[left + 1] + 1;
+ if (cost < best_cost)
+ {
+ kind = 7;
+ best_cost = cost;
+ }
+ }
+ }
+ if (TARGET_SH3)
+ {
+ /* Try to use a dynamic shift. */
+ cost = shift_insns[32 - insize] + 1 + SH_DYNAMIC_SHIFT_COST;
+ if (cost < best_cost)
+ {
+ kind = 0;
+ best_cost = cost;
+ }
+ }
+ if (costp)
+ *costp = cost;
+ return kind;
+}
+
+/* Function to be used in the length attribute of the instructions
+ implementing this pattern. */
+
+int
+shl_sext_length (insn)
+ rtx insn;
+{
+ rtx set_src, left_rtx, size_rtx;
+ int cost;
+
+ set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+ left_rtx = XEXP (XEXP (set_src, 0), 1);
+ size_rtx = XEXP (set_src, 1);
+ shl_sext_kind (left_rtx, size_rtx, &cost);
+ return cost;
+}
+
+/* Generate rtl for this pattern */
+
+int
+gen_shl_sext (dest, left_rtx, size_rtx, source)
+ rtx dest, left_rtx, size_rtx, source;
+{
+ int kind;
+ int left, size, insize, cost;
+ rtx operands[3];
+
+ kind = shl_sext_kind (left_rtx, size_rtx, &cost);
+ left = INTVAL (left_rtx);
+ size = INTVAL (size_rtx);
+ insize = size - left;
+ switch (kind)
+ {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ {
+ int ext = kind & 1 ? 8 : 16;
+ int shift2 = size - ext;
+
+ /* Don't expand fine-grained when combining, because that will
+ make the pattern fail. */
+ if (! rtx_equal_function_value_matters
+ && ! reload_in_progress && ! reload_completed)
+ {
+ emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
+ emit_insn (gen_movsi (dest, source));
+ break;
+ }
+ if (dest != source)
+ emit_insn (gen_movsi (dest, source));
+ operands[0] = dest;
+ if (ext - insize)
+ {
+ operands[2] = GEN_INT (ext - insize);
+ gen_shifty_hi_op (ASHIFT, operands);
+ }
+ emit_insn (kind & 1
+ ? gen_extendqisi2(dest, gen_lowpart (QImode, dest))
+ : gen_extendhisi2(dest, gen_lowpart (HImode, dest)));
+ if (kind <= 2)
+ {
+ if (shift2)
+ {
+ operands[2] = GEN_INT (shift2);
+ gen_shifty_op (ASHIFT, operands);
+ }
+ }
+ else
+ {
+ if (shift2 > 0)
+ {
+ if (EXT_SHIFT_SIGNED (shift2))
+ {
+ operands[2] = GEN_INT (shift2 + 1);
+ gen_shifty_op (ASHIFT, operands);
+ operands[2] = GEN_INT (1);
+ gen_shifty_op (ASHIFTRT, operands);
+ break;
+ }
+ operands[2] = GEN_INT (shift2);
+ gen_shifty_hi_op (ASHIFT, operands);
+ }
+ else if (shift2)
+ {
+ operands[2] = GEN_INT (-shift2);
+ gen_shifty_hi_op (LSHIFTRT, operands);
+ }
+ emit_insn (size <= 8
+ ? gen_extendqisi2 (dest, gen_lowpart (QImode, dest))
+ : gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
+ }
+ break;
+ }
+ case 5:
+ {
+ int i = 16 - size;
+ emit_insn (gen_shl_sext_ext (dest, source, GEN_INT (16 - insize),
+ GEN_INT (16)));
+ /* Don't use gen_ashrsi3 because it generates new pseudos. */
+ while (--i >= 0)
+ gen_ashift (ASHIFTRT, 1, dest);
+ break;
+ }
+ case 6:
+ case 7:
+ /* Don't expand fine-grained when combining, because that will
+ make the pattern fail. */
+ if (! rtx_equal_function_value_matters
+ && ! reload_in_progress && ! reload_completed)
+ {
+ emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
+ emit_insn (gen_movsi (dest, source));
+ break;
+ }
+ emit_insn (gen_andsi3 (dest, source, GEN_INT ((1 << insize) - 1)));
+ emit_insn (gen_xorsi3 (dest, dest, GEN_INT (1 << (insize - 1))));
+ emit_insn (gen_addsi3 (dest, dest, GEN_INT (-1 << (insize - 1))));
+ operands[0] = dest;
+ operands[2] = kind == 7 ? GEN_INT (left + 1) : left_rtx;
+ gen_shifty_op (ASHIFT, operands);
+ if (kind == 7)
+ emit_insn (gen_ashrsi3_k (dest, dest, GEN_INT (1)));
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
/* The SH cannot load a large constant into a register, constants have to
come from a pc relative load. The reference of a pc relative load
@@ -1038,6 +1694,8 @@ typedef struct
static pool_node pool_vector[MAX_POOL_SIZE];
static int pool_size;
+static int max_uid_before_fixup_addr_diff_vecs;
+
/* ??? If we need a constant in HImode which is the truncated value of a
constant we need in SImode, we could combine the two entries thus saving
two bytes. Is this common enough to be worth the effort of implementing
@@ -1121,15 +1779,18 @@ dump_table (scan)
case HImode:
break;
case SImode:
+ case SFmode:
if (need_align)
{
need_align = 0;
scan = emit_label_after (gen_label_rtx (), scan);
scan = emit_insn_after (gen_align_4 (), scan);
}
- scan = emit_label_after (p->label, scan);
+ if (p->label)
+ scan = emit_label_after (p->label, scan);
scan = emit_insn_after (gen_consttable_4 (p->value), scan);
break;
+ case DFmode:
case DImode:
if (need_align)
{
@@ -1137,7 +1798,8 @@ dump_table (scan)
scan = emit_label_after (gen_label_rtx (), scan);
scan = emit_insn_after (gen_align_4 (), scan);
}
- scan = emit_label_after (p->label, scan);
+ if (p->label)
+ scan = emit_label_after (p->label, scan);
scan = emit_insn_after (gen_consttable_8 (p->value), scan);
break;
default:
@@ -1173,83 +1835,183 @@ static int
broken_move (insn)
rtx insn;
{
- if (GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET
- /* We can load any 8 bit value if we don't care what the high
- order bits end up as. */
- && GET_MODE (SET_DEST (PATTERN (insn))) != QImode
- && CONSTANT_P (SET_SRC (PATTERN (insn)))
- && (GET_CODE (SET_SRC (PATTERN (insn))) != CONST_INT
- || ! CONST_OK_FOR_I (INTVAL (SET_SRC (PATTERN (insn))))))
- return 1;
+ if (GET_CODE (insn) == INSN)
+ {
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == PARALLEL)
+ pat = XVECEXP (pat, 0, 0);
+ if (GET_CODE (pat) == SET
+ /* We can load any 8 bit value if we don't care what the high
+ order bits end up as. */
+ && GET_MODE (SET_DEST (pat)) != QImode
+ && CONSTANT_P (SET_SRC (pat))
+ && ! (TARGET_SH3E
+ && GET_CODE (SET_SRC (pat)) == CONST_DOUBLE
+ && (fp_zero_operand (SET_SRC (pat))
+ || fp_one_operand (SET_SRC (pat)))
+ && GET_CODE (SET_DEST (pat)) == REG
+ && REGNO (SET_DEST (pat)) >= FIRST_FP_REG
+ && REGNO (SET_DEST (pat)) <= LAST_FP_REG)
+ && (GET_CODE (SET_SRC (pat)) != CONST_INT
+ || ! CONST_OK_FOR_I (INTVAL (SET_SRC (pat)))))
+ return 1;
+ }
return 0;
}
+int
+cache_align_p (insn)
+ rtx insn;
+{
+ rtx pat;
+
+ if (! insn)
+ return 1;
+
+ if (GET_CODE (insn) != INSN)
+ return 0;
+
+ pat = PATTERN (insn);
+ return (GET_CODE (pat) == UNSPEC_VOLATILE
+ && XINT (pat, 1) == 1
+ && INTVAL (XVECEXP (pat, 0, 0)) == CACHE_LOG);
+}
+
+static int
+mova_p (insn)
+ rtx insn;
+{
+ return (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
+ && XINT (SET_SRC (PATTERN (insn)), 1) == 1);
+}
+
/* Find the last barrier from insn FROM which is close enough to hold the
constant pool. If we can't find one, then create one near the end of
the range. */
-/* ??? It would be good to put constant pool tables between a case jump and
- the jump table. This fails for two reasons. First, there is no
- barrier after the case jump. This is a bug in the casesi pattern.
- Second, inserting the table here may break the mova instruction that
- loads the jump table address, by moving the jump table too far away.
- We fix that problem by never outputting the constant pool between a mova
- and its label. */
-
static rtx
-find_barrier (from)
- rtx from;
+find_barrier (num_mova, mova, from)
+ int num_mova;
+ rtx mova, from;
{
int count_si = 0;
int count_hi = 0;
int found_hi = 0;
int found_si = 0;
- rtx found_barrier = 0;
- rtx found_mova = 0;
+ int leading_mova = num_mova;
+ rtx barrier_before_mova, found_barrier = 0, good_barrier = 0;
+ int si_limit;
+ int hi_limit;
/* For HImode: range is 510, add 4 because pc counts from address of
second instruction after this one, subtract 2 for the jump instruction
- that we may need to emit before the table. This gives 512.
+ that we may need to emit before the table, subtract 2 for the instruction
+ that fills the jump delay slot (in very rare cases, reorg will take an
+ instruction from after the constant pool or will leave the delay slot
+ empty). This gives 510.
For SImode: range is 1020, add 4 because pc counts from address of
second instruction after this one, subtract 2 in case pc is 2 byte
aligned, subtract 2 for the jump instruction that we may need to emit
- before the table. This gives 1020. */
- while (from && count_si < 1020 && count_hi < 512)
+ before the table, subtract 2 for the instruction that fills the jump
+ delay slot. This gives 1018. */
+
+ /* The branch will always be shortened now that the reference address for
+ forward branches is the successor address, thus we need no longer make
+ adjustments to the [sh]i_limit for -O0. */
+
+ si_limit = 1018;
+ hi_limit = 510;
+
+ while (from && count_si < si_limit && count_hi < hi_limit)
{
- int inc = get_attr_length (from);
+ int inc = 0;
+
+ /* The instructions created by fixup_addr_diff_vecs have no valid length
+ info yet. They should be considered to have zero at this point. */
+ if (INSN_UID (from) < max_uid_before_fixup_addr_diff_vecs)
+ inc = get_attr_length (from);
if (GET_CODE (from) == BARRIER)
- found_barrier = from;
+ {
+ found_barrier = from;
+ /* If we are at the end of the function, or in front of an alignment
+ instruction, we need not insert an extra alignment. We prefer
+ this kind of barrier. */
+
+ if (cache_align_p (next_real_insn (found_barrier)))
+ good_barrier = from;
+ }
if (broken_move (from))
{
- rtx src = SET_SRC (PATTERN (from));
-
- if (hi_const (src))
+ rtx pat, src, dst;
+ enum machine_mode mode;
+
+ pat = PATTERN (from);
+ if (GET_CODE (pat) == PARALLEL)
+ pat = XVECEXP (pat, 0, 0);
+ src = SET_SRC (pat);
+ dst = SET_DEST (pat);
+ mode = GET_MODE (dst);
+
+ /* We must explicitly check the mode, because sometimes the
+ front end will generate code to load unsigned constants into
+ HImode targets without properly sign extending them. */
+ if (mode == HImode || (mode == SImode && hi_const (src)))
{
- found_hi = 1;
+ found_hi += 2;
/* We put the short constants before the long constants, so
we must count the length of short constants in the range
for the long constants. */
/* ??? This isn't optimal, but is easy to do. */
- if (found_si)
- count_si += 2;
+ si_limit -= 2;
}
else
- found_si = 1;
+ {
+ if (found_si > count_si)
+ count_si = found_si;
+ found_si += GET_MODE_SIZE (mode);
+ if (num_mova)
+ si_limit -= GET_MODE_SIZE (mode);
+ }
}
if (GET_CODE (from) == INSN
&& GET_CODE (PATTERN (from)) == SET
&& GET_CODE (SET_SRC (PATTERN (from))) == UNSPEC
&& XINT (SET_SRC (PATTERN (from)), 1) == 1)
- found_mova = from;
+ {
+ if (! num_mova++)
+ {
+ leading_mova = 0;
+ mova = from;
+ barrier_before_mova = good_barrier ? good_barrier : found_barrier;
+ }
+ if (found_si > count_si)
+ count_si = found_si;
+ }
else if (GET_CODE (from) == JUMP_INSN
&& (GET_CODE (PATTERN (from)) == ADDR_VEC
|| GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC))
- found_mova = 0;
+ {
+ if (num_mova)
+ num_mova--;
+ if (cache_align_p (NEXT_INSN (next_nonnote_insn (from))))
+ {
+ /* We have just passed the barrier in front front of the
+ ADDR_DIFF_VEC. Since the ADDR_DIFF_VEC is accessed
+ as data, just like our pool constants, this is a good
+ opportunity to accommodate what we have gathered so far.
+ If we waited any longer, we could end up at a barrier in
+ front of code, which gives worse cache usage for separated
+ instruction / data caches. */
+ good_barrier = found_barrier;
+ break;
+ }
+ }
if (found_si)
count_si += inc;
@@ -1258,12 +2020,42 @@ find_barrier (from)
from = NEXT_INSN (from);
}
- /* Insert the constant pool table before the mova instruction, to prevent
- the mova label reference from going out of range. */
- if (found_mova)
- from = found_mova;
+ if (num_mova)
+ if (leading_mova)
+ {
+ /* Try as we might, the leading mova is out of range. Change
+ it into a load (which will become a pcload) and retry. */
+ SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
+ INSN_CODE (mova) = -1;
+ return find_barrier (0, 0, mova);
+ }
+ else
+ {
+ /* Insert the constant pool table before the mova instruction,
+ to prevent the mova label reference from going out of range. */
+ from = mova;
+ good_barrier = found_barrier = barrier_before_mova;
+ }
- if (! found_barrier)
+ if (found_barrier)
+ {
+ /* We have before prepared barriers to come in pairs, with an
+ alignment instruction in-between. We want to use the first
+ barrier, so that the alignment applies to the code.
+ If we are compiling for SH3 or newer, there are some exceptions
+ when the second barrier and the alignment doesn't exist yet, so
+ we have to add it. */
+ if (good_barrier)
+ found_barrier = good_barrier;
+ else if (! TARGET_SMALLCODE)
+ {
+ found_barrier
+ = emit_insn_before (gen_align_log (GEN_INT (CACHE_LOG)),
+ found_barrier);
+ found_barrier = emit_barrier_before (found_barrier);
+ }
+ }
+ else
{
/* We didn't find a barrier in time to dump our stuff,
so we'll make one. */
@@ -1272,7 +2064,7 @@ find_barrier (from)
/* If we exceeded the range, then we must back up over the last
instruction we looked at. Otherwise, we just need to undo the
NEXT_INSN at the end of the loop. */
- if (count_hi > 512 || count_si > 1020)
+ if (count_hi > hi_limit || count_si > si_limit)
from = PREV_INSN (PREV_INSN (from));
else
from = PREV_INSN (from);
@@ -1291,43 +2083,1044 @@ find_barrier (from)
LABEL_NUSES (label) = 1;
found_barrier = emit_barrier_after (from);
emit_label_after (label, found_barrier);
+ if (! TARGET_SMALLCODE)
+ {
+ emit_barrier_after (found_barrier);
+ emit_insn_after (gen_align_log (GEN_INT (CACHE_LOG)), found_barrier);
+ }
}
return found_barrier;
}
+/* If the instruction INSN is implemented by a special function, and we can
+ positively find the register that is used to call the sfunc, and this
+ register is not used anywhere else in this instruction - except as the
+ destination of a set, return this register; else, return 0. */
+rtx
+sfunc_uses_reg (insn)
+ rtx insn;
+{
+ int i;
+ rtx pattern, part, reg_part, reg;
+
+ if (GET_CODE (insn) != INSN)
+ return 0;
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) != PARALLEL || get_attr_type (insn) != TYPE_SFUNC)
+ return 0;
+
+ for (reg_part = 0, i = XVECLEN (pattern, 0) - 1; i >= 1; i--)
+ {
+ part = XVECEXP (pattern, 0, i);
+ if (GET_CODE (part) == USE && GET_MODE (XEXP (part, 0)) == SImode)
+ reg_part = part;
+ }
+ if (! reg_part)
+ return 0;
+ reg = XEXP (reg_part, 0);
+ for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
+ {
+ part = XVECEXP (pattern, 0, i);
+ if (part == reg_part)
+ continue;
+ if (reg_mentioned_p (reg, ((GET_CODE (part) == SET
+ && GET_CODE (SET_DEST (part)) == REG)
+ ? SET_SRC (part) : part)))
+ return 0;
+ }
+ return reg;
+}
+
+/* See if the only way in which INSN uses REG is by calling it, or by
+ setting it while calling it. Set *SET to a SET rtx if the register
+ is set by INSN. */
+
+static int
+noncall_uses_reg (reg, insn, set)
+ rtx reg;
+ rtx insn;
+ rtx *set;
+{
+ rtx pattern, reg2;
+
+ *set = NULL_RTX;
+
+ reg2 = sfunc_uses_reg (insn);
+ if (reg2 && REGNO (reg2) == REGNO (reg))
+ {
+ pattern = single_set (insn);
+ if (pattern
+ && GET_CODE (SET_DEST (pattern)) == REG
+ && REGNO (reg) == REGNO (SET_DEST (pattern)))
+ *set = pattern;
+ return 0;
+ }
+ if (GET_CODE (insn) != CALL_INSN)
+ {
+ /* We don't use rtx_equal_p because we don't care if the mode is
+ different. */
+ pattern = single_set (insn);
+ if (pattern
+ && GET_CODE (SET_DEST (pattern)) == REG
+ && REGNO (reg) == REGNO (SET_DEST (pattern)))
+ {
+ rtx par, part;
+ int i;
+
+ *set = pattern;
+ par = PATTERN (insn);
+ if (GET_CODE (par) == PARALLEL)
+ for (i = XVECLEN (par, 0) - 1; i >= 0; i--)
+ {
+ part = XVECEXP (par, 0, i);
+ if (GET_CODE (part) != SET && reg_mentioned_p (reg, part))
+ return 1;
+ }
+ return reg_mentioned_p (reg, SET_SRC (pattern));
+ }
+
+ return 1;
+ }
+
+ pattern = PATTERN (insn);
+
+ if (GET_CODE (pattern) == PARALLEL)
+ {
+ int i;
+
+ for (i = XVECLEN (pattern, 0) - 1; i >= 1; i--)
+ if (reg_mentioned_p (reg, XVECEXP (pattern, 0, i)))
+ return 1;
+ pattern = XVECEXP (pattern, 0, 0);
+ }
+
+ if (GET_CODE (pattern) == SET)
+ {
+ if (reg_mentioned_p (reg, SET_DEST (pattern)))
+ {
+ /* We don't use rtx_equal_p, because we don't care if the
+ mode is different. */
+ if (GET_CODE (SET_DEST (pattern)) != REG
+ || REGNO (reg) != REGNO (SET_DEST (pattern)))
+ return 1;
+
+ *set = pattern;
+ }
+
+ pattern = SET_SRC (pattern);
+ }
+
+ if (GET_CODE (pattern) != CALL
+ || GET_CODE (XEXP (pattern, 0)) != MEM
+ || ! rtx_equal_p (reg, XEXP (XEXP (pattern, 0), 0)))
+ return 1;
+
+ return 0;
+}
+
+/* Given a X, a pattern of an insn or a part of it, return a mask of used
+ general registers. Bits 0..15 mean that the respective registers
+ are used as inputs in the instruction. Bits 16..31 mean that the
+ registers 0..15, respectively, are used as outputs, or are clobbered.
+ IS_DEST should be set to 16 if X is the destination of a SET, else to 0. */
+int
+regs_used (x, is_dest)
+ rtx x; int is_dest;
+{
+ enum rtx_code code;
+ char *fmt;
+ int i, used = 0;
+
+ if (! x)
+ return used;
+ code = GET_CODE (x);
+ switch (code)
+ {
+ case REG:
+ if (REGNO (x) < 16)
+ return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
+ << (REGNO (x) + is_dest));
+ return 0;
+ case SUBREG:
+ {
+ rtx y = SUBREG_REG (x);
+
+ if (GET_CODE (y) != REG)
+ break;
+ if (REGNO (y) < 16)
+ return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
+ << (REGNO (y) + SUBREG_WORD (x) + is_dest));
+ return 0;
+ }
+ case SET:
+ return regs_used (SET_SRC (x), 0) | regs_used (SET_DEST (x), 16);
+ case RETURN:
+ /* If there was a return value, it must have been indicated with USE. */
+ return 0x00ffff00;
+ case CLOBBER:
+ is_dest = 1;
+ break;
+ case MEM:
+ is_dest = 0;
+ break;
+ case CALL:
+ used |= 0x00ff00f0;
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'E')
+ {
+ register int j;
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ used |= regs_used (XVECEXP (x, i, j), is_dest);
+ }
+ else if (fmt[i] == 'e')
+ used |= regs_used (XEXP (x, i), is_dest);
+ }
+ return used;
+}
+
+/* Create an instruction that prevents redirection of a conditional branch
+ to the destination of the JUMP with address ADDR.
+ If the branch needs to be implemented as an indirect jump, try to find
+ a scratch register for it.
+ If NEED_BLOCK is 0, don't do anything unless we need a scratch register.
+ If any preceding insn that doesn't fit into a delay slot is good enough,
+ pass 1. Pass 2 if a definite blocking insn is needed.
+ -1 is used internally to avoid deep recursion.
+ If a blocking instruction is made or recognized, return it. */
+
+static rtx
+gen_block_redirect (jump, addr, need_block)
+ rtx jump;
+ int addr, need_block;
+{
+ int dead = 0;
+ rtx prev = prev_nonnote_insn (jump);
+ rtx dest;
+
+ /* First, check if we already have an instruction that satisfies our need. */
+ if (prev && GET_CODE (prev) == INSN && ! INSN_DELETED_P (prev))
+ {
+ if (INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)
+ return prev;
+ if (GET_CODE (PATTERN (prev)) == USE
+ || GET_CODE (PATTERN (prev)) == CLOBBER
+ || get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
+ prev = jump;
+ else if ((need_block &= ~1) < 0)
+ return prev;
+ else if (recog_memoized (prev) == CODE_FOR_block_branch_redirect)
+ need_block = 0;
+ }
+ /* We can't use JUMP_LABEL here because it might be undefined
+ when not optimizing. */
+ dest = XEXP (SET_SRC (PATTERN (jump)), 0);
+ /* If the branch is out of range, try to find a scratch register for it. */
+ if (optimize
+ && (insn_addresses[INSN_UID (dest)] - addr + 4092U > 4092 + 4098))
+ {
+ rtx scan;
+ /* Don't look for the stack pointer as a scratch register,
+ it would cause trouble if an interrupt occurred. */
+ unsigned try = 0x7fff, used;
+ int jump_left = flag_expensive_optimizations + 1;
+
+ /* It is likely that the most recent eligible instruction is wanted for
+ the delay slot. Therefore, find out which registers it uses, and
+ try to avoid using them. */
+
+ for (scan = jump; scan = PREV_INSN (scan); )
+ {
+ enum rtx_code code;
+
+ if (INSN_DELETED_P (scan))
+ continue;
+ code = GET_CODE (scan);
+ if (code == CODE_LABEL || code == JUMP_INSN)
+ break;
+ if (code == INSN
+ && GET_CODE (PATTERN (scan)) != USE
+ && GET_CODE (PATTERN (scan)) != CLOBBER
+ && get_attr_in_delay_slot (scan) == IN_DELAY_SLOT_YES)
+ {
+ try &= ~regs_used (PATTERN (scan), 0);
+ break;
+ }
+ }
+ for (used = dead = 0, scan = JUMP_LABEL (jump); scan = NEXT_INSN (scan); )
+ {
+ enum rtx_code code;
+
+ if (INSN_DELETED_P (scan))
+ continue;
+ code = GET_CODE (scan);
+ if (GET_RTX_CLASS (code) == 'i')
+ {
+ used |= regs_used (PATTERN (scan), 0);
+ if (code == CALL_INSN)
+ used |= regs_used (CALL_INSN_FUNCTION_USAGE (scan), 0);
+ dead |= (used >> 16) & ~used;
+ if (dead & try)
+ {
+ dead &= try;
+ break;
+ }
+ if (code == JUMP_INSN)
+ if (jump_left-- && simplejump_p (scan))
+ scan = JUMP_LABEL (scan);
+ else
+ break;
+ }
+ }
+ /* Mask out the stack pointer again, in case it was
+ the only 'free' register we have found. */
+ dead &= 0x7fff;
+ }
+ /* If the immediate destination is still in range, check for possible
+ threading with a jump beyond the delay slot insn.
+ Don't check if we are called recursively; the jump has been or will be
+ checked in a different invocation then. */
+
+ else if (optimize && need_block >= 0)
+ {
+ rtx next = next_active_insn (next_active_insn (dest));
+ if (next && GET_CODE (next) == JUMP_INSN
+ && GET_CODE (PATTERN (next)) == SET
+ && recog_memoized (next) == CODE_FOR_jump)
+ {
+ dest = JUMP_LABEL (next);
+ if (dest
+ && insn_addresses[INSN_UID (dest)] - addr + 4092U > 4092 + 4098)
+ gen_block_redirect (next, insn_addresses[INSN_UID (next)], -1);
+ }
+ }
+
+ if (dead)
+ {
+ rtx reg = gen_rtx (REG, SImode, exact_log2 (dead & -dead));
+
+ /* It would be nice if we could convert the jump into an indirect
+ jump / far branch right now, and thus exposing all constituent
+ instructions to further optimization. However, reorg uses
+ simplejump_p to determine if there is an unconditional jump where
+ it should try to schedule instructions from the target of the
+ branch; simplejump_p fails for indirect jumps even if they have
+ a JUMP_LABEL. */
+ rtx insn = emit_insn_before (gen_indirect_jump_scratch
+ (reg, GEN_INT (INSN_UID (JUMP_LABEL (jump))))
+ , jump);
+ INSN_CODE (insn) = CODE_FOR_indirect_jump_scratch;
+ return insn;
+ }
+ else if (need_block)
+ /* We can't use JUMP_LABEL here because it might be undefined
+ when not optimizing. */
+ return emit_insn_before (gen_block_branch_redirect
+ (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))))
+ , jump);
+ return prev;
+}
+
+#define CONDJUMP_MIN -252
+#define CONDJUMP_MAX 262
+struct far_branch
+{
+ /* A label (to be placed) in front of the jump
+ that jumps to our ultimate destination. */
+ rtx near_label;
+ /* Where we are going to insert it if we cannot move the jump any farther,
+ or the jump itself if we have picked up an existing jump. */
+ rtx insert_place;
+ /* The ultimate destination. */
+ rtx far_label;
+ struct far_branch *prev;
+ /* If the branch has already been created, its address;
+ else the address of its first prospective user. */
+ int address;
+};
+
+enum mdep_reorg_phase_e mdep_reorg_phase;
+void
+gen_far_branch (bp)
+ struct far_branch *bp;
+{
+ rtx insn = bp->insert_place;
+ rtx jump;
+ rtx label = gen_label_rtx ();
+
+ emit_label_after (label, insn);
+ if (bp->far_label)
+ {
+ jump = emit_jump_insn_after (gen_jump (bp->far_label), insn);
+ LABEL_NUSES (bp->far_label)++;
+ }
+ else
+ jump = emit_jump_insn_after (gen_return (), insn);
+ emit_label_after (bp->near_label, insn);
+ JUMP_LABEL (jump) = bp->far_label;
+ if (! invert_jump (insn, label))
+ abort ();
+ /* Prevent reorg from undoing our splits. */
+ gen_block_redirect (jump, bp->address += 2, 2);
+}
+
+static void
+fixup_aligns ()
+{
+ rtx insn = get_last_insn ();
+ rtx align_tab[MAX_BITS_PER_WORD];
+ int i;
+
+ for (i = CACHE_LOG; i >= 0; i--)
+ align_tab[i] = insn;
+ bzero ((char *) uid_align, uid_align_max * sizeof *uid_align);
+ for (; insn; insn = PREV_INSN (insn))
+ {
+ int uid = INSN_UID (insn);
+ if (uid < uid_align_max)
+ uid_align[uid] = align_tab[1];
+ if (GET_CODE (insn) == INSN)
+ {
+ rtx pat = PATTERN (insn);
+ if (GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == 1)
+ {
+ /* Found an alignment instruction. */
+ int log = INTVAL (XVECEXP (pat, 0, 0));
+ uid_align[uid] = align_tab[log];
+ for (i = log - 1; i >= 0; i--)
+ align_tab[i] = insn;
+ }
+ }
+ else if (GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) == SET)
+ {
+ rtx dest = SET_SRC (PATTERN (insn));
+ if (GET_CODE (dest) == IF_THEN_ELSE)
+ dest = XEXP (dest, 1);
+ if (GET_CODE (dest) == LABEL_REF)
+ {
+ dest = XEXP (dest, 0);
+ if (! uid_align[INSN_UID (dest)])
+ /* Mark backward branch. */
+ uid_align[uid] = 0;
+ }
+ }
+ }
+}
+
+/* Fix up ADDR_DIFF_VECs. */
+void
+fixup_addr_diff_vecs (first)
+ rtx first;
+{
+ rtx insn;
+ int max_address;
+ int need_fixup_aligns = 0;
+
+ if (optimize)
+ max_address = insn_addresses[INSN_UID (get_last_insn ())] + 2;
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ rtx vec_lab, rel_lab, pat, min_lab, max_lab, adj;
+ int len, i, min, max, size;
+
+ if (GET_CODE (insn) != JUMP_INSN
+ || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
+ continue;
+ pat = PATTERN (insn);
+ rel_lab = vec_lab = XEXP (XEXP (pat, 0), 0);
+ if (TARGET_SH2)
+ {
+ rtx prev, prevpat, x;
+
+ /* Search the matching casesi_jump_2. */
+ for (prev = vec_lab; ; prev = PREV_INSN (prev))
+ {
+ if (GET_CODE (prev) != JUMP_INSN)
+ continue;
+ prevpat = PATTERN (prev);
+ if (GET_CODE (prevpat) != PARALLEL || XVECLEN (prevpat, 0) != 2)
+ continue;
+ x = XVECEXP (prevpat, 0, 1);
+ if (GET_CODE (x) != USE)
+ continue;
+ x = XEXP (x, 0);
+ if (GET_CODE (x) == LABEL_REF && XEXP (x, 0) == vec_lab)
+ break;
+ }
+ /* Fix up the ADDR_DIF_VEC to be relative
+ to the reference address of the braf. */
+ XEXP (XEXP (pat, 0), 0)
+ = rel_lab = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
+ }
+ if (! optimize)
+ continue;
+ len = XVECLEN (pat, 1);
+ if (len <= 0)
+ abort ();
+ for (min = max_address, max = 0, i = len - 1; i >= 0; i--)
+ {
+ rtx lab = XEXP (XVECEXP (pat, 1, i), 0);
+ int addr = insn_addresses[INSN_UID (lab)];
+ if (addr < min)
+ {
+ min = addr;
+ min_lab = lab;
+ }
+ if (addr > max)
+ {
+ max = addr;
+ max_lab = lab;
+ }
+ }
+ adj
+ = emit_insn_before (gen_addr_diff_vec_adjust (min_lab, max_lab, rel_lab,
+ GEN_INT (len)), vec_lab);
+ size = (XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
+ - addr_diff_vec_adjust (adj, 0));
+ /* If this is a very small table, we want to remove the alignment after
+ the table. */
+ if (! TARGET_SMALLCODE && size <= 1 << (CACHE_LOG - 2))
+ {
+ rtx align = NEXT_INSN (next_nonnote_insn (insn));
+ PUT_CODE (align, NOTE);
+ NOTE_LINE_NUMBER (align) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (align) = 0;
+ need_fixup_aligns = 1;
+ }
+ }
+ if (need_fixup_aligns)
+ fixup_aligns ();
+}
+
+/* Say how much the ADDR_DIFF_VEC following INSN can be shortened.
+ If FIRST_PASS is nonzero, all addresses and length of following
+ insns are still uninitialized. */
+int
+addr_diff_vec_adjust (insn, first_pass)
+ rtx insn;
+ int first_pass;
+{
+ rtx pat = PATTERN (insn);
+ rtx min_lab = XEXP (XVECEXP (pat, 0, 0), 0);
+ rtx max_lab = XEXP (XVECEXP (pat, 0, 1), 0);
+ rtx rel_lab = XEXP (XVECEXP (pat, 0, 2), 0);
+ int len = INTVAL (XVECEXP (pat, 0, 3));
+ int addr, min_addr, max_addr, saving, prev_saving = 0, offset;
+ rtx align_insn = uid_align[INSN_UID (rel_lab)];
+ int standard_size = TARGET_BIGTABLE ? 4 : 2;
+ int last_size = GET_MODE_SIZE ( GET_MODE(pat));
+ int align_fuzz = 0;
+
+ if (! insn_addresses)
+ return 0;
+ if (first_pass)
+ /* If optimizing, we may start off with an optimistic guess. */
+ return optimize ? len & ~1 : 0;
+ addr = insn_addresses[INSN_UID (rel_lab)];
+ min_addr = insn_addresses[INSN_UID (min_lab)];
+ max_addr = insn_addresses[INSN_UID (max_lab)];
+ if (! last_size)
+ last_size = standard_size;
+ if (TARGET_SH2)
+ prev_saving = ((standard_size - last_size) * len) & ~1;
+
+ /* The savings are linear to the vector length. However, if we have an
+ odd saving, we need one byte again to reinstate 16 bit alignment. */
+ saving = ((standard_size - 1) * len) & ~1;
+ offset = prev_saving - saving;
+
+ if ((insn_addresses[INSN_UID (align_insn)] < max_addr
+ || (insn_addresses[INSN_UID (align_insn)] == max_addr
+ && next_real_insn (max_lab) != align_insn))
+ && GET_CODE (align_insn) == INSN)
+ {
+ int align = 1 << INTVAL (XVECEXP (PATTERN (align_insn), 0, 0));
+ int align_addr = insn_addresses[INSN_UID (align_insn)];
+ if (align_addr > insn_addresses[INSN_UID (insn)])
+ {
+ int old_offset = offset;
+ offset = (align_addr - 1 & align - 1) + offset & -align;
+ align_addr += old_offset;
+ }
+ align_fuzz += (align_addr - 1) & (align - 2);
+ align_insn = uid_align[INSN_UID (align_insn)];
+ if (insn_addresses[INSN_UID (align_insn)] <= max_addr
+ && GET_CODE (align_insn) == INSN)
+ {
+ int align2 = 1 << INTVAL (XVECEXP (PATTERN (align_insn), 0, 0));
+ align_addr = insn_addresses[INSN_UID (align_insn)];
+ if (align_addr > insn_addresses[INSN_UID (insn)])
+ {
+ int old_offset = offset;
+ offset = (align_addr - 1 & align2 - 1) + offset & -align2;
+ align_addr += old_offset;
+ }
+ align_fuzz += (align_addr - 1) & (align2 - align);
+ }
+ }
+
+ if (min_addr >= addr
+ && max_addr + offset - addr + align_fuzz <= 255)
+ {
+ PUT_MODE (pat, QImode);
+ return saving;
+ }
+ saving = 2 * len;
+/* Since alignment might play a role in min_addr if it is smaller than addr,
+ we may not use it without exact alignment compensation; a 'worst case'
+ estimate is not good enough, because it won't prevent infinite oscillation
+ of shorten_branches.
+ ??? We should fix that eventually, but the code to deal with alignments
+ should go in a new function. */
+#if 0
+ if (TARGET_BIGTABLE && min_addr - ((1 << CACHE_LOG) - 2) - addr >= -32768
+#else
+ if (TARGET_BIGTABLE && (min_addr >= addr || addr <= 32768)
+#endif
+ && max_addr - addr <= 32767 + saving - prev_saving)
+ {
+ PUT_MODE (pat, HImode);
+ return saving;
+ }
+ PUT_MODE (pat, TARGET_BIGTABLE ? SImode : HImode);
+ return 0;
+}
+
/* Exported to toplev.c.
- Scan the function looking for move instructions which have to be changed to
- pc-relative loads and insert the literal tables. */
+ Do a final pass over the function, just before delayed branch
+ scheduling. */
void
machine_dependent_reorg (first)
rtx first;
{
- rtx insn;
+ rtx insn, mova;
+ int num_mova;
+ rtx r0_rtx = gen_rtx (REG, Pmode, 0);
+ rtx r0_inc_rtx = gen_rtx (POST_INC, Pmode, r0_rtx);
+
+ /* If relaxing, generate pseudo-ops to associate function calls with
+ the symbols they call. It does no harm to not generate these
+ pseudo-ops. However, when we can generate them, it enables to
+ linker to potentially relax the jsr to a bsr, and eliminate the
+ register load and, possibly, the constant pool entry. */
+
+ mdep_reorg_phase = SH_INSERT_USES_LABELS;
+ if (TARGET_RELAX)
+ {
+ /* Remove all REG_LABEL notes. We want to use them for our own
+ purposes. This works because none of the remaining passes
+ need to look at them.
- for (insn = first; insn; insn = NEXT_INSN (insn))
+ ??? But it may break in the future. We should use a machine
+ dependent REG_NOTE, or some other approach entirely. */
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ rtx note;
+
+ while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != 0)
+ remove_note (insn, note);
+ }
+ }
+
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ rtx pattern, reg, link, set, scan, dies, label;
+ int rescan = 0, foundinsn = 0;
+
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ pattern = PATTERN (insn);
+
+ if (GET_CODE (pattern) == PARALLEL)
+ pattern = XVECEXP (pattern, 0, 0);
+ if (GET_CODE (pattern) == SET)
+ pattern = SET_SRC (pattern);
+
+ if (GET_CODE (pattern) != CALL
+ || GET_CODE (XEXP (pattern, 0)) != MEM)
+ continue;
+
+ reg = XEXP (XEXP (pattern, 0), 0);
+ }
+ else
+ {
+ reg = sfunc_uses_reg (insn);
+ if (! reg)
+ continue;
+ }
+
+ if (GET_CODE (reg) != REG)
+ continue;
+
+ /* This is a function call via REG. If the only uses of REG
+ between the time that it is set and the time that it dies
+ are in function calls, then we can associate all the
+ function calls with the setting of REG. */
+
+ for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
+ {
+ if (REG_NOTE_KIND (link) != 0)
+ continue;
+ set = single_set (XEXP (link, 0));
+ if (set && rtx_equal_p (reg, SET_DEST (set)))
+ {
+ link = XEXP (link, 0);
+ break;
+ }
+ }
+
+ if (! link)
+ {
+ /* ??? Sometimes global register allocation will have
+ deleted the insn pointed to by LOG_LINKS. Try
+ scanning backward to find where the register is set. */
+ for (scan = PREV_INSN (insn);
+ scan && GET_CODE (scan) != CODE_LABEL;
+ scan = PREV_INSN (scan))
+ {
+ if (GET_RTX_CLASS (GET_CODE (scan)) != 'i')
+ continue;
+
+ if (! reg_mentioned_p (reg, scan))
+ continue;
+
+ if (noncall_uses_reg (reg, scan, &set))
+ break;
+
+ if (set)
+ {
+ link = scan;
+ break;
+ }
+ }
+ }
+
+ if (! link)
+ continue;
+
+ /* The register is set at LINK. */
+
+ /* We can only optimize the function call if the register is
+ being set to a symbol. In theory, we could sometimes
+ optimize calls to a constant location, but the assembler
+ and linker do not support that at present. */
+ if (GET_CODE (SET_SRC (set)) != SYMBOL_REF
+ && GET_CODE (SET_SRC (set)) != LABEL_REF)
+ continue;
+
+ /* Scan forward from LINK to the place where REG dies, and
+ make sure that the only insns which use REG are
+ themselves function calls. */
+
+ /* ??? This doesn't work for call targets that were allocated
+ by reload, since there may not be a REG_DEAD note for the
+ register. */
+
+ dies = NULL_RTX;
+ for (scan = NEXT_INSN (link); scan; scan = NEXT_INSN (scan))
+ {
+ rtx scanset;
+
+ /* Don't try to trace forward past a CODE_LABEL if we haven't
+ seen INSN yet. Ordinarily, we will only find the setting insn
+ in LOG_LINKS if it is in the same basic block. However,
+ cross-jumping can insert code labels in between the load and
+ the call, and can result in situations where a single call
+ insn may have two targets depending on where we came from. */
+
+ if (GET_CODE (scan) == CODE_LABEL && ! foundinsn)
+ break;
+
+ if (GET_RTX_CLASS (GET_CODE (scan)) != 'i')
+ continue;
+
+ /* Don't try to trace forward past a JUMP. To optimize
+ safely, we would have to check that all the
+ instructions at the jump destination did not use REG. */
+
+ if (GET_CODE (scan) == JUMP_INSN)
+ break;
+
+ if (! reg_mentioned_p (reg, scan))
+ continue;
+
+ if (noncall_uses_reg (reg, scan, &scanset))
+ break;
+
+ if (scan == insn)
+ foundinsn = 1;
+
+ if (scan != insn
+ && (GET_CODE (scan) == CALL_INSN || sfunc_uses_reg (scan)))
+ {
+ /* There is a function call to this register other
+ than the one we are checking. If we optimize
+ this call, we need to rescan again below. */
+ rescan = 1;
+ }
+
+ /* ??? We shouldn't have to worry about SCANSET here.
+ We should just be able to check for a REG_DEAD note
+ on a function call. However, the REG_DEAD notes are
+ apparently not dependable around libcalls; c-torture
+ execute/920501-2 is a test case. If SCANSET is set,
+ then this insn sets the register, so it must have
+ died earlier. Unfortunately, this will only handle
+ the cases in which the register is, in fact, set in a
+ later insn. */
+
+ /* ??? We shouldn't have to use FOUNDINSN here.
+ However, the LOG_LINKS fields are apparently not
+ entirely reliable around libcalls;
+ newlib/libm/math/e_pow.c is a test case. Sometimes
+ an insn will appear in LOG_LINKS even though it is
+ not the most recent insn which sets the register. */
+
+ if (foundinsn
+ && (scanset
+ || find_reg_note (scan, REG_DEAD, reg)))
+ {
+ dies = scan;
+ break;
+ }
+ }
+
+ if (! dies)
+ {
+ /* Either there was a branch, or some insn used REG
+ other than as a function call address. */
+ continue;
+ }
+
+ /* Create a code label, and put it in a REG_LABEL note on
+ the insn which sets the register, and on each call insn
+ which uses the register. In final_prescan_insn we look
+ for the REG_LABEL notes, and output the appropriate label
+ or pseudo-op. */
+
+ label = gen_label_rtx ();
+ REG_NOTES (link) = gen_rtx (EXPR_LIST, REG_LABEL, label,
+ REG_NOTES (link));
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL, label,
+ REG_NOTES (insn));
+ if (rescan)
+ {
+ scan = link;
+ do
+ {
+ rtx reg2;
+
+ scan = NEXT_INSN (scan);
+ if (scan != insn
+ && ((GET_CODE (scan) == CALL_INSN
+ && reg_mentioned_p (reg, scan))
+ || ((reg2 = sfunc_uses_reg (scan))
+ && REGNO (reg2) == REGNO (reg))))
+ REG_NOTES (scan) = gen_rtx (EXPR_LIST, REG_LABEL,
+ label, REG_NOTES (scan));
+ }
+ while (scan != dies);
+ }
+ }
+ }
+
+ /* The following processing passes need length information.
+ addr_diff_vec_adjust needs to know if insn_addresses is valid. */
+ insn_addresses = 0;
+
+ /* If not optimizing for space, we want extra alignment for code after
+ a barrier, so that it starts on a word / cache line boundary.
+ We used to emit the alignment for the barrier itself and associate the
+ instruction length with the following instruction, but that had two
+ problems:
+ i) A code label that follows directly after a barrier gets too low an
+ address. When there is a forward branch to it, the incorrect distance
+ calculation can lead to out of range branches. That happened with
+ compile/920625-2 -O -fomit-frame-pointer in copyQueryResult.
+ ii) barriers before constant tables get the extra alignment too.
+ That is just a waste of space.
+
+ So what we do now is to insert align_* instructions after the
+ barriers. By doing that before literal tables are generated, we
+ don't have to care about these. */
+ /* We also want alignment in front of ADDR_DIFF_VECs; this is done already
+ by ASM_OUTPUT_CASE_LABEL, but when optimizing, we have to make it
+ explicit in the RTL in order to correctly shorten branches. */
+
+ if (optimize)
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ rtx addr_diff_vec;
+
+ if (GET_CODE (insn) == BARRIER
+ && (addr_diff_vec = next_real_insn (insn)))
+ if (GET_CODE (PATTERN (addr_diff_vec)) == ADDR_DIFF_VEC)
+ emit_insn_before (gen_align_4 (),
+ XEXP (XEXP (PATTERN (addr_diff_vec), 0), 0));
+ else if (TARGET_SMALLCODE)
+ continue;
+ else if (TARGET_SH3)
+ {
+ /* We align for an entire cache line. If there is a immediately
+ preceding branch to the insn beyond the barrier, it does not
+ make sense to insert the align, because we are more likely
+ to discard useful information from the current cache line
+ when doing the align than to fetch unneeded insns when not. */
+ rtx prev = prev_real_insn (prev_real_insn (insn));
+ int slot, credit;
+
+ for (slot = 2, credit = 1 << (CACHE_LOG - 2) + 2;
+ credit >= 0 && prev && GET_CODE (prev) == INSN;
+ prev = prev_real_insn (prev))
+ {
+ if (GET_CODE (PATTERN (prev)) == USE
+ || GET_CODE (PATTERN (prev)) == CLOBBER)
+ continue;
+ if (slot &&
+ get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
+ slot = 0;
+ credit -= get_attr_length (prev);
+ }
+ if (! prev || GET_CODE (prev) != JUMP_INSN
+ || (next_real_insn (JUMP_LABEL (prev))
+ != next_real_insn (insn))
+ || (credit - slot
+ < (GET_CODE (SET_SRC (PATTERN (prev))) == PC ? 2 : 0)))
+ {
+ insn = emit_insn_after (gen_align_log (GEN_INT (CACHE_LOG)),
+ insn);
+ insn = emit_barrier_after (insn);
+ }
+ }
+ else
+ {
+ insn = emit_insn_after (gen_align_4 (), insn);
+ insn = emit_barrier_after (insn);
+ }
+ else if (TARGET_SMALLCODE)
+ continue;
+ else if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+ {
+ rtx next = next_nonnote_insn (insn);
+ if (next && GET_CODE (next) == CODE_LABEL)
+ emit_insn_after (gen_align_4 (), insn);
+ }
+ }
+
+ /* If TARGET_IEEE, we might have to split some branches before fixup_align.
+ If optimizing, the double call to shorten_branches will split insns twice,
+ unless we split now all that is to split and delete the original insn. */
+ if (TARGET_IEEE || optimize)
+ for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' && ! INSN_DELETED_P (insn))
+ {
+ rtx old = insn;
+ insn = try_split (PATTERN (insn), insn, 1);
+ if (INSN_DELETED_P (old))
+ {
+ PUT_CODE (old, NOTE);
+ NOTE_LINE_NUMBER (old) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (old) = 0;
+ }
+ }
+
+ max_uid_before_fixup_addr_diff_vecs = get_max_uid ();
+
+ if (optimize)
+ {
+ uid_align_max = get_max_uid ();
+ uid_align = (rtx *) alloca (uid_align_max * sizeof *uid_align);
+ fixup_aligns ();
+ mdep_reorg_phase = SH_SHORTEN_BRANCHES0;
+ shorten_branches (first);
+ }
+ fixup_addr_diff_vecs (first);
+ /* Scan the function looking for move instructions which have to be
+ changed to pc-relative loads and insert the literal tables. */
+
+ mdep_reorg_phase = SH_FIXUP_PCLOAD;
+ for (insn = first, num_mova = 0; insn; insn = NEXT_INSN (insn))
{
+ if (mova_p (insn))
+ {
+ if (! num_mova++)
+ mova = insn;
+ }
+ else if (GET_CODE (insn) == JUMP_INSN
+ && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
+ && num_mova)
+ {
+ rtx scan;
+ int total;
+
+ num_mova--;
+
+ /* Some code might have been inserted between the mova and
+ its ADDR_DIFF_VEC. Check if the mova is still in range. */
+ for (scan = mova, total = 0; scan != insn; scan = NEXT_INSN (scan))
+ if (INSN_UID (scan) < max_uid_before_fixup_addr_diff_vecs)
+ total += get_attr_length (scan);
+
+ /* range of mova is 1020, add 4 because pc counts from address of
+ second instruction after this one, subtract 2 in case pc is 2
+ byte aligned. Possible alignment needed for the ADDR_DIFF_VEC
+ cancels out with alignment effects of the mova itself. */
+ if (total > 1022)
+ {
+ /* Change the mova into a load, and restart scanning
+ there. broken_move will then return true for mova. */
+ SET_SRC (PATTERN (mova))
+ = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
+ INSN_CODE (mova) = -1;
+ insn = mova;
+ }
+ }
if (broken_move (insn))
{
rtx scan;
/* Scan ahead looking for a barrier to stick the constant table
behind. */
- rtx barrier = find_barrier (insn);
+ rtx barrier = find_barrier (num_mova, mova, insn);
+ rtx last_float_move, last_float = 0, *last_float_addr;
+ if (num_mova && ! mova_p (mova))
+ {
+ /* find_barrier had to change the first mova into a
+ pcload; thus, we have to start with this new pcload. */
+ insn = mova;
+ num_mova = 0;
+ }
/* Now find all the moves between the points and modify them. */
for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
{
+ if (GET_CODE (scan) == CODE_LABEL)
+ last_float = 0;
if (broken_move (scan))
{
- rtx pat = PATTERN (scan);
- rtx src = SET_SRC (pat);
- rtx dst = SET_DEST (pat);
- enum machine_mode mode = GET_MODE (dst);
+ rtx *patp = &PATTERN (scan), pat = *patp;
+ rtx src, dst;
rtx lab;
rtx newinsn;
rtx newsrc;
+ enum machine_mode mode;
+
+ if (GET_CODE (pat) == PARALLEL)
+ patp = &XVECEXP (pat, 0, 0), pat = *patp;
+ src = SET_SRC (pat);
+ dst = SET_DEST (pat);
+ mode = GET_MODE (dst);
if (mode == SImode && hi_const (src))
{
@@ -1342,24 +3135,313 @@ machine_dependent_reorg (first)
dst = gen_rtx (REG, HImode, REGNO (dst) + offset);
}
- lab = add_constant (src, mode);
- newsrc = gen_rtx (MEM, mode,
- gen_rtx (LABEL_REF, VOIDmode, lab));
+ if (GET_CODE (dst) == REG
+ && ((REGNO (dst) >= FIRST_FP_REG
+ && REGNO (dst) <= LAST_FP_REG)
+ || REGNO (dst) == FPUL_REG))
+ {
+ if (last_float
+ && reg_set_between_p (r0_rtx, last_float_move, scan))
+ last_float = 0;
+ lab = add_constant (src, mode, last_float);
+ if (lab)
+ emit_insn_before (gen_mova (lab), scan);
+ else
+ *last_float_addr = r0_inc_rtx;
+ last_float_move = scan;
+ last_float = src;
+ newsrc = gen_rtx (MEM, mode,
+ (REGNO (dst) == FPUL_REG
+ ? r0_inc_rtx
+ : r0_rtx));
+ last_float_addr = &XEXP (newsrc, 0);
+ }
+ else
+ {
+ lab = add_constant (src, mode, 0);
+ newsrc = gen_rtx (MEM, mode,
+ gen_rtx (LABEL_REF, VOIDmode, lab));
+ }
RTX_UNCHANGING_P (newsrc) = 1;
- newinsn = emit_insn_after (gen_rtx (SET, VOIDmode,
- dst, newsrc), scan);
-
- delete_insn (scan);
- scan = newinsn;
+ *patp = gen_rtx (SET, VOIDmode, dst, newsrc);
+ INSN_CODE (scan) = -1;
}
}
dump_table (barrier);
+ insn = barrier;
+ }
+ }
+
+ mdep_reorg_phase = SH_SHORTEN_BRANCHES1;
+ insn_addresses = 0;
+ split_branches (first);
+
+ /* The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
+ also has an effect on the register that holds the address of the sfunc.
+ Insert an extra dummy insn in front of each sfunc that pretends to
+ use this register. */
+ if (flag_delayed_branch)
+ {
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ rtx reg = sfunc_uses_reg (insn);
+
+ if (! reg)
+ continue;
+ emit_insn_before (gen_use_sfunc_addr (reg), insn);
}
}
+ mdep_reorg_phase = SH_AFTER_MDEP_REORG;
+}
+
+int
+get_dest_uid (label, max_uid)
+ rtx label;
+ int max_uid;
+{
+ rtx dest = next_real_insn (label);
+ int dest_uid;
+ if (! dest)
+ /* This can happen for an undefined label. */
+ return 0;
+ dest_uid = INSN_UID (dest);
+ /* If this is a newly created branch redirection blocking instruction,
+ we cannot index the branch_uid or insn_addresses arrays with its
+ uid. But then, we won't need to, because the actual destination is
+ the following branch. */
+ while (dest_uid >= max_uid)
+ {
+ dest = NEXT_INSN (dest);
+ dest_uid = INSN_UID (dest);
+ }
+ if (GET_CODE (dest) == JUMP_INSN && GET_CODE (PATTERN (dest)) == RETURN)
+ return 0;
+ return dest_uid;
+}
+
+/* Split condbranches that are out of range. Also add clobbers for
+ scratch registers that are needed in far jumps.
+ We do this before delay slot scheduling, so that it can take our
+ newly created instructions into account. It also allows us to
+ find branches with common targets more easily. */
+
+static void
+split_branches (first)
+ rtx first;
+{
+ rtx insn;
+ struct far_branch **uid_branch, *far_branch_list = 0;
+ int max_uid = get_max_uid ();
+
+ /* Find out which branches are out of range. */
+ uid_align_max = get_max_uid ();
+ uid_align = (rtx *) alloca (uid_align_max * sizeof *uid_align);
+ fixup_aligns ();
+ shorten_branches (first);
+
+ uid_branch = (struct far_branch **) alloca (max_uid * sizeof *uid_branch);
+ bzero ((char *) uid_branch, max_uid * sizeof *uid_branch);
+
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ continue;
+ else if (INSN_DELETED_P (insn))
+ {
+ /* Shorten_branches would split this instruction again,
+ so transform it into a note. */
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
+ else if (GET_CODE (insn) == JUMP_INSN
+ /* Don't mess with ADDR_DIFF_VEC */
+ && (GET_CODE (PATTERN (insn)) == SET
+ || GET_CODE (PATTERN (insn)) == RETURN))
+ {
+ enum attr_type type = get_attr_type (insn);
+ if (type == TYPE_CBRANCH)
+ {
+ rtx next, beyond;
+
+ if (get_attr_length (insn) > 4)
+ {
+ rtx src = SET_SRC (PATTERN (insn));
+ rtx cond = XEXP (src, 0);
+ rtx olabel = XEXP (XEXP (src, 1), 0);
+ rtx jump;
+ int addr = insn_addresses[INSN_UID (insn)];
+ rtx label = 0;
+ int dest_uid = get_dest_uid (olabel, max_uid);
+ struct far_branch *bp = uid_branch[dest_uid];
+
+ /* redirect_jump needs a valid JUMP_LABEL, and it might delete
+ the label if th lABEL_BUSES count drops to zero. There is
+ always a jump_optimize pass that sets these values, but it
+ proceeds to delete unreferenced code, and then if not
+ optimizing, to un-delete the deleted instructions, thus
+ leaving labels with too low uses counts. */
+ if (! optimize)
+ {
+ JUMP_LABEL (insn) = olabel;
+ LABEL_NUSES (olabel)++;
+ }
+ if (! bp)
+ {
+ bp = (struct far_branch *) alloca (sizeof *bp);
+ uid_branch[dest_uid] = bp;
+ bp->prev = far_branch_list;
+ far_branch_list = bp;
+ bp->far_label
+ = XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0);
+ LABEL_NUSES (bp->far_label)++;
+ }
+ else
+ {
+ label = bp->near_label;
+ if (! label && bp->address - addr >= CONDJUMP_MIN)
+ {
+ rtx block = bp->insert_place;
+
+ if (GET_CODE (PATTERN (block)) == RETURN)
+ block = PREV_INSN (block);
+ else
+ block = gen_block_redirect (block,
+ bp->address, 2);
+ label = emit_label_after (gen_label_rtx (),
+ PREV_INSN (block));
+ bp->near_label = label;
+ }
+ else if (label && ! NEXT_INSN (label))
+ if (addr + 2 - bp->address <= CONDJUMP_MAX)
+ bp->insert_place = insn;
+ else
+ gen_far_branch (bp);
+ }
+ if (! label
+ || NEXT_INSN (label) && bp->address - addr < CONDJUMP_MIN)
+ {
+ bp->near_label = label = gen_label_rtx ();
+ bp->insert_place = insn;
+ bp->address = addr;
+ }
+ if (! redirect_jump (insn, label))
+ abort ();
+ }
+ else
+ {
+ /* get_attr_length (insn) == 2 */
+ /* Check if we have a pattern where reorg wants to redirect
+ the branch to a label from an unconditional branch that
+ is too far away. */
+ /* We can't use JUMP_LABEL here because it might be undefined
+ when not optimizing. */
+ beyond
+ = next_active_insn (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1),
+ 0));
+
+ if ((GET_CODE (beyond) == JUMP_INSN
+ || (GET_CODE (beyond = next_active_insn (beyond))
+ == JUMP_INSN))
+ && GET_CODE (PATTERN (beyond)) == SET
+ && recog_memoized (beyond) == CODE_FOR_jump
+ && ((insn_addresses[INSN_UID (XEXP (SET_SRC (PATTERN (beyond)), 0))]
+ - insn_addresses[INSN_UID (insn)] + 252U)
+ > 252 + 258 + 2))
+ gen_block_redirect (beyond,
+ insn_addresses[INSN_UID (beyond)], 1);
+ }
+
+ next = next_active_insn (insn);
+
+ if ((GET_CODE (next) == JUMP_INSN
+ || GET_CODE (next = next_active_insn (next)) == JUMP_INSN)
+ && GET_CODE (PATTERN (next)) == SET
+ && recog_memoized (next) == CODE_FOR_jump
+ && ((insn_addresses[INSN_UID (XEXP (SET_SRC (PATTERN (next)), 0))]
+ - insn_addresses[INSN_UID (insn)] + 252U)
+ > 252 + 258 + 2))
+ gen_block_redirect (next, insn_addresses[INSN_UID (next)], 1);
+ }
+ else if (type == TYPE_JUMP || type == TYPE_RETURN)
+ {
+ int addr = insn_addresses[INSN_UID (insn)];
+ rtx far_label = 0;
+ int dest_uid = 0;
+ struct far_branch *bp;
+
+ if (type == TYPE_JUMP)
+ {
+ far_label = XEXP (SET_SRC (PATTERN (insn)), 0);
+ dest_uid = get_dest_uid (far_label, max_uid);
+ if (! dest_uid)
+ {
+ /* Parse errors can lead to labels outside
+ the insn stream. */
+ if (! NEXT_INSN (far_label))
+ continue;
+
+ if (! optimize)
+ {
+ JUMP_LABEL (insn) = far_label;
+ LABEL_NUSES (far_label)++;
+ }
+ redirect_jump (insn, NULL_RTX);
+ far_label = 0;
+ }
+ }
+ bp = uid_branch[dest_uid];
+ if (! bp)
+ {
+ bp = (struct far_branch *) alloca (sizeof *bp);
+ uid_branch[dest_uid] = bp;
+ bp->prev = far_branch_list;
+ far_branch_list = bp;
+ bp->near_label = 0;
+ bp->far_label = far_label;
+ if (far_label)
+ LABEL_NUSES (far_label)++;
+ }
+ else if (bp->near_label && ! NEXT_INSN (bp->near_label))
+ if (addr - bp->address <= CONDJUMP_MAX)
+ emit_label_after (bp->near_label, PREV_INSN (insn));
+ else
+ {
+ gen_far_branch (bp);
+ bp->near_label = 0;
+ }
+ else
+ bp->near_label = 0;
+ bp->address = addr;
+ bp->insert_place = insn;
+ if (! far_label)
+ emit_insn_before (gen_block_branch_redirect (const0_rtx), insn);
+ else
+ gen_block_redirect (insn, addr, bp->near_label ? 2 : 0);
+ }
+ }
+ /* Generate all pending far branches,
+ and free our references to the far labels. */
+ while (far_branch_list)
+ {
+ if (far_branch_list->near_label
+ && ! NEXT_INSN (far_branch_list->near_label))
+ gen_far_branch (far_branch_list);
+ if (optimize
+ && far_branch_list->far_label
+ && ! --LABEL_NUSES (far_branch_list->far_label))
+ delete_insn (far_branch_list->far_label);
+ far_branch_list = far_branch_list->prev;
+ }
+ uid_align_max = get_max_uid ();
+ uid_align = (rtx *) oballoc (uid_align_max * sizeof *uid_align);
+ fixup_aligns ();
}
/* Dump out instruction addresses, which is useful for debugging the
- constant pool table stuff. */
+ constant pool table stuff.
+
+ If relaxing, output the label and pseudo-ops used to link together
+ calls and the instruction which set the registers. */
/* ??? This is unnecessary, and probably should be deleted. This makes
the insn_addresses declaration above unnecessary. */
@@ -1377,6 +3459,32 @@ final_prescan_insn (insn, opvec, noperands)
{
if (TARGET_DUMPISIZE)
fprintf (asm_out_file, "\n! at %04x\n", insn_addresses[INSN_UID (insn)]);
+
+ if (TARGET_RELAX)
+ {
+ rtx note;
+
+ note = find_reg_note (insn, REG_LABEL, NULL_RTX);
+ if (note)
+ {
+ rtx pattern;
+
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) == PARALLEL)
+ pattern = XVECEXP (pattern, 0, 0);
+ if (GET_CODE (pattern) == CALL
+ || (GET_CODE (pattern) == SET
+ && (GET_CODE (SET_SRC (pattern)) == CALL
+ || get_attr_type (insn) == TYPE_SFUNC)))
+ asm_fprintf (asm_out_file, "\t.uses %LL%d\n",
+ CODE_LABEL_NUMBER (XEXP (note, 0)));
+ else if (GET_CODE (pattern) == SET)
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+ CODE_LABEL_NUMBER (XEXP (note, 0)));
+ else
+ abort ();
+ }
+ }
}
/* Dump out any constants accumulated in the final pass. These will
@@ -1428,27 +3536,54 @@ output_jump_label_table ()
static int extra_push;
-/* Adjust the stack and return the number of bytes taken to do it. */
+/* Adjust the stack by SIZE bytes. REG holds the rtl of the register
+ to be adjusted, and TEMP, if nonnegative, holds the register number
+ of a general register that we may clobber. */
static void
-output_stack_adjust (size, reg)
+output_stack_adjust (size, reg, temp)
int size;
rtx reg;
+ int temp;
{
if (size)
{
- rtx val = GEN_INT (size);
- rtx insn;
-
- if (! CONST_OK_FOR_I (size))
+ if (CONST_OK_FOR_I (size))
+ emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
+ /* Try to do it with two partial adjustments; however, we must make
+ sure that the stack is properly aligned at all times, in case
+ an interrupt occurs between the two partial adjustments. */
+ else if (CONST_OK_FOR_I (size / 2 & -4)
+ && CONST_OK_FOR_I (size - (size / 2 & -4)))
{
- rtx reg = gen_rtx (REG, SImode, 3);
- emit_insn (gen_movsi (reg, val));
- val = reg;
+ emit_insn (gen_addsi3 (reg, reg, GEN_INT (size / 2 & -4)));
+ emit_insn (gen_addsi3 (reg, reg, GEN_INT (size - (size / 2 & -4))));
}
+ else
+ {
+ rtx const_reg;
+
+ /* If TEMP is invalid, we could temporarily save a general
+ register to MACL. However, there is currently no need
+ to handle this case, so just abort when we see it. */
+ if (temp < 0)
+ abort ();
+ const_reg = gen_rtx (REG, SImode, temp);
- insn = gen_addsi3 (reg, reg, val);
- emit_insn (insn);
+ /* If SIZE is negative, subtract the positive value.
+ This sometimes allows a constant pool entry to be shared
+ between prologue and epilogue code. */
+ if (size < 0)
+ {
+ emit_insn (gen_movsi (const_reg, GEN_INT (-size)));
+ emit_insn (gen_subsi3 (reg, reg, const_reg));
+ }
+ else
+ {
+ emit_insn (gen_movsi (const_reg, GEN_INT (size)));
+ emit_insn (gen_addsi3 (reg, reg, const_reg));
+ }
+ }
}
}
@@ -1459,7 +3594,13 @@ push (rn)
int rn;
{
rtx x;
- x = emit_insn (gen_push (gen_rtx (REG, SImode, rn)));
+ if ((rn >= FIRST_FP_REG && rn <= LAST_FP_REG)
+ || rn == FPUL_REG)
+ x = gen_push_e (gen_rtx (REG, SFmode, rn));
+ else
+ x = gen_push (gen_rtx (REG, SImode, rn));
+
+ x = emit_insn (x);
REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC,
gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0);
}
@@ -1471,62 +3612,74 @@ pop (rn)
int rn;
{
rtx x;
- x = emit_insn (gen_pop (gen_rtx (REG, SImode, rn)));
+ if ((rn >= FIRST_FP_REG && rn <= LAST_FP_REG)
+ || rn == FPUL_REG)
+ x = gen_pop_e (gen_rtx (REG, SFmode, rn));
+ else
+ x = gen_pop (gen_rtx (REG, SImode, rn));
+
+ x = emit_insn (x);
REG_NOTES (x) = gen_rtx (EXPR_LIST, REG_INC,
gen_rtx(REG, SImode, STACK_POINTER_REGNUM), 0);
}
-/* Generate code to push the regs specified in the mask, and return
- the number of bytes the insns take. */
+/* Generate code to push the regs specified in the mask. */
static void
-push_regs (mask)
- int mask;
+push_regs (mask, mask2)
+ int mask, mask2;
{
int i;
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (mask & (1 << i))
+ /* Push PR last; this gives better latencies after the prologue, and
+ candidates for the return delay slot when there are no general
+ registers pushed. */
+ for (i = 0; i < 32; i++)
+ if (mask & (1 << i) && i != PR_REG)
+ push (i);
+ for (i = 32; i < FIRST_PSEUDO_REGISTER; i++)
+ if (mask2 & (1 << (i - 32)))
push (i);
+ if (mask & (1 << PR_REG))
+ push (PR_REG);
}
/* Work out the registers which need to be saved, both as a mask and a
- count.
+ count of saved words.
If doing a pragma interrupt function, then push all regs used by the
function, and if we call another function (we can tell by looking at PR),
make sure that all the regs it clobbers are safe too. */
static int
-calc_live_regs (count_ptr)
+calc_live_regs (count_ptr, live_regs_mask2)
int *count_ptr;
+ int *live_regs_mask2;
{
int reg;
int live_regs_mask = 0;
- int count = 0;
+ int count;
- for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
+ *live_regs_mask2 = 0;
+ for (count = 0, reg = FIRST_PSEUDO_REGISTER - 1; reg >= 0; reg--)
{
- if (pragma_interrupt && ! pragma_trapa)
- {
- /* Need to save all the regs ever live. */
- if ((regs_ever_live[reg]
- || (call_used_regs[reg] && regs_ever_live[PR_REG]))
- && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
- && reg != T_REG && reg != GBR_REG)
- {
- live_regs_mask |= 1 << reg;
- count++;
- }
- }
- else
+ if ((pragma_interrupt && ! pragma_trapa)
+ ? (/* Need to save all the regs ever live. */
+ (regs_ever_live[reg]
+ || (call_used_regs[reg]
+ && (! fixed_regs[reg] || reg == MACH_REG || reg == MACL_REG)
+ && regs_ever_live[PR_REG]))
+ && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
+ && reg != RETURN_ADDRESS_POINTER_REGNUM
+ && reg != T_REG && reg != GBR_REG)
+ : (/* Only push those regs which are used and need to be saved. */
+ regs_ever_live[reg] && ! call_used_regs[reg]))
{
- /* Only push those regs which are used and need to be saved. */
- if (regs_ever_live[reg] && ! call_used_regs[reg])
- {
- live_regs_mask |= (1 << reg);
- count++;
- }
+ if (reg >= 32)
+ *live_regs_mask2 |= 1 << (reg - 32);
+ else
+ live_regs_mask |= 1 << reg;
+ count++;
}
}
@@ -1541,33 +3694,46 @@ sh_expand_prologue ()
{
int live_regs_mask;
int d, i;
- live_regs_mask = calc_live_regs (&d);
+ int live_regs_mask2;
/* We have pretend args if we had an object sent partially in registers
and partially on the stack, e.g. a large structure. */
- output_stack_adjust (-current_function_pretend_args_size, stack_pointer_rtx);
+ output_stack_adjust (-current_function_pretend_args_size,
+ stack_pointer_rtx, 3);
extra_push = 0;
/* This is set by SETUP_VARARGS to indicate that this is a varargs
- routine. Clear it here so that the next function isn't affected. */
+ routine. Clear it here so that the next function isn't affected. */
if (current_function_anonymous_args)
{
current_function_anonymous_args = 0;
- /* Push arg regs as if they'd been provided by caller in stack. */
- for (i = 0; i < NPARM_REGS; i++)
+ /* This is not used by the SH3E calling convention */
+ if (!TARGET_SH3E)
{
- int rn = NPARM_REGS + FIRST_PARM_REG - i - 1;
- if (i > (NPARM_REGS - current_function_args_info
- - current_function_varargs))
- break;
- push (rn);
- extra_push += 4;
+ /* Push arg regs as if they'd been provided by caller in stack. */
+ for (i = 0; i < NPARM_REGS(SImode); i++)
+ {
+ int rn = NPARM_REGS(SImode) + FIRST_PARM_REG - i - 1;
+ if (i > (NPARM_REGS(SImode)
+ - current_function_args_info.arg_count[(int) SH_ARG_INT]
+ - current_function_varargs))
+ break;
+ push (rn);
+ extra_push += 4;
+ }
}
}
- push_regs (live_regs_mask);
- output_stack_adjust (-get_frame_size (), stack_pointer_rtx);
+
+ /* If we're supposed to switch stacks at function entry, do so now. */
+ if (sp_switch)
+ emit_insn (gen_sp_switch_1 ());
+
+ live_regs_mask = calc_live_regs (&d, &live_regs_mask2);
+ push_regs (live_regs_mask, live_regs_mask2);
+
+ output_stack_adjust (-get_frame_size (), stack_pointer_rtx, 3);
if (frame_pointer_needed)
emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
@@ -1579,31 +3745,49 @@ sh_expand_epilogue ()
int live_regs_mask;
int d, i;
- live_regs_mask = calc_live_regs (&d);
+ int live_regs_mask2;
if (frame_pointer_needed)
{
- /* We deliberately make the add dependent on the frame_pointer,
- to ensure that instruction scheduling won't move the stack pointer
- adjust before instructions reading from the frame. This can fail
- if there is an interrupt which then writes to the stack. */
- output_stack_adjust (get_frame_size (), frame_pointer_rtx);
+ output_stack_adjust (get_frame_size (), frame_pointer_rtx, 7);
+
+ /* We must avoid moving the stack pointer adjustment past code
+ which reads from the local frame, else an interrupt could
+ occur after the SP adjustment and clobber data in the local
+ frame. */
+ emit_insn (gen_blockage ());
emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx));
}
- else
- output_stack_adjust (get_frame_size (), stack_pointer_rtx);
+ else if (get_frame_size ())
+ {
+ /* We must avoid moving the stack pointer adjustment past code
+ which reads from the local frame, else an interrupt could
+ occur after the SP adjustment and clobber data in the local
+ frame. */
+ emit_insn (gen_blockage ());
+ output_stack_adjust (get_frame_size (), stack_pointer_rtx, 7);
+ }
/* Pop all the registers. */
+ live_regs_mask = calc_live_regs (&d, &live_regs_mask2);
+ if (live_regs_mask & (1 << PR_REG))
+ pop (PR_REG);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
int j = (FIRST_PSEUDO_REGISTER - 1) - i;
- if (live_regs_mask & (1 << j))
+ if (j < 32 && (live_regs_mask & (1 << j)) && j != PR_REG)
+ pop (j);
+ else if (j >= 32 && (live_regs_mask2 & (1 << (j - 32))))
pop (j);
}
output_stack_adjust (extra_push + current_function_pretend_args_size,
- stack_pointer_rtx);
+ stack_pointer_rtx, 7);
+
+ /* Switch back to the normal stack if necessary. */
+ if (sp_switch)
+ emit_insn (gen_sp_switch_2 ());
}
/* Clear variables at function end. */
@@ -1613,7 +3797,66 @@ function_epilogue (stream, size)
FILE *stream;
int size;
{
- pragma_interrupt = pragma_trapa = 0;
+ trap_exit = pragma_interrupt = pragma_trapa = pragma_nosave_low_regs = 0;
+ sp_switch = NULL_RTX;
+}
+
+rtx
+sh_builtin_saveregs (arglist)
+ tree arglist;
+{
+ tree fntype = TREE_TYPE (current_function_decl);
+ /* First unnamed integer register. */
+ int first_intreg = current_function_args_info.arg_count[(int) SH_ARG_INT];
+ /* Number of integer registers we need to save. */
+ int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg);
+ /* First unnamed SFmode float reg */
+ int first_floatreg = current_function_args_info.arg_count[(int) SH_ARG_FLOAT];
+ /* Number of SFmode float regs to save. */
+ int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
+ int ptrsize = GET_MODE_SIZE (Pmode);
+ rtx valist, regbuf, fpregs;
+ int bufsize, regno;
+
+ /* Allocate block of memory for the regs. */
+ /* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte?
+ Or can assign_stack_local accept a 0 SIZE argument? */
+ bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD);
+
+ regbuf = assign_stack_local (BLKmode, bufsize, 0);
+ MEM_IN_STRUCT_P (regbuf) = 1;
+
+ /* Save int args.
+ This is optimized to only save the regs that are necessary. Explicitly
+ named args need not be saved. */
+ if (n_intregs > 0)
+ move_block_from_reg (BASE_ARG_REG (SImode) + first_intreg,
+ gen_rtx (MEM, BLKmode,
+ plus_constant (XEXP (regbuf, 0),
+ n_floatregs * UNITS_PER_WORD)),
+ n_intregs, n_intregs * UNITS_PER_WORD);
+
+ /* Save float args.
+ This is optimized to only save the regs that are necessary. Explicitly
+ named args need not be saved.
+ We explicitly build a pointer to the buffer because it halves the insn
+ count when not optimizing (otherwise the pointer is built for each reg
+ saved).
+ We emit the moves in reverse order so that we can use predecrement. */
+
+ fpregs = gen_reg_rtx (Pmode);
+ emit_move_insn (fpregs, XEXP (regbuf, 0));
+ emit_insn (gen_addsi3 (fpregs, fpregs,
+ GEN_INT (n_floatregs * UNITS_PER_WORD)));
+ for (regno = NPARM_REGS (SFmode) - 1; regno >= first_floatreg; regno--)
+ {
+ emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
+ emit_move_insn (gen_rtx (MEM, SFmode, fpregs),
+ gen_rtx (REG, SFmode, BASE_ARG_REG (SFmode) + regno));
+ }
+
+ /* Return the address of the regbuf. */
+ return XEXP (regbuf, 0);
}
/* Define the offset between two registers, one to be eliminated, and
@@ -1627,8 +3870,12 @@ initial_elimination_offset (from, to)
int regs_saved;
int total_saved_regs_space;
int total_auto_space = get_frame_size ();
+ int save_flags = target_flags;
+
+ int live_regs_mask, live_regs_mask2;
+ live_regs_mask = calc_live_regs (&regs_saved, &live_regs_mask2);
+ target_flags = save_flags;
- calc_live_regs (&regs_saved);
total_saved_regs_space = (regs_saved) * 4;
if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
@@ -1641,6 +3888,16 @@ initial_elimination_offset (from, to)
if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
return 0;
+ if (from == RETURN_ADDRESS_POINTER_REGNUM
+ && (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM))
+ {
+ int i, n = total_saved_regs_space;
+ for (i = PR_REG-1; i >= 0; i--)
+ if (live_regs_mask & (1 << i))
+ n -= 4;
+ return n + total_auto_space;
+ }
+
abort ();
}
@@ -1648,37 +3905,96 @@ initial_elimination_offset (from, to)
compiler. */
int
-handle_pragma (file)
+handle_pragma (file, t)
FILE *file;
+ tree t;
{
- int c;
- char pbuf[200];
- int psize = 0;
+ int retval = 0;
+ register char *pname;
- c = getc (file);
- while (c == ' ' || c == '\t')
- c = getc (file);
+ if (TREE_CODE (t) != IDENTIFIER_NODE)
+ return 0;
- if (c == '\n' || c == EOF)
- return c;
+ pname = IDENTIFIER_POINTER (t);
+ if (strcmp (pname, "interrupt") == 0)
+ pragma_interrupt = retval = 1;
+ else if (strcmp (pname, "trapa") == 0)
+ pragma_interrupt = pragma_trapa = retval = 1;
+ else if (strcmp (pname, "nosave_low_regs") == 0)
+ pragma_nosave_low_regs = retval = 1;
- while (psize < sizeof (pbuf) - 1 && c != '\n')
+ return retval;
+}
+/* Return nonzero if ATTR is a valid attribute for DECL.
+ ATTRIBUTES are any existing attributes and ARGS are the arguments
+ supplied with ATTR.
+
+ Supported attributes:
+
+ interrupt_handler -- specifies this function is an interrupt handler.
+
+ sp_switch -- specifies an alternate stack for an interrupt handler
+ to run on.
+
+ trap_exit -- use a trapa to exit an interrupt function instead of
+ an rte instruction. */
+
+int
+sh_valid_machine_decl_attribute (decl, attributes, attr, args)
+ tree decl;
+ tree attributes;
+ tree attr;
+ tree args;
+{
+ int retval = 0;
+
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ return 0;
+
+ if (is_attribute_p ("interrupt_handler", attr))
{
- pbuf[psize++] = c;
- if (psize == 9 && strncmp (pbuf, "interrupt", 9) == 0)
- {
- pragma_interrupt = 1;
- return ' ';
- }
- if (psize == 5 && strncmp (pbuf, "trapa", 5) == 0)
- {
- pragma_interrupt = pragma_trapa = 1;
- return ' ';
- }
- c = getc (file);
+ pragma_interrupt = 1;
+ return 1;
+ }
+
+ if (is_attribute_p ("sp_switch", attr))
+ {
+ /* The sp_switch attribute only has meaning for interrupt functions. */
+ if (!pragma_interrupt)
+ return 0;
+
+ /* sp_switch must have an argument. */
+ if (!args || TREE_CODE (args) != TREE_LIST)
+ return 0;
+
+ /* The argument must be a constant string. */
+ if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+ return 0;
+
+ sp_switch = gen_rtx (SYMBOL_REF, VOIDmode,
+ TREE_STRING_POINTER (TREE_VALUE (args)));
+ return 1;
+ }
+
+ if (is_attribute_p ("trap_exit", attr))
+ {
+ /* The trap_exit attribute only has meaning for interrupt functions. */
+ if (!pragma_interrupt)
+ return 0;
+
+ /* trap_exit must have an argument. */
+ if (!args || TREE_CODE (args) != TREE_LIST)
+ return 0;
+
+ /* The argument must be a constant integer. */
+ if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
+ return 0;
+
+ trap_exit = TREE_INT_CST_LOW (TREE_VALUE (args));
+ return 1;
}
- return c;
}
+
/* Predicates used by the templates. */
@@ -1761,12 +4077,17 @@ arith_reg_operand (op, mode)
{
if (register_operand (op, mode))
{
+ int regno;
+
if (GET_CODE (op) == REG)
- return (REGNO (op) != T_REG
- && REGNO (op) != PR_REG
- && REGNO (op) != MACH_REG
- && REGNO (op) != MACL_REG);
- return 1;
+ regno = REGNO (op);
+ else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
+ regno = REGNO (SUBREG_REG (op));
+ else
+ return 1;
+
+ return (regno != T_REG && regno != PR_REG && regno != FPUL_REG
+ && regno != MACH_REG && regno != MACL_REG);
}
return 0;
}
@@ -1818,65 +4139,239 @@ logical_operand (op, mode)
return 0;
}
-
-/* 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). */
-rtx
-sh_function_arg (cum, mode, type, named)
- CUMULATIVE_ARGS cum;
- enum machine_mode mode;
- tree type;
- int named;
+/* Nonzero if OP is a floating point value with value 0.0. */
+
+int
+fp_zero_operand (op)
+ rtx op;
{
- if (named)
- {
- int rr = (ROUND_REG (cum, mode));
+ REAL_VALUE_TYPE r;
- if (rr < NPARM_REGS)
- return ((type == 0 || ! TREE_ADDRESSABLE (type))
- ? gen_rtx (REG, mode, FIRST_PARM_REG + rr) : 0);
- }
- return 0;
+ if (GET_MODE (op) != SFmode)
+ return 0;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ return REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r);
}
-/* 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 4 regs but won't entirely fit in them
- needs partial registers on the SH. */
+/* Nonzero if OP is a floating point value with value 1.0. */
int
-sh_function_arg_partial_nregs (cum, mode, type, named)
- CUMULATIVE_ARGS cum;
+fp_one_operand (op)
+ rtx op;
+{
+ REAL_VALUE_TYPE r;
+
+ if (GET_MODE (op) != SFmode)
+ return 0;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ return REAL_VALUES_EQUAL (r, dconst1);
+}
+
+int
+braf_label_ref_operand(op, mode)
+ rtx op;
enum machine_mode mode;
- tree type;
- int named;
{
- if (cum < NPARM_REGS)
+ rtx prev;
+
+ if (GET_CODE (op) != LABEL_REF)
+ return 0;
+ prev = prev_real_insn (XEXP (op, 0));
+ if (GET_CODE (prev) != JUMP_INSN)
+ return 0;
+ prev = PATTERN (prev);
+ if (GET_CODE (prev) != PARALLEL || XVECLEN (prev, 0) != 2)
+ return 0;
+ prev = XVECEXP (prev, 0, 0);
+ if (GET_CODE (prev) != SET)
+ return 0;
+ prev = SET_SRC (prev);
+ if (GET_CODE (prev) != PLUS || XEXP (prev, 1) != op)
+ return 0;
+}
+
+/* Return the offset of a branch. Offsets for backward branches are
+ reported relative to the branch instruction, while offsets for forward
+ branches are reported relative to the following instruction. */
+
+int
+branch_offset (branch)
+ rtx branch;
+{
+ rtx dest = SET_SRC (PATTERN (branch)), dest_next;
+ int branch_uid = INSN_UID (branch);
+ int dest_uid, dest_addr;
+ rtx branch_align = uid_align[branch_uid];
+
+ if (GET_CODE (dest) == IF_THEN_ELSE)
+ dest = XEXP (dest, 1);
+ dest = XEXP (dest, 0);
+ dest_uid = INSN_UID (dest);
+ dest_addr = insn_addresses[dest_uid];
+ if (branch_align)
{
- if ((type == 0 || ! TREE_ADDRESSABLE (type))
- && (cum + (mode == BLKmode
- ? ROUND_ADVANCE (int_size_in_bytes (type))
- : ROUND_ADVANCE (GET_MODE_SIZE (mode))) - NPARM_REGS > 0))
- return NPARM_REGS - cum;
+ /* Forward branch. */
+ /* If branch is in a sequence, get the successor of the sequence. */
+ rtx next = NEXT_INSN (NEXT_INSN (PREV_INSN (branch)));
+ int next_addr = insn_addresses[INSN_UID (next)];
+ int diff;
+
+ /* If NEXT has been hoisted in a sequence further on, it address has
+ been clobbered in the previous pass. However, if that is the case,
+ we know that it is exactly 2 bytes long (because it fits in a delay
+ slot), and that there is a following label (the destination of the
+ instruction that filled its delay slot with NEXT). The address of
+ this label is reliable. */
+ if (NEXT_INSN (next))
+ {
+ int next_next_addr = insn_addresses[INSN_UID (NEXT_INSN (next))];
+ if (next_addr > next_next_addr)
+ next_addr = next_next_addr - 2;
+ }
+ diff = dest_addr - next_addr;
+ /* If BRANCH_ALIGN has been the last insn, it might be a barrier or
+ a note. */
+ if ((insn_addresses[INSN_UID (branch_align)] < dest_addr
+ || (insn_addresses[INSN_UID (branch_align)] == dest_addr
+ && next_real_insn (dest) != branch_align))
+ && GET_CODE (branch_align) == INSN)
+ {
+ int align = 1 << INTVAL (XVECEXP (PATTERN (branch_align), 0, 0));
+ int align_addr = insn_addresses[INSN_UID (branch_align)];
+ diff += (align_addr - 1) & (align - 2);
+ branch_align = uid_align[INSN_UID (branch_align)];
+ if (insn_addresses[INSN_UID (branch_align)] <= dest_addr
+ && GET_CODE (branch_align) == INSN)
+ {
+ int align2 = 1 << INTVAL (XVECEXP (PATTERN (branch_align), 0, 0));
+ align_addr = insn_addresses[INSN_UID (branch_align)];
+ diff += (align_addr - 1) & (align2 - align);
+ }
+ }
+ return diff;
}
- return 0;
+ else
+ {
+ /* Backward branch. */
+ int branch_addr = insn_addresses[branch_uid];
+ int diff = dest_addr - branch_addr;
+ int old_align = 2;
+
+ while (dest_uid >= uid_align_max || ! uid_align[dest_uid])
+ {
+ /* Label might be outside the insn stream, or even in a separate
+ insn stream, after a syntax error. */
+ if (! NEXT_INSN (dest))
+ return 0;
+ dest = NEXT_INSN (dest), dest_uid = INSN_UID (dest);
+ }
+
+ /* By searching for a known destination, we might already have
+ stumbled on the alignment instruction. */
+ if (GET_CODE (dest) == INSN
+ && GET_CODE (PATTERN (dest)) == UNSPEC_VOLATILE
+ && XINT (PATTERN (dest), 1) == 1
+ && INTVAL (XVECEXP (PATTERN (dest), 0, 0)) > 1)
+ branch_align = dest;
+ else
+ branch_align = uid_align[dest_uid];
+ while (insn_addresses[INSN_UID (branch_align)] <= branch_addr
+ && GET_CODE (branch_align) == INSN)
+ {
+ int align = 1 << INTVAL (XVECEXP (PATTERN (branch_align), 0, 0));
+ int align_addr = insn_addresses[INSN_UID (branch_align)];
+ diff -= (align_addr - 1) & (align - old_align);
+ old_align = align;
+ branch_align = uid_align[INSN_UID (branch_align)];
+ }
+ return diff;
+ }
+}
+
+int
+short_cbranch_p (branch)
+ rtx branch;
+{
+ int offset;
+
+ if (! insn_addresses)
+ return 0;
+ if (mdep_reorg_phase <= SH_FIXUP_PCLOAD)
+ return 0;
+ offset = branch_offset (branch);
+ return (offset >= -252
+ && offset <= (NEXT_INSN (PREV_INSN (branch)) == branch ? 256 : 254));
+}
+
+/* The maximum range used for SImode constant pool entrys is 1018. A final
+ instruction can add 8 bytes while only being 4 bytes in size, thus we
+ can have a total of 1022 bytes in the pool. Add 4 bytes for a branch
+ instruction around the pool table, 2 bytes of alignment before the table,
+ and 30 bytes of alignment after the table. That gives a maximum total
+ pool size of 1058 bytes.
+ Worst case code/pool content size ratio is 1:2 (using asms).
+ Thus, in the worst case, there is one instruction in front of a maximum
+ sized pool, and then there are 1052 bytes of pool for every 508 bytes of
+ code. For the last n bytes of code, there are 2n + 36 bytes of pool.
+ If we have a forward branch, the initial table will be put after the
+ unconditional branch.
+
+ ??? We could do much better by keeping track of the actual pcloads within
+ the branch range and in the pcload range in front of the branch range. */
+
+int
+med_branch_p (branch, condlen)
+ rtx branch;
+ int condlen;
+{
+ int offset;
+
+ if (! insn_addresses)
+ return 0;
+ offset = branch_offset (branch);
+ if (mdep_reorg_phase <= SH_FIXUP_PCLOAD)
+ return offset - condlen >= -990 && offset <= 998;
+ return offset - condlen >= -4092 && offset <= 4094;
+}
+
+int
+braf_branch_p (branch, condlen)
+ rtx branch;
+ int condlen;
+{
+ int offset;
+
+ if (! insn_addresses)
+ return 0;
+ if (! TARGET_SH2)
+ return 0;
+ offset = branch_offset (branch);
+ if (mdep_reorg_phase <= SH_FIXUP_PCLOAD)
+ return offset - condlen >= -10330 && offset <= 10330;
+ return offset -condlen >= -32764 && offset <= 32766;
+}
+
+int
+align_length (insn)
+ rtx insn;
+{
+ int align = 1 << INTVAL (XVECEXP (PATTERN (insn), 0, 0));
+ if (! insn_addresses)
+ if (optimize
+ && (mdep_reorg_phase == SH_SHORTEN_BRANCHES0
+ || mdep_reorg_phase == SH_SHORTEN_BRANCHES1))
+ return 0;
+ else
+ return align - 2;
+ return align - 2 - ((insn_addresses[INSN_UID (insn)] - 2) & (align - 2));
}
/* 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. */
+ not live past labels. It may live past calls or jumps though. */
int
reg_unused_after (reg, insn)
rtx reg;
@@ -1907,11 +4402,14 @@ reg_unused_after (reg, insn)
/* else */
#endif
+ if (code == JUMP_INSN)
+ return 0;
+
/* If this is a sequence, we must handle them all at once.
We could have for instance a call that sets the target register,
and a insn in a delay slot that uses the register. In this case,
we must return 0. */
- if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
{
int i;
int retval = 0;
@@ -1923,6 +4421,12 @@ reg_unused_after (reg, insn)
if (GET_CODE (this_insn) == CALL_INSN)
code = CALL_INSN;
+ else if (GET_CODE (this_insn) == JUMP_INSN)
+ {
+ if (INSN_ANNULLED_BRANCH_P (this_insn))
+ return 0;
+ code = JUMP_INSN;
+ }
if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
return 0;
@@ -1939,6 +4443,8 @@ reg_unused_after (reg, insn)
}
if (retval == 1)
return 1;
+ else if (code == JUMP_INSN)
+ return 0;
}
else if (GET_RTX_CLASS (code) == 'i')
{
diff --git a/gnu/usr.bin/gcc/config/sh/sh.h b/gnu/usr.bin/gcc/config/sh/sh.h
index 3b670149722..a3aa90253e6 100644
--- a/gnu/usr.bin/gcc/config/sh/sh.h
+++ b/gnu/usr.bin/gcc/config/sh/sh.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler for Hitachi Super-H.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Steve Chamberlain (sac@cygnus.com).
Improved by Jim Wilson (wilson@cygnus.com).
@@ -24,38 +24,50 @@ Boston, MA 02111-1307, USA. */
#define TARGET_VERSION \
fputs (" (Hitachi SH)", stderr);
+/* Unfortunately, insn-attrtab.c doesn't include insn-codes.h. We can't
+ include it here, because hconfig.h is also included by gencodes.c . */
+extern int code_for_indirect_jump_scratch;
+
/* Generate SDB debugging information. */
#define SDB_DEBUGGING_INFO
/* Output DBX (stabs) debugging information if doing -gstabs. */
-#define DBX_DEBUGGING_INFO
-
-/* Generate SDB debugging information by default. */
-
-#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
+#include "dbxcoff.h"
#define SDB_DELIM ";"
-#define CPP_SPEC "%{ml:-D__LITTLE_ENDIAN__}"
+#define CPP_SPEC "%{ml:-D__LITTLE_ENDIAN__} \
+%{m1:-D__sh1__} \
+%{m2:-D__sh2__} \
+%{m3:-D__sh3__} \
+%{m3e:-D__SH3E__} \
+%{!m1:%{!m2:%{!m3:%{!m3e:-D__sh1__}}}}"
#define CPP_PREDEFINES "-D__sh__ -Acpu(sh) -Amachine(sh)"
-#define ASM_SPEC "%{ml:-little}"
+#define ASM_SPEC "%{ml:-little} %{mrelax:-relax}"
-#define LINK_SPEC "%{ml:-m shl}"
+#define LINK_SPEC "%{ml:-m shl} %{mrelax:-relax}"
/* We can not debug without a frame pointer. */
/* #define CAN_DEBUG_WITHOUT_FP */
#define CONDITIONAL_REGISTER_USAGE \
+ if (! TARGET_SH3E) \
+ { \
+ int regno; \
+ for (regno = FIRST_FP_REG; regno <= LAST_FP_REG; regno++) \
+ fixed_regs[regno] = call_used_regs[regno] = 1; \
+ fixed_regs[FPUL_REG] = call_used_regs[FPUL_REG] = 1; \
+ } \
/* Hitachi saves and restores mac registers on call. */ \
if (TARGET_HITACHI) \
- { \
- call_used_regs[MACH_REG] = 0; \
- call_used_regs[MACL_REG] = 0; \
- }
+ { \
+ call_used_regs[MACH_REG] = 0; \
+ call_used_regs[MACL_REG] = 0; \
+ }
/* ??? Need to write documentation for all SH options and add it to the
invoke.texi file. */
@@ -65,15 +77,17 @@ Boston, MA 02111-1307, USA. */
extern int target_flags;
#define ISIZE_BIT (1<<1)
#define DALIGN_BIT (1<<6)
-#define SH0_BIT (1<<7)
#define SH1_BIT (1<<8)
#define SH2_BIT (1<<9)
#define SH3_BIT (1<<10)
+#define SH3E_BIT (1<<11)
#define SPACE_BIT (1<<13)
#define BIGTABLE_BIT (1<<14)
+#define RELAX_BIT (1<<15)
#define HITACHI_BIT (1<<22)
#define PADSTRUCT_BIT (1<<28)
#define LITTLE_ENDIAN_BIT (1<<29)
+#define IEEE_BIT (1<<30)
/* Nonzero if we should dump out instruction size info. */
#define TARGET_DUMPISIZE (target_flags & ISIZE_BIT)
@@ -81,11 +95,6 @@ extern int target_flags;
/* Nonzero to align doubles on 64 bit boundaries. */
#define TARGET_ALIGN_DOUBLE (target_flags & DALIGN_BIT)
-/* Nonzero if we should generate code using type 0 insns. */
-/* ??? Is there such a thing as SH0? If not, we should delete all
- references to it. */
-#define TARGET_SH0 (target_flags & SH0_BIT)
-
/* Nonzero if we should generate code using type 1 insns. */
#define TARGET_SH1 (target_flags & SH1_BIT)
@@ -95,12 +104,22 @@ extern int target_flags;
/* Nonzero if we should generate code using type 3 insns. */
#define TARGET_SH3 (target_flags & SH3_BIT)
+/* Nonzero if we should generate code using type 3E insns. */
+#define TARGET_SH3E (target_flags & SH3E_BIT)
+
+/* Nonzero if we respect NANs. */
+#define TARGET_IEEE (target_flags & IEEE_BIT)
+
/* Nonzero if we should generate smaller code rather than faster code. */
#define TARGET_SMALLCODE (target_flags & SPACE_BIT)
/* Nonzero to use long jump tables. */
#define TARGET_BIGTABLE (target_flags & BIGTABLE_BIT)
+/* Nonzero to generate pseudo-ops needed by the assembler and linker
+ to do function call relaxing. */
+#define TARGET_RELAX (target_flags & RELAX_BIT)
+
/* Nonzero if using Hitachi's calling convention. */
#define TARGET_HITACHI (target_flags & HITACHI_BIT)
@@ -115,47 +134,48 @@ extern int target_flags;
#define TARGET_LITTLE_ENDIAN (target_flags & LITTLE_ENDIAN_BIT)
#define TARGET_SWITCHES \
-{ {"0", SH0_BIT}, \
- {"1", SH1_BIT}, \
+{ {"1", SH1_BIT}, \
{"2", SH2_BIT}, \
{"3", SH3_BIT|SH2_BIT}, \
- {"3l", SH3_BIT|SH2_BIT|LITTLE_ENDIAN_BIT}, \
+ {"3e", SH3E_BIT|SH3_BIT|SH2_BIT}, \
{"b", -LITTLE_ENDIAN_BIT}, \
{"bigtable", BIGTABLE_BIT}, \
{"dalign", DALIGN_BIT}, \
{"hitachi", HITACHI_BIT}, \
+ {"ieee", IEEE_BIT}, \
{"isize", ISIZE_BIT}, \
{"l", LITTLE_ENDIAN_BIT}, \
+ {"no-ieee", -IEEE_BIT}, \
{"padstruct", PADSTRUCT_BIT}, \
+ {"relax", RELAX_BIT}, \
{"space", SPACE_BIT}, \
+ SUBTARGET_SWITCHES \
{"", TARGET_DEFAULT} \
}
+/* This are meant to be redefined in the host dependent files */
+#define SUBTARGET_SWITCHES
+
#define TARGET_DEFAULT (0)
+#define PRESERVE_DEATH_INFO_REGNO_P(regno) (TARGET_RELAX || optimize)
+
+#define ASSEMBLER_DIALECT 0 /* will allow to distinguish b[tf].s and b[tf]/s . */
#define OVERRIDE_OPTIONS \
do { \
- sh_cpu = CPU_SH0; \
- if (TARGET_SH1) \
- sh_cpu = CPU_SH1; \
+ sh_cpu = CPU_SH1; \
if (TARGET_SH2) \
sh_cpu = CPU_SH2; \
if (TARGET_SH3) \
sh_cpu = CPU_SH3; \
+ if (TARGET_SH3E) \
+ sh_cpu = CPU_SH3E; \
\
- /* We *MUST* always define optimize since we *HAVE* to run \
- shorten branches to get correct code. */ \
- /* ??? This is obsolete, since now shorten branches is no \
- longer required by the SH, and is always run once even \
- when not optimizing. Changing this now might be \
- confusing though. */ \
- optimize = 1; \
- flag_delayed_branch = 1; \
- \
- /* But never run scheduling before reload, since that can \
+ /* Never run scheduling before reload, since that can \
break global alloc, and generates slower code anyway due \
to the pressure on R0. */ \
flag_schedule_insns = 0; \
+ sh_addr_diff_vec_mode = TARGET_BIGTABLE ? SImode : HImode; \
} while (0)
/* Target machine storage layout. */
@@ -207,13 +227,14 @@ do { \
/* Boundary (in *bits*) on which stack pointer should be aligned. */
#define STACK_BOUNDARY 32
+/* The log (base 2) of the cache line size, in bytes. Processors prior to
+ SH3 have no actual cache, but they fetch code in chunks of 4 bytes. */
+#define CACHE_LOG (TARGET_SH3 ? 4 : 2)
+
/* Allocation boundary (in *bits*) for the code of a function.
32 bit alignment is faster, because instructions are always fetched as a
pair from a longword boundary. */
-/* ??? Perhaps also define ASM_OUTPUT_ALIGN_CODE and/or ASM_OUTPUT_LOOP_ALIGN
- so as to align jump targets and/or loops to 4 byte boundaries when not
- optimizing for space? */
-#define FUNCTION_BOUNDARY (TARGET_SMALLCODE ? 16 : 32)
+#define FUNCTION_BOUNDARY (TARGET_SMALLCODE ? 16 : (1 << CACHE_LOG) * 8)
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 32
@@ -259,7 +280,13 @@ do { \
pr subroutine return address
t t bit
mach multiply/accumulate result, high part
- macl multiply/accumulate result, low part. */
+ macl multiply/accumulate result, low part.
+ fpul fp/int communication register
+ rap return address pointer register
+ fr0 fp arg return
+ fr1..fr3 scratch floating point registers
+ fr4..fr11 fp args in
+ fr12..fr15 call saved floating point registers */
/* Number of actual hardware registers.
The hardware registers are assigned numbers for the compiler
@@ -274,8 +301,12 @@ do { \
#define MACH_REG 20
#define MACL_REG 21
#define SPECIAL_REG(REGNO) ((REGNO) >= 18 && (REGNO) <= 21)
+#define FPUL_REG 22
+#define RAP_REG 23
+#define FIRST_FP_REG 24
+#define LAST_FP_REG 39
-#define FIRST_PSEUDO_REGISTER 22
+#define FIRST_PSEUDO_REGISTER 40
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
@@ -289,7 +320,12 @@ do { \
0, 0, 0, 0, \
0, 0, 0, 1, \
1, 1, 1, 1, \
- 1, 1}
+ 1, 1, 0, 1, \
+ 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
@@ -299,12 +335,17 @@ do { \
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, \
- 0, 0, 0, 0, \
- 0, 0, 0, 1, \
- 1, 0, 1, 1, \
- 1, 1}
+ { 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 0, 0, 0, 0, \
+ 0, 0, 0, 1, \
+ 1, 0, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 1, 1, 1, 1, \
+ 0, 0, 0, 0, \
+}
/* Return number of consecutive hard regs needed starting at reg REGNO
to hold something of mode MODE.
@@ -322,6 +363,8 @@ do { \
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(SPECIAL_REG (REGNO) ? (MODE) == SImode \
+ : (REGNO) == FPUL_REG ? (MODE) == SImode || (MODE) == SFmode \
+ : (REGNO) >= FIRST_FP_REG && (REGNO) <= LAST_FP_REG ? (MODE) == SFmode \
: (REGNO) == PR_REG ? 0 \
: 1)
@@ -345,6 +388,10 @@ do { \
/* Base register for access to local variables of the function. */
#define FRAME_POINTER_REGNUM 14
+/* Fake register that holds the address on the stack of the
+ current function's return address. */
+#define RETURN_ADDRESS_POINTER_REGNUM 23
+
/* 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. */
@@ -353,20 +400,33 @@ do { \
/* Definitions for register eliminations.
- We have two registers that can be eliminated on the SH. First, the
+ We have three registers that can be eliminated on the SH. First, the
frame pointer register can often be eliminated in favor of the stack
pointer register. Secondly, the argument pointer register can always be
- eliminated; it is replaced with either the stack or frame pointer. */
+ eliminated; it is replaced with either the stack or frame pointer.
+ Third, there is the return address pointer, which can also be replaced
+ with either the stack or the frame pointer. */
/* This is an array of structures. Each structure initializes one pair
of eliminable registers. The "from" register number is given first,
followed by "to". Eliminations of the same "from" register are listed
in order of preference. */
-#define ELIMINABLE_REGS \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},}
+/* If you add any registers here that are not actually hard registers,
+ and that have any alternative of elimination that doesn't always
+ apply, you need to amend calc_live_regs to exclude it, because
+ reload spills all eliminable registers where it sees an
+ can_eliminate == 0 entry, thus making them 'live' .
+ If you add any hard registers that can be eliminated in different
+ ways, you have to patch reload to spill them only when all alternatives
+ of elimination fail. */
+
+#define ELIMINABLE_REGS \
+{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { RETURN_ADDRESS_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM},}
/* Given FROM and TO register numbers, say whether this elimination
is allowed. */
@@ -377,7 +437,7 @@ do { \
its replacement, at the start of a routine. */
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- OFFSET = initial_elimination_offset (FROM, TO)
+ OFFSET = initial_elimination_offset ((FROM), (TO))
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM 16
@@ -425,6 +485,14 @@ do { \
be used as the destination of some of the arithmetic ops. There are
also some special purpose registers; the T bit register, the
Procedure Return Register and the Multiply Accumulate Registers. */
+/* Place GENERAL_REGS after FPUL_REGS so that it will be preferred by
+ reg_class_subunion. We don't want to have an actual union class
+ of these, because it would only be used when both classes are calculated
+ to give the same cost, but there is only one FPUL register.
+ Besides, regclass fails to notice the different REGISTER_MOVE_COSTS
+ applying to the actual instruction alternative considered. E.g., the
+ y/r alternative of movsi_ie is considered to have no more cost that
+ the r/r alternative, which is patently untrue. */
enum reg_class
{
@@ -433,7 +501,11 @@ enum reg_class
PR_REGS,
T_REGS,
MAC_REGS,
+ FPUL_REGS,
GENERAL_REGS,
+ FP0_REGS,
+ FP_REGS,
+ GENERAL_FP_REGS,
ALL_REGS,
LIM_REG_CLASSES
};
@@ -448,7 +520,11 @@ enum reg_class
"PR_REGS", \
"T_REGS", \
"MAC_REGS", \
+ "FPUL_REGS", \
"GENERAL_REGS", \
+ "FP0_REGS", \
+ "FP_REGS", \
+ "GENERAL_FP_REGS", \
"ALL_REGS", \
}
@@ -456,15 +532,19 @@ enum reg_class
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
-#define REG_CLASS_CONTENTS \
-{ \
- 0x000000, /* NO_REGS */ \
- 0x000001, /* R0_REGS */ \
- 0x020000, /* PR_REGS */ \
- 0x040000, /* T_REGS */ \
- 0x300000, /* MAC_REGS */ \
- 0x01FFFF, /* GENERAL_REGS */ \
- 0x37FFFF /* ALL_REGS */ \
+#define REG_CLASS_CONTENTS \
+{ \
+ { 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0x00000001, 0x00000000 }, /* R0_REGS */ \
+ { 0x00020000, 0x00000000 }, /* PR_REGS */ \
+ { 0x00040000, 0x00000000 }, /* T_REGS */ \
+ { 0x00300000, 0x00000000 }, /* MAC_REGS */ \
+ { 0x00400000, 0x00000000 }, /* FPUL_REGS */ \
+ { 0x0081FFFF, 0x00000000 }, /* GENERAL_REGS */ \
+ { 0x01000000, 0x00000000 }, /* FP0_REGS */ \
+ { 0xFF000000, 0x000000FF }, /* FP_REGS */ \
+ { 0xFF81FFFF, 0x000000FF }, /* GENERAL_FP_REGS */ \
+ { 0xFFFFFFFF, 0x000000FF }, /* ALL_REGS */ \
}
/* The same information, inverted:
@@ -473,17 +553,22 @@ enum reg_class
or could index an array. */
extern int regno_reg_class[];
-#define REGNO_REG_CLASS(REGNO) regno_reg_class[REGNO]
+#define REGNO_REG_CLASS(REGNO) regno_reg_class[(REGNO)]
/* When defined, the compiler allows registers explicitly used in the
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
/* The order in which register should be allocated. */
+/* Sometimes FP0_REGS becomes the preferred class of a floating point pseudo,
+ and GENERAL_FP_REGS the alternate class. Since FP0 is likely to be
+ spilled or used otherwise, we better have the FP_REGS allocated first. */
#define REG_ALLOC_ORDER \
- { 1,2,3,7,6,5,4,0,8,9,10,11,12,13,14,15,16,17,18,19,20,21 }
+ { 25,26,27,28,29,30,31,24,32,33,34,35,36,37,38,39, \
+ 1,2,3,7,6,5,4,0,8,9,10,11,12,13,14, \
+ 22,15,16,17,18,19,20,21,23 }
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS R0_REGS
@@ -523,14 +608,40 @@ extern enum reg_class reg_class_from_letter[];
/* 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) 0
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
+((C) == 'G' ? fp_zero_operand (VALUE) \
+ : (C) == 'H' ? fp_one_operand (VALUE) \
+ : (C) == 'F')
/* 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. */
-#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
+#define PREFERRED_RELOAD_CLASS(X, CLASS) (CLASS)
+
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS,MODE,X) \
+ ((((((CLASS) == FP_REGS || (CLASS) == FP0_REGS) \
+ && (GET_CODE (X) == REG && REGNO (X) <= AP_REG)) \
+ || (((CLASS) == GENERAL_REGS || (CLASS) == R0_REGS) \
+ && GET_CODE (X) == REG \
+ && REGNO (X) >= FIRST_FP_REG && REGNO (X) <= LAST_FP_REG)) \
+ && MODE == SFmode) \
+ ? FPUL_REGS \
+ : ((CLASS) == FPUL_REGS \
+ && (GET_CODE (X) == MEM \
+ || GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER))\
+ ? GENERAL_REGS \
+ : (((CLASS) == MAC_REGS || (CLASS) == PR_REGS) \
+ && GET_CODE (X) == REG && REGNO (X) > 15 \
+ && (CLASS) != REGNO_REG_CLASS (REGNO (X))) \
+ ? GENERAL_REGS : NO_REGS)
+
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS,MODE,X) \
+ ((((CLASS) == FP_REGS || (CLASS) == FP0_REGS) \
+ && immediate_operand ((X), (MODE)) \
+ && ! (fp_zero_operand (X) || fp_one_operand (X))) \
+ ? R0_REGS : SECONDARY_OUTPUT_RELOAD_CLASS((CLASS),(MODE),(X)))
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
@@ -542,11 +653,19 @@ extern enum reg_class reg_class_from_letter[];
/* Stack layout; function entry, exit and calling. */
/* Define the number of registers that can hold parameters.
- These three macros are used only in other macro definitions below. */
-#define NPARM_REGS 4
+ These macros are used only in other macro definitions below. */
+
+#define NPARM_REGS(MODE) \
+ (TARGET_SH3E && (MODE) == SFmode \
+ ? 8 \
+ : 4)
+
#define FIRST_PARM_REG 4
#define FIRST_RET_REG 0
+#define FIRST_FP_PARM_REG (FIRST_FP_REG + 4)
+#define FIRST_FP_RET_REG FIRST_FP_REG
+
/* Define this if pushing a word on the stack
makes the stack pointer a smaller address. */
#define STACK_GROWS_DOWNWARD
@@ -563,7 +682,12 @@ extern enum reg_class reg_class_from_letter[];
/* If we generate an insn to push BYTES bytes,
this says how many the stack pointer really advances by. */
+/* Don't define PUSH_ROUNDING, since the hardware doesn't do this.
+ When PUSH_ROUNDING is not defined, PARM_BOUNDARY will cause gcc to
+ do correct alignment. */
+#if 0
#define PUSH_ROUNDING(NPUSHED) (((NPUSHED) + 3) & ~3)
+#endif
/* Offset of first parameter from the argument pointer register value. */
#define FIRST_PARM_OFFSET(FNDECL) 0
@@ -579,26 +703,40 @@ extern enum reg_class reg_class_from_letter[];
on the stack. */
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
+/* Some subroutine macros specific to this machine. */
+
+#define BASE_RETURN_VALUE_REG(MODE) \
+ ((TARGET_SH3E && ((MODE) == SFmode)) \
+ ? FIRST_FP_RET_REG \
+ : FIRST_RET_REG)
+
+#define BASE_ARG_REG(MODE) \
+ ((TARGET_SH3E && ((MODE) == SFmode)) \
+ ? FIRST_FP_PARM_REG \
+ : FIRST_PARM_REG)
+
/* 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. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx (REG, TYPE_MODE (VALTYPE), FIRST_RET_REG)
-
+ LIBCALL_VALUE (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, FIRST_RET_REG)
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, (MODE), BASE_RETURN_VALUE_REG (MODE));
-/* 1 if N is a possible register number for a function value.
- On the SH, only r0 can return results. */
-#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RET_REG)
+/* 1 if N is a possible register number for a function value. */
+#define FUNCTION_VALUE_REGNO_P(REGNO) \
+ ((REGNO) == FIRST_RET_REG || (TARGET_SH3E && (REGNO) == FIRST_FP_RET_REG))
/* 1 if N is a possible register number for function argument passing. */
-
#define FUNCTION_ARG_REGNO_P(REGNO) \
- ((REGNO) >= FIRST_PARM_REG && (REGNO) < (NPARM_REGS + FIRST_PARM_REG))
+ (((REGNO) >= FIRST_PARM_REG && (REGNO) < (FIRST_PARM_REG + 4)) \
+ || (TARGET_SH3E \
+ && (REGNO) >= FIRST_FP_PARM_REG && (REGNO) < (FIRST_FP_PARM_REG + 8)))
/* Define a data type for recording info about an argument list
during the scan of that argument list. This data type should
@@ -611,10 +749,18 @@ extern enum reg_class reg_class_from_letter[];
if any, which holds the structure-value-address).
Thus NARGREGS or more means all following args should go on the stack. */
-#define CUMULATIVE_ARGS int
+enum sh_arg_class { SH_ARG_INT = 0, SH_ARG_FLOAT = 1 };
+struct sh_args {
+ int arg_count[2];
+};
+
+#define CUMULATIVE_ARGS struct sh_args
+
+#define GET_SH_ARG_CLASS(MODE) \
+ ((TARGET_SH3E && ((MODE) == SFmode)) ? SH_ARG_FLOAT : SH_ARG_INT)
#define ROUND_ADVANCE(SIZE) \
- ((SIZE + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+ (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* Round a register number up to a proper boundary for an arg of mode
MODE.
@@ -622,20 +768,25 @@ extern enum reg_class reg_class_from_letter[];
The SH doesn't care about double alignment, so we only
round doubles to even regs when asked to explicitly. */
-#define ROUND_REG(X, MODE) \
- ((TARGET_ALIGN_DOUBLE \
- && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD) \
- ? ((X) + ((X) & 1)) : (X))
+#define ROUND_REG(CUM, MODE) \
+ ((TARGET_ALIGN_DOUBLE \
+ && GET_MODE_UNIT_SIZE ((MODE)) > UNITS_PER_WORD) \
+ ? ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \
+ + ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] & 1)) \
+ : (CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)])
/* 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.
On SH, the offset always starts at 0: the first parm reg is always
- the same reg. */
+ the same reg for a given argument class. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME) \
- ((CUM) = 0)
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
+ do { \
+ (CUM).arg_count[(int) SH_ARG_INT] = 0; \
+ (CUM).arg_count[(int) SH_ARG_FLOAT] = 0; \
+ } while (0)
/* Update the data in CUM to advance over an argument
of mode MODE and data type TYPE.
@@ -643,11 +794,27 @@ extern enum reg_class reg_class_from_letter[];
available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- ((CUM) = (ROUND_REG ((CUM), (MODE)) \
+ ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] = \
+ (ROUND_REG ((CUM), (MODE)) \
+ ((MODE) != BLKmode \
? ROUND_ADVANCE (GET_MODE_SIZE (MODE)) \
: ROUND_ADVANCE (int_size_in_bytes (TYPE)))))
+/* Return boolean indicating arg of mode MODE will be passed in a reg.
+ This macro is only used in this file. */
+
+#define PASS_IN_REG_P(CUM, MODE, TYPE) \
+ (((TYPE) == 0 || ! TREE_ADDRESSABLE ((tree)(TYPE))) \
+ && (TARGET_SH3E \
+ ? ((MODE) == BLKmode \
+ ? (((CUM).arg_count[(int) SH_ARG_INT] * UNITS_PER_WORD \
+ + int_size_in_bytes (TYPE)) \
+ <= NPARM_REGS (SImode) * UNITS_PER_WORD) \
+ : ((ROUND_REG((CUM), (MODE)) \
+ + HARD_REGNO_NREGS (BASE_ARG_REG (MODE), (MODE))) \
+ <= NPARM_REGS (MODE))) \
+ : ROUND_REG ((CUM), (MODE)) < NPARM_REGS (MODE)))
+
/* Define where to put the arguments to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
@@ -667,9 +834,11 @@ extern enum reg_class reg_class_from_letter[];
its data type forbids. */
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- sh_function_arg (CUM, MODE, TYPE, NAMED)
-
-extern struct rtx_def *sh_function_arg();
+ ((PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \
+ && ((NAMED) || TARGET_SH3E)) \
+ ? gen_rtx (REG, (MODE), \
+ (BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE)))) \
+ : 0)
/* For an arg passed partly in registers and partly in memory,
this is the number of registers used.
@@ -678,7 +847,15 @@ extern struct rtx_def *sh_function_arg();
We sometimes split args. */
#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- sh_function_arg_partial_nregs (CUM, MODE, TYPE, NAMED)
+ ((PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \
+ && ((NAMED) || TARGET_SH3E) \
+ && (ROUND_REG ((CUM), (MODE)) \
+ + (MODE != BLKmode \
+ ? ROUND_ADVANCE (GET_MODE_SIZE (MODE)) \
+ : ROUND_ADVANCE (int_size_in_bytes (TYPE))) \
+ - NPARM_REGS (MODE) > 0)) \
+ ? NPARM_REGS (MODE) - ROUND_REG ((CUM), (MODE)) \
+ : 0)
extern int current_function_anonymous_args;
@@ -688,15 +865,25 @@ extern int current_function_anonymous_args;
#define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST) \
current_function_anonymous_args = 1;
-/* Call the function profiler with a given profile label. */
+/* Call the function profiler with a given profile label.
+ We use two .aligns, so as to make sure that both the .long is aligned
+ on a 4 byte boundary, and that the .long is a fixed distance (2 bytes)
+ from the trapa instruction. */
#define FUNCTION_PROFILER(STREAM,LABELNO) \
{ \
- fprintf(STREAM, " trapa #5\n"); \
- fprintf(STREAM, " .align 2\n"); \
- fprintf(STREAM, " .long LP%d\n", (LABELNO)); \
+ fprintf((STREAM), "\t.align\t2\n"); \
+ fprintf((STREAM), "\ttrapa\t#33\n"); \
+ fprintf((STREAM), "\t.align\t2\n"); \
+ asm_fprintf((STREAM), "\t.long\t%LLP%d\n", (LABELNO)); \
}
+/* Define this macro if the code for function profiling should come
+ before the function prologue. Normally, the profiling code comes
+ after. */
+
+#define PROFILE_BEFORE_PROLOGUE
+
/* 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.
@@ -707,33 +894,23 @@ extern int current_function_anonymous_args;
/* Generate the assembly code for function exit
Just dump out any accumulated constant table. */
-#define FUNCTION_EPILOGUE(STREAM, SIZE) function_epilogue (STREAM, SIZE)
-
-/* Output assembler code for a block containing the constant parts
- of a trampoline, leaving space for the variable parts.
+#define FUNCTION_EPILOGUE(STREAM, SIZE) function_epilogue ((STREAM), (SIZE))
+/*
On the SH, the trampoline looks like
- 1 0000 D301 mov.l l1,r3
2 0002 DD02 mov.l l2,r13
+ 1 0000 D301 mov.l l1,r3
3 0004 4D2B jmp @r13
- 4 0006 200B or r0,r0
+ 4 0006 0009 nop
5 0008 00000000 l1: .long function
6 000c 00000000 l2: .long area */
-#define TRAMPOLINE_TEMPLATE(FILE) \
-{ \
- fprintf ((FILE), " .word 0xd301\n"); \
- fprintf ((FILE), " .word 0xdd02\n"); \
- fprintf ((FILE), " .word 0x4d2b\n"); \
- fprintf ((FILE), " .word 0x200b\n"); \
- fprintf ((FILE), " .long 0\n"); \
- fprintf ((FILE), " .long 0\n"); \
-}
/* Length in units of the trampoline for entering a nested function. */
#define TRAMPOLINE_SIZE 16
-/* Alignment required for a trampoline in units. */
-#define TRAMPOLINE_ALIGN 4
+/* Alignment required for a trampoline in bits . */
+#define TRAMPOLINE_ALIGNMENT \
+ ((CACHE_LOG < 3 || TARGET_SMALLCODE) ? 32 : 64) \
/* Emit RTL insns to initialize the variable parts of a trampoline.
FNADDR is an RTX for the address of the function's pure code.
@@ -741,11 +918,30 @@ extern int current_function_anonymous_args;
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
{ \
+ emit_move_insn (gen_rtx (MEM, SImode, (TRAMP)), \
+ GEN_INT (TARGET_LITTLE_ENDIAN ? 0xd301dd02 : 0xdd02d301));\
+ emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 4)), \
+ GEN_INT (TARGET_LITTLE_ENDIAN ? 0x00094d2b : 0x4d2b0009));\
emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
(CXT)); \
emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
(FNADDR)); \
}
+
+/* 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 already the frame pointer of the COUNT frame, so we
+ can ignore COUNT. */
+
+#define RETURN_ADDR_RTX(COUNT, FRAME) \
+ (((COUNT) == 0) \
+ ? gen_rtx (MEM, Pmode, gen_rtx (REG, Pmode, RETURN_ADDRESS_POINTER_REGNUM)) \
+ : (rtx) 0)
+
+/* Generate necessary RTL for __builtin_saveregs().
+ ARGLIST is the argument list; see expr.c. */
+extern struct rtx_def *sh_builtin_saveregs ();
+#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) sh_builtin_saveregs (ARGLIST)
/* Addressing modes, and classification of registers for them. */
#define HAVE_POST_INCREMENT 1
@@ -777,11 +973,10 @@ extern int current_function_anonymous_args;
/* Nonzero if the constant value X is a legitimate general operand. */
-/* ??? Should modify this to accept CONST_DOUBLE, and then modify the
- constant pool table code to fix loads of CONST_DOUBLEs. If that doesn't
- work well, then we can at least handle simple CONST_DOUBLEs here
- such as 0.0. */
-#define LEGITIMATE_CONSTANT_P(X) (GET_CODE(X) != CONST_DOUBLE)
+#define LEGITIMATE_CONSTANT_P(X) \
+ (GET_CODE (X) != CONST_DOUBLE \
+ || GET_MODE (X) == DFmode || GET_MODE (X) == SFmode \
+ || (TARGET_SH3E && (fp_zero_operand (X) || fp_one_operand (X))))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
@@ -790,9 +985,6 @@ extern int current_function_anonymous_args;
them unless they have been allocated suitable hard regs.
The symbol REG_OK_STRICT causes the latter definition to be used. */
-#define MODE_DISP_OK_4(X,MODE) ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<64) && (!(INTVAL(X) &3)))
-#define MODE_DISP_OK_8(X,MODE) ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) && (!(INTVAL(X) &3)))
-
#ifndef REG_OK_STRICT
/* Nonzero if X is a hard reg that can be used as a base reg
@@ -822,18 +1014,18 @@ extern int current_function_anonymous_args;
/* Nonzero if X/OFFSET is a hard reg that can be used as an index. */
#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
- (REGNO_OK_FOR_INDEX_P (REGNO (X)) && OFFSET == 0)
+ (REGNO_OK_FOR_INDEX_P (REGNO (X)) && (OFFSET) == 0)
#endif
/* The 'Q' constraint is a pc relative load operand. */
#define EXTRA_CONSTRAINT_Q(OP) \
(GET_CODE (OP) == MEM && \
- ((GET_CODE (XEXP (OP, 0)) == LABEL_REF) \
- || (GET_CODE (XEXP (OP, 0)) == CONST \
- && GET_CODE (XEXP (XEXP (OP, 0), 0)) == PLUS \
- && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 0)) == LABEL_REF \
- && GET_CODE (XEXP (XEXP (XEXP (OP, 0), 0), 1)) == CONST_INT)))
+ ((GET_CODE (XEXP ((OP), 0)) == LABEL_REF) \
+ || (GET_CODE (XEXP ((OP), 0)) == CONST \
+ && GET_CODE (XEXP (XEXP ((OP), 0), 0)) == PLUS \
+ && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 0)) == LABEL_REF \
+ && GET_CODE (XEXP (XEXP (XEXP ((OP), 0), 0), 1)) == CONST_INT)))
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'Q' ? EXTRA_CONSTRAINT_Q (OP) \
@@ -846,6 +1038,11 @@ extern int current_function_anonymous_args;
The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */
+#define MODE_DISP_OK_4(X,MODE) \
+(GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
+ && ! (INTVAL (X) & 3) && ! (TARGET_SH3E && (MODE) == SFmode))
+#define MODE_DISP_OK_8(X,MODE) ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) && (!(INTVAL(X) &3)))
+
#define BASE_REGISTER_RTX_P(X) \
((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|| (GET_CODE (X) == SUBREG \
@@ -871,6 +1068,11 @@ extern int current_function_anonymous_args;
REG++
--REG */
+/* ??? The SH3e does not have the REG+disp addressing mode when loading values
+ into the FRx registers. We implement this by setting the maximum offset
+ to zero when the value is SFmode. This also restricts loading of SFmode
+ values into the integer registers, but that can't be helped. */
+
/* The SH allows a displacement in a QI or HI amode, but only when the
other operand is R0. GCC doesn't handle this very well, so we forgo
all of that.
@@ -882,8 +1084,8 @@ extern int current_function_anonymous_args;
do { \
if (GET_CODE (OP) == CONST_INT) \
{ \
- if (MODE_DISP_OK_4 (OP, MODE)) goto LABEL; \
- if (MODE_DISP_OK_8 (OP, MODE)) goto LABEL; \
+ if (MODE_DISP_OK_4 ((OP), (MODE))) goto LABEL; \
+ if (MODE_DISP_OK_8 ((OP), (MODE))) goto LABEL; \
} \
} while(0)
@@ -892,14 +1094,14 @@ extern int current_function_anonymous_args;
if (BASE_REGISTER_RTX_P (X)) \
goto LABEL; \
else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \
- && BASE_REGISTER_RTX_P (XEXP (X, 0))) \
+ && BASE_REGISTER_RTX_P (XEXP ((X), 0))) \
goto LABEL; \
- else if (GET_CODE (X) == PLUS) \
+ else if (GET_CODE (X) == PLUS && MODE != PSImode) \
{ \
- rtx xop0 = XEXP (X, 0); \
- rtx xop1 = XEXP (X, 1); \
+ rtx xop0 = XEXP ((X), 0); \
+ rtx xop1 = XEXP ((X), 1); \
if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0)) \
- GO_IF_LEGITIMATE_INDEX (MODE, xop1, LABEL); \
+ GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL); \
if (GET_MODE_SIZE (MODE) <= 4) \
{ \
if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
@@ -921,12 +1123,61 @@ extern int current_function_anonymous_args;
GO_IF_LEGITIMATE_ADDRESS.
It is always safe for this macro to do nothing. It exists to recognize
- opportunities to optimize the output. */
+ opportunities to optimize the output.
+
+ For the SH, if X is almost suitable for indexing, but the offset is
+ out of range, convert it into a normal form so that cse has a chance
+ of reducing the number of address registers used. */
-#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) ;
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+{ \
+ if (GET_CODE (X) == PLUS \
+ && (GET_MODE_SIZE (MODE) == 4 \
+ || GET_MODE_SIZE (MODE) == 8) \
+ && GET_CODE (XEXP ((X), 1)) == CONST_INT \
+ && BASE_REGISTER_RTX_P (XEXP ((X), 0)) \
+ && ! (TARGET_SH3E && (MODE) == SFmode)) \
+ { \
+ rtx index_rtx = XEXP ((X), 1); \
+ HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base; \
+ rtx sum; \
+ \
+ GO_IF_LEGITIMATE_INDEX ((MODE), index_rtx, WIN); \
+ /* On rare occasions, we might get an unaligned pointer \
+ that is indexed in a way to give an aligned address. \
+ Therefore, keep the lower two bits in offset_base. */ \
+ /* Instead of offset_base 128..131 use 124..127, so that \
+ simple add suffices. */ \
+ if (offset > 127) \
+ { \
+ offset_base = ((offset + 4) & ~60) - 4; \
+ } \
+ else \
+ offset_base = offset & ~60; \
+ /* Sometimes the normal form does not suit DImode. We \
+ could avoid that by using smaller ranges, but that \
+ would give less optimized code when SImode is \
+ prevalent. */ \
+ if (GET_MODE_SIZE (MODE) + offset - offset_base <= 64) \
+ { \
+ sum = expand_binop (Pmode, add_optab, XEXP ((X), 0), \
+ GEN_INT (offset_base), NULL_RTX, 0, \
+ OPTAB_LIB_WIDEN); \
+ \
+ (X) = gen_rtx (PLUS, Pmode, sum, GEN_INT (offset - offset_base)); \
+ goto WIN; \
+ } \
+ } \
+}
/* Go to LABEL if ADDR (a legitimate address expression)
- has an effect that depends on the machine mode it is used for. */
+ has an effect that depends on the machine mode it is used for.
+
+ ??? Strictly speaking, we should also include all indexed addressing,
+ because the index scale factor is the length of the operand.
+ However, the impact of GO_IF_MODE_DEPENDENT_ADDRESS would be to
+ high if we did that. So we rely on reload to fix things up. */
+
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) \
{ \
if (GET_CODE(ADDR) == PRE_DEC || GET_CODE(ADDR) == POST_INC) \
@@ -948,6 +1199,10 @@ extern int current_function_anonymous_args;
/* This is the kind of divide that is easiest to do in the general case. */
#define EASY_DIV_EXPR TRUNC_DIV_EXPR
+/* Since the SH3e has only `float' support, it is desirable to make all
+ floating point types equivalent to `float'. */
+#define DOUBLE_TYPE_SIZE (TARGET_SH3E ? 32 : 64)
+
/* 'char' is signed by default. */
#define DEFAULT_SIGNED_CHAR 1
@@ -974,6 +1229,9 @@ extern int current_function_anonymous_args;
done, NIL if none. */
#define LOAD_EXTEND_OP(MODE) SIGN_EXTEND
+/* Define if loading short immediate values into registers sign extends. */
+#define SHORT_IMMEDIATES_SIGN_EXTEND
+
/* Define this if zero-extension is slow (more than one real instruction).
On the SH, it's only one instruction. */
/* #define SLOW_ZERO_EXTEND */
@@ -991,14 +1249,11 @@ extern int current_function_anonymous_args;
that the native compiler puts too large (> 32) immediate shift counts
into a register and shifts by the register, letting the SH decide what
to do instead of doing that itself. */
-/* ??? This is defined, but the library routines in lib1funcs.asm do not
- truncate the shift count. This may result in incorrect results for
- unusual cases. Truncating the shift counts in the library routines would
- make them faster. However, the SH3 has hardware shifts that do not
- truncate, so it appears that we need to leave this undefined for correct
- SH3 code. We can still using truncation in the library routines though to
- make them faster. */
-#define SHIFT_COUNT_TRUNCATED 1
+/* ??? The library routines in lib1funcs.asm truncate the shift count.
+ However, the SH3 has hardware shifts that do not truncate exactly as gcc
+ expects - the sign bit is significant - so it appears that we need to
+ leave this zero for correct SH3 code. */
+#define SHIFT_COUNT_TRUNCATED (! TARGET_SH3)
/* All integers have the same format so truncation is easy. */
#define TRULY_NOOP_TRUNCATION(OUTPREC,INPREC) 1
@@ -1025,7 +1280,7 @@ extern int current_function_anonymous_args;
return 0; \
else if (CONST_OK_FOR_I (INTVAL (RTX))) \
return 1; \
- else if ((OUTER_CODE == AND || OUTER_CODE == IOR || OUTER_CODE == XOR) \
+ else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \
&& CONST_OK_FOR_L (INTVAL (RTX))) \
return 1; \
else \
@@ -1083,14 +1338,21 @@ extern int current_function_anonymous_args;
&& GET_CODE (PATTERN (X)) != CLOBBER \
&& get_attr_type (X) == TYPE_SFUNC))
-/* Compute extra cost of moving data between one register class
- and another.
+/* Compute the cost of an address. For the SH, all valid addresses are
+ the same cost. */
+/* ??? Perhaps we should make reg+reg addresses have higher cost because
+ they add to register pressure on r0. */
+
+#define ADDRESS_COST(RTX) 1
- On the SH it is hard to move into the T reg, but simple to load
- from it. */
+/* Compute extra cost of moving data between one register class
+ and another. */
#define REGISTER_MOVE_COST(SRCCLASS, DSTCLASS) \
- (((DSTCLASS == T_REGS) || (DSTCLASS == PR_REG)) ? 10 : 1)
+ ((DSTCLASS) == PR_REG ? 10 \
+ : (((DSTCLASS) == FP_REGS && (SRCCLASS) == GENERAL_REGS) \
+ || ((DSTCLASS) == GENERAL_REGS && (SRCCLASS) == FP_REGS)) ? 4 \
+ : 1)
/* ??? Perhaps make MEMORY_MOVE_COST depend on compiler option? This
would be so that people would slow memory systems could generate
@@ -1098,11 +1360,14 @@ extern int current_function_anonymous_args;
/* Assembler output control. */
+/* 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 "!"
+
/* The text to go at the start of the assembler file. */
-#define ASM_FILE_START(STREAM) \
- output_file_start (STREAM, f_options, \
- sizeof f_options / sizeof f_options[0], \
- W_options, sizeof W_options / sizeof W_options[0]);
+#define ASM_FILE_START(STREAM) \
+ output_file_start (STREAM)
#define ASM_FILE_END(STREAM)
@@ -1110,6 +1375,7 @@ extern int current_function_anonymous_args;
#define ASM_APP_OFF ""
#define FILE_ASM_OP "\t.file\n"
#define IDENT_ASM_OP "\t.ident\n"
+#define SET_ASM_OP ".set"
/* How to change between sections. */
@@ -1138,19 +1404,23 @@ dtors_section() \
} \
}
+/* Define this so that jump tables go in same section as the current function,
+ which could be text or it could be a user defined section. */
+#define JUMP_TABLES_IN_TEXT_SECTION
+
/* 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. */
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
do { fprintf (FILE, ".section\t%s\n", NAME); } while (0)
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
- do { ctors_section(); fprintf(FILE,"\t.long\t_%s\n", NAME); } while (0)
+ do { ctors_section(); asm_fprintf((FILE),"\t.long\t%U%s\n", (NAME)); } while (0)
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
- do { dtors_section(); fprintf(FILE,"\t.long\t_%s\n", NAME); } while (0)
+ do { dtors_section(); asm_fprintf((FILE),"\t.long\t%U%s\n", (NAME)); } while (0)
#undef DO_GLOBAL_CTORS_BODY
@@ -1180,10 +1450,10 @@ dtors_section() \
}
#define ASM_OUTPUT_REG_PUSH(file, v) \
- fprintf (file, "\tmov.l r%s,-@r15\n", v);
+ fprintf ((file), "\tmov.l\tr%s,-@r15\n", (v));
#define ASM_OUTPUT_REG_POP(file, v) \
- fprintf (file, "\tmov.l @r15+,r%s\n", v);
+ fprintf ((file), "\tmov.l\t@r15+,r%s\n", (v));
/* The assembler's names for the registers. RFP need not always be used as
the Real framepointer; it can also be used as a normal general register.
@@ -1193,15 +1463,20 @@ dtors_section() \
{ \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
- "ap", "pr", "t", "gbr", "mach","macl" \
+ "ap", "pr", "t", "gbr", "mach","macl", "fpul","rap", \
+ "fr0","fr1","fr2", "fr3", "fr4", "fr5", "fr6", "fr7", \
+ "fr8","fr9","fr10","fr11","fr12","fr13","fr14","fr15",\
}
/* DBX register number for a given compiler register number. */
-#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
+/* GDB has FPUL at 23 and FP0 at 25, so we must add one to all FP registers
+ to match gdb. */
+#define DBX_REGISTER_NUMBER(REGNO) \
+ (((REGNO) >= 22 && (REGNO) <= 39) ? ((REGNO) + 1) : (REGNO))
/* Output a label definition. */
#define ASM_OUTPUT_LABEL(FILE,NAME) \
- do { assemble_name (FILE, NAME); fputs (":\n", FILE); } while (0)
+ do { assemble_name ((FILE), (NAME)); fputs (":\n", (FILE)); } while (0)
/* This is how to output an assembler line
that says to advance the location counter
@@ -1209,29 +1484,33 @@ dtors_section() \
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
if ((LOG) != 0) \
- fprintf (FILE, "\t.align %d\n", LOG)
+ fprintf ((FILE), "\t.align %d\n", (LOG))
/* Output a function label definition. */
#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL) \
- ASM_OUTPUT_LABEL(STREAM, NAME)
+ ASM_OUTPUT_LABEL((STREAM), (NAME))
/* Output a globalising directive for a label. */
#define ASM_GLOBALIZE_LABEL(STREAM,NAME) \
- (fprintf (STREAM, "\t.global\t"), \
- assemble_name (STREAM, NAME), \
- fputc ('\n',STREAM))
+ (fprintf ((STREAM), "\t.global\t"), \
+ assemble_name ((STREAM), (NAME)), \
+ fputc ('\n', (STREAM)))
-/* Output a reference to a label. */
-#define ASM_OUTPUT_LABELREF(STREAM,NAME) \
- fprintf (STREAM, "_%s", NAME)
+/* The prefix to add to user-visible assembler symbols. */
+
+#define USER_LABEL_PREFIX "_"
+
+/* The prefix to add to an internally generated label. */
+
+#define LOCAL_LABEL_PREFIX ""
/* Make an internal label into a string. */
#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
- sprintf (STRING, "*%s%d", PREFIX, NUM)
+ sprintf ((STRING), "*%s%s%d", LOCAL_LABEL_PREFIX, (PREFIX), (NUM))
/* Output an internal label definition. */
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
- fprintf (FILE, "%s%d:\n", PREFIX, NUM)
+ asm_fprintf ((FILE), "%L%s%d:\n", (PREFIX), (NUM))
/* #define ASM_OUTPUT_CASE_END(STREAM,NUM,TABLE) */
@@ -1242,23 +1521,31 @@ dtors_section() \
/* Jump tables must be 32 bit aligned, no matter the size of the element. */
#define ASM_OUTPUT_CASE_LABEL(STREAM,PREFIX,NUM,TABLE) \
- fprintf (STREAM, "\t.align 2\n%s%d:\n", PREFIX, NUM);
+ fprintf ((STREAM), "\t.align 2\n%s%d:\n", (PREFIX), (NUM));
/* Output a relative address table. */
#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM,VALUE,REL) \
- if (TARGET_BIGTABLE) \
- fprintf (STREAM, "\t.long L%d-L%d\n", VALUE,REL); \
- else \
- fprintf (STREAM, "\t.word L%d-L%d\n", VALUE,REL); \
+ switch (sh_addr_diff_vec_mode) \
+ { \
+ case SImode: \
+ asm_fprintf ((STREAM), "\t.long\t%LL%d-%LL%d\n", (VALUE),(REL)); \
+ break; \
+ case HImode: \
+ asm_fprintf ((STREAM), "\t.word\t%LL%d-%LL%d\n", (VALUE),(REL)); \
+ break; \
+ case QImode: \
+ asm_fprintf ((STREAM), "\t.byte\t%LL%d-%LL%d\n", (VALUE),(REL)); \
+ break; \
+ }
/* Output an absolute table element. */
#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE) \
if (TARGET_BIGTABLE) \
- fprintf (STREAM, "\t.long L%d\n", VALUE); \
+ asm_fprintf ((STREAM), "\t.long\t%LL%d\n", (VALUE)); \
else \
- fprintf (STREAM, "\t.word L%d\n", VALUE); \
+ asm_fprintf ((STREAM), "\t.word\t%LL%d\n", (VALUE)); \
/* Output various types of constants. */
@@ -1267,39 +1554,46 @@ dtors_section() \
#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
do { char dstr[30]; \
REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
- fprintf (FILE, "\t.double %s\n", dstr); \
+ fprintf ((FILE), "\t.double %s\n", dstr); \
} while (0)
/* This is how to output an assembler line defining a `float' constant. */
#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
do { char dstr[30]; \
REAL_VALUE_TO_DECIMAL ((VALUE), "%.20e", dstr); \
- fprintf (FILE, "\t.float %s\n", dstr); \
+ fprintf ((FILE), "\t.float %s\n", dstr); \
} while (0)
-#define ASM_OUTPUT_INT(STREAM, EXP) \
- (fprintf (STREAM, "\t.long\t"), \
- output_addr_const (STREAM, (EXP)), \
- fputc ('\n', STREAM))
+#define ASM_OUTPUT_INT(STREAM, EXP) \
+ (fprintf ((STREAM), "\t.long\t"), \
+ output_addr_const ((STREAM), (EXP)), \
+ fputc ('\n', (STREAM)))
#define ASM_OUTPUT_SHORT(STREAM, EXP) \
- (fprintf (STREAM, "\t.short\t"), \
- output_addr_const (STREAM, (EXP)), \
- fputc ('\n', STREAM))
+ (fprintf ((STREAM), "\t.short\t"), \
+ output_addr_const ((STREAM), (EXP)), \
+ fputc ('\n', (STREAM)))
-#define ASM_OUTPUT_CHAR(STREAM, EXP) \
- (fprintf (STREAM, "\t.byte\t"), \
- output_addr_const (STREAM, (EXP)), \
- fputc ('\n', STREAM))
+#define ASM_OUTPUT_CHAR(STREAM, EXP) \
+ (fprintf ((STREAM), "\t.byte\t"), \
+ output_addr_const ((STREAM), (EXP)), \
+ fputc ('\n', (STREAM)))
#define ASM_OUTPUT_BYTE(STREAM, VALUE) \
- fprintf (STREAM, "\t.byte\t%d\n", VALUE) \
+ fprintf ((STREAM), "\t.byte\t%d\n", (VALUE)) \
+
+/* The next two are used for debug info when compiling with -gdwarf. */
+#define UNALIGNED_SHORT_ASM_OP ".uaword"
+#define UNALIGNED_INT_ASM_OP ".ualong"
+
+/* Loop alignment is now done in machine_dependent_reorg, so that
+ branch shortening can know about it. */
/* This is how to output an assembler line
that says to advance the location counter by SIZE bytes. */
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\t.space %d\n", (SIZE))
+ fprintf ((FILE), "\t.space %d\n", (SIZE))
/* This says how to output an assembler line
to define a global common symbol. */
@@ -1312,7 +1606,7 @@ do { char dstr[30]; \
/* This says how to output an assembler line
to define a local common symbol. */
-#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE,ROUNDED) \
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
( fputs ("\t.lcomm ", (FILE)), \
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%d\n", (SIZE)))
@@ -1330,23 +1624,33 @@ do { char dstr[30]; \
#define TARGET_FF 014
#define TARGET_CR 015
-/* Only perform branch elimination (by making instructions conditional) if
- we're optimizing. Otherwise it's of no use anyway. */
+/* A C statement to be executed just prior to the output of
+ assembler code for INSN, to modify the extracted operands so
+ they will be output differently.
+
+ Here the argument OPVEC is the vector containing the operands
+ extracted from INSN, and NOPERANDS is the number of elements of
+ the vector which contain meaningful data for this insn.
+ The contents of this vector are what will be used to convert the insn
+ template into assembler code, so you can change the assembler output
+ by changing the contents of the vector. */
+
#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
- final_prescan_insn (INSN, OPVEC, NOPERANDS)
+ final_prescan_insn ((INSN), (OPVEC), (NOPERANDS))
/* 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(STREAM, X, CODE) print_operand (STREAM, X, CODE)
+#define PRINT_OPERAND(STREAM, X, CODE) print_operand ((STREAM), (X), (CODE))
/* Print a memory address as an operand to reference that memory location. */
-#define PRINT_OPERAND_ADDRESS(STREAM,X) print_operand_address (STREAM, X)
+#define PRINT_OPERAND_ADDRESS(STREAM,X) print_operand_address ((STREAM), (X))
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
- ((CHAR)=='.' || (CHAR) == '#' || (CHAR)=='@')
+ ((CHAR) == '.' || (CHAR) == '#' || (CHAR) == '@' || (CHAR) == ',' \
+ || (CHAR) == '$')
extern struct rtx_def *sh_compare_op0;
extern struct rtx_def *sh_compare_op1;
@@ -1356,64 +1660,130 @@ extern struct rtx_def *prepare_scc_operands();
match exactly the cpu attribute in the sh.md file. */
enum processor_type {
- PROCESSOR_SH0,
PROCESSOR_SH1,
PROCESSOR_SH2,
- PROCESSOR_SH3
+ PROCESSOR_SH3,
+ PROCESSOR_SH3E
};
#define sh_cpu_attr ((enum attr_cpu)sh_cpu)
extern enum processor_type sh_cpu;
+extern enum machine_mode sh_addr_diff_vec_mode;
+
+extern int optimize; /* needed for gen_casesi, and addr_diff_vec_adjust. */
+
/* Declare functions defined in sh.c and used in templates. */
extern char *output_branch();
+extern char *output_ieee_ccmpeq();
+extern char *output_branchy_insn();
extern char *output_shift();
extern char *output_movedouble();
extern char *output_movepcrel();
extern char *output_jump_label_table();
extern char *output_far_jump();
+enum mdep_reorg_phase_e
+{
+ SH_BEFORE_MDEP_REORG,
+ SH_INSERT_USES_LABELS,
+ SH_SHORTEN_BRANCHES0,
+ SH_FIXUP_PCLOAD,
+ SH_SHORTEN_BRANCHES1,
+ SH_AFTER_MDEP_REORG
+};
+
+void machine_dependent_reorg ();
+int short_cbranch_p ();
+int med_branch_p ();
+int braf_branch_p ();
+int align_length ();
+int addr_diff_vec_adjust ();
+struct rtx_def *sfunc_uses_reg ();
+
#define MACHINE_DEPENDENT_REORG(X) machine_dependent_reorg(X)
/* Generate calls to memcpy, memcmp and memset. */
#define TARGET_MEM_FUNCTIONS
-#define HANDLE_PRAGMA(finput) return handle_pragma (finput)
+/* Define this macro if you want to implement any pragmas. If defined, it
+ is a C expression to be executed when #pragma is seen. The
+ argument FILE is the stdio input stream from which the source
+ text can be read. CH is the first character after the #pragma. The
+ result of the expression is the terminating character found
+ (newline or EOF). */
+#define HANDLE_PRAGMA(FILE, NODE) handle_pragma ((FILE), (NODE))
/* Set when processing a function with pragma interrupt turned on. */
extern int pragma_interrupt;
+/* Set to an RTX containing the address of the stack to switch to
+ for interrupt functions. */
+extern struct rtx_def *sp_switch;
+
+/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+ is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+extern int sh_valid_machine_decl_attribute ();
+#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+sh_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+
+
#define MOVE_RATIO (TARGET_SMALLCODE ? 2 : 16)
/* Instructions with unfilled delay slots take up an extra two bytes for
- the nop in the delay slot. */
+ the nop in the delay slot. Instructions at the start of loops, or
+ after unconditional branches, may take up extra room when they are
+ aligned. ??? We would get more accurate results if we did instruction
+ alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
+ here is too conservative. */
#define ADJUST_INSN_LENGTH(X, LENGTH) \
if (((GET_CODE (X) == INSN \
- && GET_CODE (PATTERN (X)) != SEQUENCE \
&& GET_CODE (PATTERN (X)) != USE \
&& GET_CODE (PATTERN (X)) != CLOBBER) \
|| GET_CODE (X) == CALL_INSN \
|| (GET_CODE (X) == JUMP_INSN \
&& GET_CODE (PATTERN (X)) != ADDR_DIFF_VEC \
&& GET_CODE (PATTERN (X)) != ADDR_VEC)) \
+ && GET_CODE (PATTERN (NEXT_INSN (PREV_INSN (X)))) != SEQUENCE \
&& get_attr_needs_delay_slot (X) == NEEDS_DELAY_SLOT_YES) \
- LENGTH += 2;
+ (LENGTH) += 2; \
+ if (GET_CODE (X) == INSN \
+ && GET_CODE (PATTERN (X)) == UNSPEC_VOLATILE \
+ && XINT (PATTERN (X), 1) == 7) \
+ (LENGTH) -= addr_diff_vec_adjust (X, LENGTH); \
+ if (GET_CODE (X) == INSN \
+ && GET_CODE (PATTERN (X)) == UNSPEC_VOLATILE \
+ && XINT (PATTERN (X), 1) == 1) \
+ (LENGTH) = align_length (X); \
+ if (GET_CODE (X) == JUMP_INSN \
+ && GET_CODE (PATTERN (X)) == ADDR_DIFF_VEC) \
+ { \
+ /* The code before an ADDR_DIFF_VEC is even aligned, \
+ thus any odd estimate is wrong. */ \
+ (LENGTH) &= ~1; \
+ /* If not optimizing, the alignment is implicit. */ \
+ if (! optimize) \
+ (LENGTH) += 2; \
+ }
/* Enable a bug fix for the shorten_branches pass. */
#define SHORTEN_WITH_ADJUST_INSN_LENGTH
/* Define the codes that are matched by predicates in sh.c. */
#define PREDICATE_CODES \
- {"arith_reg_operand", {SUBREG, REG}}, \
{"arith_operand", {SUBREG, REG, CONST_INT}}, \
+ {"arith_reg_operand", {SUBREG, REG}}, \
{"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
- {"logical_operand", {SUBREG, REG, CONST_INT}}, \
+ {"braf_label_ref_operand", {LABEL_REF}}, \
{"general_movsrc_operand", {SUBREG, REG, CONST_INT, MEM}}, \
- {"general_movdst_operand", {SUBREG, REG, CONST_INT, MEM}},
+ {"general_movdst_operand", {SUBREG, REG, CONST_INT, MEM}}, \
+ {"logical_operand", {SUBREG, REG, CONST_INT}}, \
+ {"register_operand", {SUBREG, REG}},
/* 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,
@@ -1427,7 +1797,7 @@ extern int pragma_interrupt;
#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
if (GET_MODE_CLASS (MODE) == MODE_INT \
&& GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
- MODE = SImode;
+ (MODE) = SImode;
/* Defining PROMOTE_FUNCTION_ARGS eliminates some unnecessary zero/sign
extensions applied to char/short functions arguments. Defining
@@ -1442,7 +1812,63 @@ extern int pragma_interrupt;
clear if this would give better code. If implemented, should check for
compatibility problems. */
-/* ??? Define ADJUST_COSTS? */
+/* 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) \
+do { \
+ rtx reg; \
+ \
+ if (GET_CODE(insn) == CALL_INSN) \
+ { \
+ /* The only input for a call that is timing-critical is the \
+ function's address. */ \
+ rtx call = PATTERN (insn); \
+ \
+ if (GET_CODE (call) == PARALLEL) \
+ call = XVECEXP (call, 0 ,0); \
+ if (GET_CODE (call) == SET) \
+ call = SET_SRC (call); \
+ if (GET_CODE (call) == CALL && GET_CODE (XEXP (call, 0)) == MEM \
+ && ! reg_set_p (XEXP (XEXP (call, 0), 0), dep_insn)) \
+ (cost) = 0; \
+ } \
+ /* All sfunc calls are parallels with at least four components. \
+ Exploit this to avoid unnecessary calls to sfunc_uses_reg. */ \
+ else if (GET_CODE (PATTERN (insn)) == PARALLEL \
+ && XVECLEN (PATTERN (insn), 0) >= 4 \
+ && (reg = sfunc_uses_reg (insn))) \
+ { \
+ /* Likewise, the most timing critical input for an sfuncs call \
+ is the function address. However, sfuncs typically start \
+ using their arguments pretty quickly. \
+ Assume a four cycle delay before they are needed. */ \
+ if (! reg_set_p (reg, dep_insn)) \
+ cost -= 4; \
+ } \
+ /* Adjust load_si / pcload_si type insns latency. Use the known \
+ nominal latency and form of the insn to speed up the check. */ \
+ else if (cost == 3 \
+ && GET_CODE (PATTERN (dep_insn)) == SET \
+ /* Latency for dmpy type insns is also 3, so check the that \
+ it's actually a move insn. */ \
+ && general_movsrc_operand (SET_SRC (PATTERN (dep_insn)), SImode))\
+ cost = 2; \
+} while (0) \
+
+/* Since the SH architecture lacks negative address offsets,
+ the givs should be sorted smallest to largest so combine_givs
+ has maximum opportunity to combine givs. */
+#define GIV_SORT_CRITERION(X, Y) \
+ if (GET_CODE ((X)->add_val) == CONST_INT \
+ && GET_CODE ((Y)->add_val) == CONST_INT) \
+ return INTVAL ((X)->add_val) - INTVAL ((Y)->add_val);
/* For the sake of libgcc2.c, indicate target supports atexit. */
#define HAVE_ATEXIT
+
+#define SH_DYNAMIC_SHIFT_COST (TARGET_SH3 ? (TARGET_SMALLCODE ? 1 : 2) : 20)
diff --git a/gnu/usr.bin/gcc/config/sh/sh.md b/gnu/usr.bin/gcc/config/sh/sh.md
index cfe968e9e33..35432aa665d 100644
--- a/gnu/usr.bin/gcc/config/sh/sh.md
+++ b/gnu/usr.bin/gcc/config/sh/sh.md
@@ -1,5 +1,5 @@
;;- Machine description for the Hitachi SH.
-;; Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+;; Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
;; Contributed by Steve Chamberlain (sac@cygnus.com).
;; Improved by Jim Wilson (wilson@cygnus.com).
@@ -29,20 +29,16 @@
;; ??? Should check all DImode patterns for consistency and usefulness.
-;; ??? Should add support for using BSR for short function calls.
-
;; ??? The MAC.W and MAC.L instructions are not supported. There is no
;; way to generate them.
-;; ??? The BSR instruction is not supported. It might be possible to
-;; generate it by keeping track of function sizes (and hence relative
-;; addresses), and then using it only if the target is earlier in the same
-;; file, and is within range. Better would be assembler/linker relaxing,
-;; but that is much harder.
-
;; ??? The cmp/str instruction is not supported. Perhaps it can be used
;; for a str* inline function.
+;; BSR is not generated by the compiler proper, but when relaxing, it
+;; generates .uses pseudo-ops that allow linker relaxation to create
+;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c
+
;; Special constraints for SH machine description:
;;
;; t -- T
@@ -71,78 +67,134 @@
;; Attributes
;; -------------------------------------------------------------------------
-; Target CPU.
+;; Target CPU.
-(define_attr "cpu" "sh0,sh1,sh2,sh3"
+(define_attr "cpu"
+ "sh1,sh2,sh3,sh3e"
(const (symbol_ref "sh_cpu_attr")))
-;;
+(define_attr "endian" "big,little"
+ (const (if_then_else (symbol_ref "TARGET_LITTLE_ENDIAN")
+ (const_string "little") (const_string "big"))))
+
;; cbranch conditional branch instructions
;; jump unconditional jumps
;; arith ordinary arithmetic
+;; arith3 a compound insn that behaves similarly to a sequence of
+;; three insns of type arith
+;; arith3b like above, but might end with a redirected branch
;; load from memory
+;; load_si Likewise, SImode variant for general register.
;; store to memory
;; move register to register
+;; fmove register to register, floating point
;; smpy word precision integer multiply
;; dmpy longword or doublelongword precision integer multiply
;; return rts
;; pload load of pr reg, which can't be put into delay slot of rts
;; pstore store of pr reg, which can't be put into delay slot of jsr
;; pcload pc relative load of constant value
+;; pcload_si Likewise, SImode variant for general register.
;; rte return from exception
;; sfunc special function call with known used registers
;; call function call
+;; fp floating point
+;; fdiv floating point divide (or square root)
+;; gp_fpul move between general purpose register and fpul
+;; nil no-op move, will be deleted.
(define_attr "type"
- "cbranch,jump,arith,other,load,store,move,smpy,dmpy,return,pload,pstore,pcload,rte,sfunc,call"
+ "cbranch,jump,jump_ind,arith,arith3,arith3b,dyn_shift,other,load,load_si,store,move,fmove,smpy,dmpy,return,pload,pstore,pcload,pcload_si,rte,sfunc,call,fp,fdiv,gp_fpul,nil"
(const_string "other"))
; If a conditional branch destination is within -252..258 bytes away
; from the instruction it can be 2 bytes long. Something in the
; range -4090..4100 bytes can be 6 bytes long. All other conditional
-; branches are 16 bytes long.
+; branches are initially assumed to be 16 bytes long.
+; In machine_dependent_reorg, we split all branches that are longer than
+; 2 bytes.
; An unconditional jump in the range -4092..4098 can be 2 bytes long.
-; Otherwise, it must be 14 bytes long.
+; For wider ranges, we need a combination of a code and a data part.
+; If we can get a scratch register for a long range jump, the code
+; part can be 4 bytes long; otherwise, it must be 8 bytes long.
+; If the jump is in the range -32764..32770, the data part can be 2 bytes
+; long; otherwise, it must be 6 bytes long.
; All other instructions are two bytes long by default.
-; All positive offsets have an adjustment added, which is the number of bytes
-; difference between this instruction length and the next larger instruction
-; length. This is because shorten_branches starts with the largest
-; instruction size and then tries to reduce them.
-
(define_attr "length" ""
(cond [(eq_attr "type" "cbranch")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -252))
- (le (minus (match_dup 0) (pc))
- (const_int 262)))
- (const_int 2)
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -4090))
- (le (minus (match_dup 0) (pc))
- (const_int 4110)))
- (const_int 6)
- (const_int 16)))
-
+ (cond [(ne (symbol_ref "short_cbranch_p (insn)") (const_int 0))
+ (const_int 2)
+ (ne (symbol_ref "med_branch_p (insn, 2)") (const_int 0))
+ (const_int 6)
+ (ne (symbol_ref "braf_branch_p (insn, 2)") (const_int 0))
+ (const_int 10)
+ (ne (pc) (pc))
+ (const_int 12)
+ ] (const_int 16))
(eq_attr "type" "jump")
- (if_then_else (and (ge (minus (match_dup 0) (pc))
- (const_int -4092))
- (le (minus (match_dup 0) (pc))
- (const_int 4110)))
- (const_int 2)
- (const_int 14))
+ (cond [(ne (symbol_ref "med_branch_p (insn, 0)") (const_int 0))
+ (const_int 2)
+ (and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")
+ (symbol_ref "INSN"))
+ (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")
+ (symbol_ref "code_for_indirect_jump_scratch")))
+ (if_then_else (ne (symbol_ref "braf_branch_p (insn, 0)")
+ (const_int 0))
+ (const_int 6)
+ (const_int 10))
+ (ne (symbol_ref "braf_branch_p (insn, 0)") (const_int 0))
+ (const_int 10)
+ (ne (pc) (pc))
+ (const_int 12)
+ ] (const_int 14))
] (const_int 2)))
;; (define_function_unit {name} {num-units} {n-users} {test}
;; {ready-delay} {issue-delay} [{conflict-list}])
-;; ??? These are probably not correct.
-(define_function_unit "memory" 1 0 (eq_attr "type" "load,pcload,pload") 2 2)
+;; Load and store instructions save a cycle if they are aligned on a
+;; four byte boundary. Using a function unit for stores encourages
+;; gcc to separate load and store instructions by one instruction,
+;; which makes it more likely that the linker will be able to word
+;; align them when relaxing.
+
+;; Loads have a latency of two.
+;; However, call insn can have ;; a delay slot, so that we want one more
+;; insn to be scheduled between the load of the function address and the call.
+;; This is equivalent to a latency of three.
+;; We cannot use a conflict list for this, because we need to distinguish
+;; between the actual call address and the function arguments.
+;; ADJUST_COST can only properly handle reductions of the cost, so we
+;; use a latency of three here.
+;; We only do this for SImode loads of general registers, to make the work
+;; for ADJUST_COST easier.
+(define_function_unit "memory" 1 0
+ (eq_attr "type" "load_si,pcload_si")
+ 3 2)
+(define_function_unit "memory" 1 0
+ (eq_attr "type" "load,pcload,pload,store,pstore")
+ 2 2)
+
+(define_function_unit "int" 1 0
+ (eq_attr "type" "arith3,arith3b") 3 3)
+
+(define_function_unit "int" 1 0
+ (eq_attr "type" "dyn_shift") 2 2)
+
+(define_function_unit "int" 1 0
+ (eq_attr "type" "arith,arith3b,dyn_shift") 2 2)
+
+;; ??? These are approximations.
(define_function_unit "mpy" 1 0 (eq_attr "type" "smpy") 2 2)
(define_function_unit "mpy" 1 0 (eq_attr "type" "dmpy") 3 3)
+(define_function_unit "fp" 1 0 (eq_attr "type" "fp,fmove") 2 1)
+(define_function_unit "fp" 1 0 (eq_attr "type" "fdiv") 13 12)
+
+
; Definitions for filling branch delay slots.
(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
@@ -154,7 +206,7 @@
(define_attr "in_delay_slot" "yes,no"
(cond [(eq_attr "type" "cbranch") (const_string "no")
- (eq_attr "type" "pcload") (const_string "no")
+ (eq_attr "type" "pcload,pcload_si") (const_string "no")
(eq_attr "needs_delay_slot" "yes") (const_string "no")
(eq_attr "length" "2") (const_string "yes")
] (const_string "no")))
@@ -190,14 +242,9 @@
;; Say that we have annulled true branches, since this gives smaller and
;; faster code when branches are predicted as not taken.
-;; ??? Branches which are out-of-range actually have two delay slots,
-;; the first is either always executed or else annulled false, and the
-;; second is always annulled false. Handling these differently from
-;; in range branches would give better code.
-
(define_delay
(and (eq_attr "type" "cbranch")
- (eq_attr "cpu" "sh2,sh3"))
+ (ne (symbol_ref "TARGET_SH2") (const_int 0)))
[(eq_attr "in_delay_slot" "yes") (eq_attr "in_delay_slot" "yes") (nil)])
;; -------------------------------------------------------------------------
@@ -205,17 +252,6 @@
;; -------------------------------------------------------------------------
(define_insn ""
- [(set (match_operand:SI 0 "arith_reg_operand" "=r")
- (eq:SI (reg:SI 18)
- (const_int 1)))]
- ""
- "movt %0")
-
-;; ??? This combiner pattern does not work, because combine does not combine
-;; instructions that set a hard register when SMALL_REGISTER_CLASSES is
-;; defined. Perhaps use a pseudo-reg for the T bit?
-
-(define_insn ""
[(set (reg:SI 18)
(eq:SI (and:SI (match_operand:SI 0 "arith_reg_operand" "z,r")
(match_operand:SI 1 "arith_operand" "L,r"))
@@ -285,6 +321,93 @@
}")
;; -------------------------------------------------------------------------
+;; DImode signed integer comparisons
+;; -------------------------------------------------------------------------
+
+;; ??? Could get better scheduling by splitting the initial test from the
+;; rest of the insn after reload. However, the gain would hardly justify
+;; the sh.md size increase necessary to do that.
+
+(define_insn ""
+ [(set (reg:SI 18)
+ (eq:SI (and:DI (match_operand:DI 0 "arith_reg_operand" "r")
+ (match_operand:DI 1 "arith_operand" "r"))
+ (const_int 0)))]
+ ""
+ "* return output_branchy_insn (EQ, \"tst\\t%S1,%S0\;bf\\t%l9\;tst\\t%R1,%R0\",
+ insn, operands);"
+ [(set_attr "length" "6")
+ (set_attr "type" "arith3b")])
+
+(define_insn "cmpeqdi_t"
+ [(set (reg:SI 18) (eq:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
+ (match_operand:DI 1 "arith_reg_or_0_operand" "N,r")))]
+ ""
+ "*
+ return output_branchy_insn
+ (EQ,
+ (which_alternative
+ ? \"cmp/eq\\t%S1,%S0\;bf\\t%l9\;cmp/eq\\t%R1,%R0\"
+ : \"tst\\t%S0,%S0\;bf\\t%l9\;tst\\t%R0,%R0\"),
+ insn, operands);"
+ [(set_attr "length" "6")
+ (set_attr "type" "arith3b")])
+
+(define_insn "cmpgtdi_t"
+ [(set (reg:SI 18) (gt:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
+ (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
+ "TARGET_SH2"
+ "@
+ cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/gt\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:
+ tst\\t%S0,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/pl\\t%S0\;cmp/hi\\t%S0,%R0\\n%,Ldi%=:"
+ [(set_attr "length" "8")
+ (set_attr "type" "arith3")])
+
+(define_insn "cmpgedi_t"
+ [(set (reg:SI 18) (ge:SI (match_operand:DI 0 "arith_reg_operand" "r,r")
+ (match_operand:DI 1 "arith_reg_or_0_operand" "r,N")))]
+ "TARGET_SH2"
+ "@
+ cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/ge\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:
+ cmp/pz\\t%S0"
+ [(set_attr "length" "8,2")
+ (set_attr "type" "arith3,arith")])
+
+;; -------------------------------------------------------------------------
+;; DImode unsigned integer comparisons
+;; -------------------------------------------------------------------------
+
+(define_insn "cmpgeudi_t"
+ [(set (reg:SI 18) (geu:SI (match_operand:DI 0 "arith_reg_operand" "r")
+ (match_operand:DI 1 "arith_reg_operand" "r")))]
+ "TARGET_SH2"
+ "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hs\\t%S1,%S0\;cmp/hs\\t%R1,%R0\\n%,Ldi%=:"
+ [(set_attr "length" "8")
+ (set_attr "type" "arith3")])
+
+(define_insn "cmpgtudi_t"
+ [(set (reg:SI 18) (gtu:SI (match_operand:DI 0 "arith_reg_operand" "r")
+ (match_operand:DI 1 "arith_reg_operand" "r")))]
+ "TARGET_SH2"
+ "cmp/eq\\t%S1,%S0\;bf{.|/}s\\t%,Ldi%=\;cmp/hi\\t%S1,%S0\;cmp/hi\\t%R1,%R0\\n%,Ldi%=:"
+ [(set_attr "length" "8")
+ (set_attr "type" "arith3")])
+
+;; We save the compare operands in the cmpxx patterns and use them when
+;; we generate the branch.
+
+(define_expand "cmpdi"
+ [(set (reg:SI 18) (compare (match_operand:DI 0 "arith_operand" "")
+ (match_operand:DI 1 "arith_operand" "")))]
+ "TARGET_SH2"
+ "
+{
+ sh_compare_op0 = operands[0];
+ sh_compare_op1 = operands[1];
+ DONE;
+}")
+
+;; -------------------------------------------------------------------------
;; Addition instructions
;; -------------------------------------------------------------------------
@@ -296,9 +419,50 @@
(match_operand:DI 2 "arith_reg_operand" "r")))
(clobber (reg:SI 18))]
""
- "clrt\;addc %R2,%R0\;addc %S2,%S0"
+ "#"
[(set_attr "length" "6")])
+(define_split
+ [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+ (plus:DI (match_operand:DI 1 "arith_reg_operand" "%0")
+ (match_operand:DI 2 "arith_reg_operand" "r")))
+ (clobber (reg:SI 18))]
+ "reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
+ high0 = gen_rtx (REG, SImode,
+ true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
+ high2 = gen_rtx (REG, SImode,
+ true_regnum (operands[2]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
+ emit_insn (gen_clrt ());
+ emit_insn (gen_addc (low0, low0, gen_lowpart (SImode, operands[2])));
+ emit_insn (gen_addc1 (high0, high0, high2));
+ DONE;
+}")
+
+(define_insn "addc"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (match_operand:SI 2 "arith_reg_operand" "r"))
+ (reg:SI 18)))
+ (set (reg:SI 18)
+ (ltu:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
+ ""
+ "addc %2,%0"
+ [(set_attr "type" "arith")])
+
+(define_insn "addc1"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (match_operand:SI 2 "arith_reg_operand" "r"))
+ (reg:SI 18)))
+ (clobber (reg:SI 18))]
+ ""
+ "addc %2,%0"
+ [(set_attr "type" "arith")])
+
(define_insn "addsi3"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(plus:SI (match_operand:SI 1 "arith_operand" "%0")
@@ -319,16 +483,77 @@
(match_operand:DI 2 "arith_reg_operand" "r")))
(clobber (reg:SI 18))]
""
- "clrt\;subc %R2,%R0\;subc %S2,%S0"
+ "#"
[(set_attr "length" "6")])
-(define_insn "subsi3"
+(define_split
+ [(set (match_operand:DI 0 "arith_reg_operand" "=r")
+ (minus:DI (match_operand:DI 1 "arith_reg_operand" "0")
+ (match_operand:DI 2 "arith_reg_operand" "r")))
+ (clobber (reg:SI 18))]
+ "reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx high0, high2, low0 = gen_lowpart (SImode, operands[0]);
+ high0 = gen_rtx (REG, SImode,
+ true_regnum (operands[0]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
+ high2 = gen_rtx (REG, SImode,
+ true_regnum (operands[2]) + (TARGET_LITTLE_ENDIAN ? 1 : 0));
+ emit_insn (gen_clrt ());
+ emit_insn (gen_subc (low0, low0, gen_lowpart (SImode, operands[2])));
+ emit_insn (gen_subc1 (high0, high0, high2));
+ DONE;
+}")
+
+(define_insn "subc"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (match_operand:SI 2 "arith_reg_operand" "r"))
+ (reg:SI 18)))
+ (set (reg:SI 18)
+ (gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
+ ""
+ "subc %2,%0"
+ [(set_attr "type" "arith")])
+
+(define_insn "subc1"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (match_operand:SI 2 "arith_reg_operand" "r"))
+ (reg:SI 18)))
+ (clobber (reg:SI 18))]
+ ""
+ "subc %2,%0"
+ [(set_attr "type" "arith")])
+
+(define_insn "*subsi3_internal"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(minus:SI (match_operand:SI 1 "arith_reg_operand" "0")
(match_operand:SI 2 "arith_reg_operand" "r")))]
""
"sub %2,%0"
[(set_attr "type" "arith")])
+
+;; Convert `constant - reg' to `neg rX; add rX, #const' since this
+;; will sometimes save one instruction. Otherwise we might get
+;; `mov #const, rY; sub rY,rX; mov rX, rY' if the source and dest regs
+;; are the same.
+
+(define_expand "subsi3"
+ [(set (match_operand:SI 0 "arith_reg_operand" "")
+ (minus:SI (match_operand:SI 1 "arith_operand" "")
+ (match_operand:SI 2 "arith_reg_operand" "")))]
+ ""
+ "
+{
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ emit_insn (gen_negsi2 (operands[0], operands[2]));
+ emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
+ DONE;
+ }
+}")
;; -------------------------------------------------------------------------
;; Division instructions
@@ -337,6 +562,17 @@
;; We take advantage of the library routines which don't clobber as many
;; registers as a normal function call would.
+;; The INSN_REFERENCES_ARE_DELAYED in sh.h is problematic because it
+;; also has an effect on the register that holds the address of the sfunc.
+;; To make this work, we have an extra dummy insns that shows the use
+;; of this register for reorg.
+
+(define_insn "use_sfunc_addr"
+ [(set (reg:SI 17) (unspec [(match_operand:SI 0 "register_operand" "r")] 5))]
+ ""
+ ""
+ [(set_attr "length" "0")])
+
;; We must use a pseudo-reg forced to reg 0 in the SET_DEST rather than
;; hard register 0. If we used hard register 0, then the next instruction
;; would be a move from hard register 0 to a pseudo-reg. If the pseudo-reg
@@ -346,14 +582,14 @@
;; If we let reload allocate r0, then this problem can never happen.
(define_insn ""
- [(set (match_operand:SI 1 "register_operand" "=z")
+ [(set (match_operand:SI 0 "register_operand" "=z")
(udiv:SI (reg:SI 4) (reg:SI 5)))
(clobber (reg:SI 18))
(clobber (reg:SI 17))
(clobber (reg:SI 4))
- (use (match_operand:SI 0 "arith_reg_operand" "r"))]
+ (use (match_operand:SI 1 "arith_reg_operand" "r"))]
""
- "jsr @%0%#"
+ "jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
@@ -372,16 +608,16 @@
"operands[3] = gen_reg_rtx(SImode);")
(define_insn ""
- [(set (match_operand:SI 1 "register_operand" "=z")
+ [(set (match_operand:SI 0 "register_operand" "=z")
(div:SI (reg:SI 4) (reg:SI 5)))
(clobber (reg:SI 18))
(clobber (reg:SI 17))
(clobber (reg:SI 1))
(clobber (reg:SI 2))
(clobber (reg:SI 3))
- (use (match_operand:SI 0 "arith_reg_operand" "r"))]
+ (use (match_operand:SI 1 "arith_reg_operand" "r"))]
""
- "jsr @%0%#"
+ "jsr @%1%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
@@ -407,20 +643,20 @@
(define_insn ""
[(set (reg:SI 21)
- (mult:SI (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))
- (zero_extend:SI (match_operand:HI 2 "arith_reg_operand" "r"))))]
+ (mult:SI (zero_extend:SI (match_operand:HI 0 "arith_reg_operand" "r"))
+ (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))))]
""
- "mulu %2,%1"
+ "mulu %1,%0"
[(set_attr "type" "smpy")])
(define_insn ""
[(set (reg:SI 21)
(mult:SI (sign_extend:SI
- (match_operand:HI 1 "arith_reg_operand" "r"))
+ (match_operand:HI 0 "arith_reg_operand" "r"))
(sign_extend:SI
- (match_operand:HI 2 "arith_reg_operand" "r"))))]
+ (match_operand:HI 1 "arith_reg_operand" "r"))))]
""
- "muls %2,%1"
+ "muls %1,%0"
[(set_attr "type" "smpy")])
(define_expand "mulhisi3"
@@ -506,12 +742,12 @@
}
}")
-(define_insn ""
+(define_insn "mulsidi3_i"
[(set (reg:DI 20)
- (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
- (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+ (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+ (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))]
"TARGET_SH2"
- "dmuls.l %2,%1"
+ "dmuls.l %1,%0"
[(set_attr "type" "dmpy")])
(define_expand "mulsidi3"
@@ -521,14 +757,30 @@
(set (match_operand:DI 0 "arith_reg_operand" "")
(reg:DI 20))]
"TARGET_SH2"
- "")
+ "
+{
+ /* We must swap the two words when copying them from MACH/MACL to the
+ output register. */
+ if (TARGET_LITTLE_ENDIAN)
+ {
+ rtx low_dst = operand_subword (operands[0], 0, 1, DImode);
+ rtx high_dst = operand_subword (operands[0], 1, 1, DImode);
-(define_insn ""
+ emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
+
+ emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0]));
+ emit_move_insn (low_dst, gen_rtx (REG, SImode, 21));
+ emit_move_insn (high_dst, gen_rtx (REG, SImode, 20));
+ DONE;
+ }
+}")
+
+(define_insn "umulsidi3_i"
[(set (reg:DI 20)
- (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
- (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+ (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+ (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))]
"TARGET_SH2"
- "dmulu.l %2,%1"
+ "dmulu.l %1,%0"
[(set_attr "type" "dmpy")])
(define_expand "umulsidi3"
@@ -538,17 +790,33 @@
(set (match_operand:DI 0 "arith_reg_operand" "")
(reg:DI 20))]
"TARGET_SH2"
- "")
+ "
+{
+ /* We must swap the two words when copying them from MACH/MACL to the
+ output register. */
+ if (TARGET_LITTLE_ENDIAN)
+ {
+ rtx low_dst = operand_subword (operands[0], 0, 1, DImode);
+ rtx high_dst = operand_subword (operands[0], 1, 1, DImode);
+
+ emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
+
+ emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0]));
+ emit_move_insn (low_dst, gen_rtx (REG, SImode, 21));
+ emit_move_insn (high_dst, gen_rtx (REG, SImode, 20));
+ DONE;
+ }
+}")
(define_insn ""
[(set (reg:SI 20)
(truncate:SI
- (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
- (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))
+ (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+ (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
(const_int 32))))
(clobber (reg:SI 21))]
"TARGET_SH2"
- "dmuls.l %2,%1"
+ "dmuls.l %1,%0"
[(set_attr "type" "dmpy")])
(define_expand "smulsi3_highpart"
@@ -566,12 +834,12 @@
(define_insn ""
[(set (reg:SI 20)
(truncate:SI
- (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
- (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))
+ (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+ (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
(const_int 32))))
(clobber (reg:SI 21))]
"TARGET_SH2"
- "dmulu.l %2,%1"
+ "dmulu.l %1,%0"
[(set_attr "type" "dmpy")])
(define_expand "umulsi3_highpart"
@@ -621,7 +889,8 @@
(ior:SI (match_operand:SI 1 "arith_reg_operand" "%0,0")
(match_operand:SI 2 "logical_operand" "r,L")))]
""
- "or %2,%0")
+ "or %2,%0"
+ [(set_attr "type" "arith")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "arith_reg_operand" "=z,r")
@@ -642,7 +911,8 @@
(set (reg:SI 18)
(lshiftrt:SI (match_dup 1) (const_int 31)))]
""
- "rotl %0")
+ "rotl %0"
+ [(set_attr "type" "arith")])
(define_insn "rotlsi3_31"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
@@ -650,14 +920,16 @@
(const_int 31)))
(clobber (reg:SI 18))]
""
- "rotr %0")
+ "rotr %0"
+ [(set_attr "type" "arith")])
-(define_insn ""
+(define_insn "rotlsi3_16"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(rotate:SI (match_operand:SI 1 "arith_reg_operand" "r")
(const_int 16)))]
""
- "swap.w %1,%0")
+ "swap.w %1,%0"
+ [(set_attr "type" "arith")])
(define_expand "rotlsi3"
[(set (match_operand:SI 0 "arith_reg_operand" "")
@@ -666,29 +938,62 @@
""
"
{
+ static char rot_tab[] = {
+ 000, 000, 000, 000, 000, 000, 010, 001,
+ 001, 001, 011, 013, 003, 003, 003, 003,
+ 003, 003, 003, 003, 003, 013, 012, 002,
+ 002, 002, 010, 000, 000, 000, 000, 000,
+ };
+
+ int count, choice;
+
if (GET_CODE (operands[2]) != CONST_INT)
FAIL;
-
- if (INTVAL (operands[2]) == 1)
- {
- emit_insn (gen_rotlsi3_1 (operands[0], operands[1]));
- DONE;
- }
- else if (INTVAL (operands[2]) == 31)
+ count = INTVAL (operands[2]);
+ choice = rot_tab[count];
+ if (choice & 010 && SH_DYNAMIC_SHIFT_COST <= 1)
+ FAIL;
+ choice &= 7;
+ switch (choice)
{
- emit_insn (gen_rotlsi3_31 (operands[0], operands[1]));
- DONE;
+ case 0:
+ emit_move_insn (operands[0], operands[1]);
+ count -= (count & 16) * 2;
+ break;
+ case 3:
+ emit_insn (gen_rotlsi3_16 (operands[0], operands[1]));
+ count -= 16;
+ break;
+ case 1:
+ case 2:
+ {
+ rtx parts[2];
+ parts[0] = gen_reg_rtx (SImode);
+ parts[1] = gen_reg_rtx (SImode);
+ emit_insn (gen_rotlsi3_16 (parts[2-choice], operands[1]));
+ parts[choice-1] = operands[1];
+ emit_insn (gen_ashlsi3 (parts[0], parts[0], GEN_INT (8)));
+ emit_insn (gen_lshrsi3 (parts[1], parts[1], GEN_INT (8)));
+ emit_insn (gen_iorsi3 (operands[0], parts[0], parts[1]));
+ count = (count & ~16) - 8;
+ }
}
- else if (INTVAL (operands[2]) != 16)
- FAIL;
+
+ for (; count > 0; count--)
+ emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
+ for (; count < 0; count++)
+ emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
+
+ DONE;
}")
-(define_insn ""
+(define_insn "*rotlhi3_8"
[(set (match_operand:HI 0 "arith_reg_operand" "=r")
(rotate:HI (match_operand:HI 1 "arith_reg_operand" "r")
(const_int 8)))]
""
- "swap.b %1,%0")
+ "swap.b %1,%0"
+ [(set_attr "type" "arith")])
(define_expand "rotlhi3"
[(set (match_operand:HI 0 "arith_reg_operand" "")
@@ -709,7 +1014,8 @@
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
(match_operand:SI 2 "arith_reg_operand" "r")))]
"TARGET_SH3"
- "shld %2,%0")
+ "shld %2,%0"
+ [(set_attr "type" "dyn_shift")])
(define_insn "ashlsi3_k"
[(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
@@ -718,14 +1024,25 @@
"CONST_OK_FOR_K (INTVAL (operands[2]))"
"@
add %0,%0
- shll%O2 %0")
+ shll%O2 %0"
+ [(set_attr "type" "arith")])
+
+(define_insn "ashlhi3_k"
+ [(set (match_operand:HI 0 "arith_reg_operand" "=r,r")
+ (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0,0")
+ (match_operand:HI 2 "const_int_operand" "M,K")))]
+ "CONST_OK_FOR_K (INTVAL (operands[2]))"
+ "@
+ add %0,%0
+ shll%O2 %0"
+ [(set_attr "type" "arith")])
(define_insn "ashlsi3_n"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))
(clobber (reg:SI 18))]
- ""
+ "! sh_dynamicalize_shift_p (operands[2])"
"#"
[(set (attr "length")
(cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
@@ -758,6 +1075,9 @@
""
"
{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && sh_dynamicalize_shift_p (operands[2]))
+ operands[2] = force_reg (SImode, operands[2]);
if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
{
emit_insn (gen_ashlsi3_d (operands[0], operands[1], operands[2]));
@@ -767,6 +1087,34 @@
FAIL;
}")
+(define_insn "ashlhi3"
+ [(set (match_operand:HI 0 "arith_reg_operand" "=r")
+ (ashift:HI (match_operand:HI 1 "arith_reg_operand" "0")
+ (match_operand:HI 2 "const_int_operand" "n")))
+ (clobber (reg:SI 18))]
+ ""
+ "#"
+ [(set (attr "length")
+ (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
+ (const_string "2")
+ (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
+ (const_string "4")]
+ (const_string "6")))
+ (set_attr "type" "arith")])
+
+(define_split
+ [(set (match_operand:HI 0 "arith_reg_operand" "")
+ (ashift:HI (match_operand:HI 1 "arith_reg_operand" "")
+ (match_operand:HI 2 "const_int_operand" "n")))
+ (clobber (reg:SI 18))]
+ ""
+ [(use (reg:SI 0))]
+ "
+{
+ gen_shifty_hi_op (ASHIFT, operands);
+ DONE;
+}")
+
;
; arithmetic shift right
;
@@ -780,6 +1128,15 @@
"shar %0"
[(set_attr "type" "arith")])
+(define_insn "ashrhi3_k"
+ [(set (match_operand:HI 0 "arith_reg_operand" "=r")
+ (ashiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0")
+ (match_operand:HI 2 "const_int_operand" "M")))
+ (clobber (reg:SI 18))]
+ "INTVAL (operands[2]) == 1"
+ "shar %0"
+ [(set_attr "type" "arith")])
+
;; ??? This should be a define expand.
(define_insn "ashrsi2_16"
@@ -787,27 +1144,59 @@
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
(const_int 16)))]
""
- "swap.w %1,%0\;exts.w %0,%0"
+ "#"
[(set_attr "length" "4")])
+(define_split
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "r")
+ (const_int 16)))]
+ ""
+ [(set (match_dup 0) (rotate:SI (match_dup 1) (const_int 16)))
+ (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
+ "operands[2] = gen_lowpart (HImode, operands[0]);")
+
;; ??? This should be a define expand.
(define_insn "ashrsi2_31"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
- (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
- (const_int 31)))
+ (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (const_int 31)))
(clobber (reg:SI 18))]
""
- "@
- shll %0\;subc %0,%0"
+ "#"
[(set_attr "length" "4")])
+(define_split
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (const_int 31)))
+ (clobber (reg:SI 18))]
+ ""
+ [(const_int 0)]
+ "
+{
+ emit_insn (gen_ashlsi_c (operands[0], operands[1], operands[1]));
+ emit_insn (gen_subc1 (operands[0], operands[0], operands[0]));
+ DONE;
+}")
+
+(define_insn "ashlsi_c"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") (const_int 1)))
+ (set (reg:SI 18) (lt:SI (match_operand:SI 2 "arith_reg_operand" "0")
+ (const_int 0)))]
+ ""
+ "shll %0"
+ [(set_attr "type" "arith")])
+
(define_insn "ashrsi3_d"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
"TARGET_SH3"
- "shad %2,%1")
+ "shad %2,%0"
+ [(set_attr "type" "dyn_shift")])
(define_insn "ashrsi3_n"
[(set (reg:SI 4)
@@ -836,7 +1225,8 @@
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
"TARGET_SH3"
- "shld %2,%0")
+ "shld %2,%0"
+ [(set_attr "type" "dyn_shift")])
;; Only the single bit shift clobbers the T bit.
@@ -846,7 +1236,8 @@
(match_operand:SI 2 "const_int_operand" "M")))
(clobber (reg:SI 18))]
"CONST_OK_FOR_M (INTVAL (operands[2]))"
- "shlr %0")
+ "shlr %0"
+ [(set_attr "type" "arith")])
(define_insn "lshrsi3_k"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
@@ -854,14 +1245,33 @@
(match_operand:SI 2 "const_int_operand" "K")))]
"CONST_OK_FOR_K (INTVAL (operands[2]))
&& ! CONST_OK_FOR_M (INTVAL (operands[2]))"
- "shlr%O2 %0")
+ "shlr%O2 %0"
+ [(set_attr "type" "arith")])
+
+(define_insn "lshrhi3_m"
+ [(set (match_operand:HI 0 "arith_reg_operand" "=r")
+ (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0")
+ (match_operand:HI 2 "const_int_operand" "M")))
+ (clobber (reg:SI 18))]
+ "CONST_OK_FOR_M (INTVAL (operands[2]))"
+ "shlr %0"
+ [(set_attr "type" "arith")])
+
+(define_insn "lshrhi3_k"
+ [(set (match_operand:HI 0 "arith_reg_operand" "=r")
+ (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0")
+ (match_operand:HI 2 "const_int_operand" "K")))]
+ "CONST_OK_FOR_K (INTVAL (operands[2]))
+ && ! CONST_OK_FOR_M (INTVAL (operands[2]))"
+ "shlr%O2 %0"
+ [(set_attr "type" "arith")])
(define_insn "lshrsi3_n"
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))
(clobber (reg:SI 18))]
- ""
+ "! sh_dynamicalize_shift_p (operands[2])"
"#"
[(set (attr "length")
(cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
@@ -894,17 +1304,49 @@
""
"
{
+ if (GET_CODE (operands[2]) == CONST_INT
+ && sh_dynamicalize_shift_p (operands[2]))
+ operands[2] = force_reg (SImode, operands[2]);
if (TARGET_SH3 && arith_reg_operand (operands[2], GET_MODE (operands[2])))
{
rtx count = copy_to_mode_reg (SImode, operands[2]);
emit_insn (gen_negsi2 (count, count));
- emit_insn (gen_ashlsi3_d (operands[0], operands[1], count));
+ emit_insn (gen_lshrsi3_d (operands[0], operands[1], count));
DONE;
}
if (! immediate_operand (operands[2], GET_MODE (operands[2])))
FAIL;
}")
+(define_insn "lshrhi3"
+ [(set (match_operand:HI 0 "arith_reg_operand" "=r")
+ (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "0")
+ (match_operand:HI 2 "const_int_operand" "n")))
+ (clobber (reg:SI 18))]
+ ""
+ "#"
+;; ??? length attribute is sometimes six instead of four.
+ [(set (attr "length")
+ (cond [(eq (symbol_ref "shift_insns_rtx (insn)") (const_int 1))
+ (const_string "2")
+ (eq (symbol_ref "shift_insns_rtx (insn)") (const_int 2))
+ (const_string "4")]
+ (const_string "6")))
+ (set_attr "type" "arith")])
+
+(define_split
+ [(set (match_operand:HI 0 "arith_reg_operand" "")
+ (lshiftrt:HI (match_operand:HI 1 "arith_reg_operand" "")
+ (match_operand:HI 2 "const_int_operand" "n")))
+ (clobber (reg:SI 18))]
+ ""
+ [(use (reg:SI 0))]
+ "
+{
+ gen_shifty_hi_op (LSHIFTRT, operands);
+ DONE;
+}")
+
;; ??? This should be a define expand.
(define_insn "ashldi3_k"
@@ -914,7 +1356,8 @@
(clobber (reg:SI 18))]
""
"shll %R0\;rotcl %S0"
- [(set_attr "length" "4")])
+ [(set_attr "length" "4")
+ (set_attr "type" "arith")])
(define_expand "ashldi3"
[(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
@@ -934,7 +1377,8 @@
(clobber (reg:SI 18))]
""
"shlr %S0\;rotcr %R0"
- [(set_attr "length" "4")])
+ [(set_attr "length" "4")
+ (set_attr "type" "arith")])
(define_expand "lshrdi3"
[(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
@@ -954,7 +1398,8 @@
(clobber (reg:SI 18))]
""
"shar %S0\;rotcr %R0"
- [(set_attr "length" "4")])
+ [(set_attr "length" "4")
+ (set_attr "type" "arith")])
(define_expand "ashrdi3"
[(parallel [(set (match_operand:DI 0 "arith_reg_operand" "")
@@ -964,6 +1409,214 @@
""
"{ if (GET_CODE (operands[2]) != CONST_INT
|| INTVAL (operands[2]) != 1) FAIL; } ")
+
+;; combined left/right shift
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")))]
+ "(unsigned)INTVAL (operands[2]) < 32"
+ [(use (reg:SI 0))]
+ "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
+ DONE;")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:SI 18))]
+ "(unsigned)INTVAL (operands[2]) < 32"
+ [(use (reg:SI 0))]
+ "if (gen_shl_and (operands[0], operands[2], operands[3], operands[1])) FAIL;
+ DONE;")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:SI 18))]
+ "shl_and_kind (operands[2], operands[3], 0) == 1"
+ "#"
+ [(set (attr "length")
+ (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
+ (const_string "4")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
+ (const_string "6")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
+ (const_string "8")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 5))
+ (const_string "10")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 6))
+ (const_string "12")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 7))
+ (const_string "14")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 8))
+ (const_string "16")]
+ (const_string "18")))
+ (set_attr "type" "arith")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=z")
+ (and:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (clobber (reg:SI 18))]
+ "shl_and_kind (operands[2], operands[3], 0) == 2"
+ "#"
+ [(set (attr "length")
+ (cond [(eq (symbol_ref "shl_and_length (insn)") (const_int 2))
+ (const_string "4")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 3))
+ (const_string "6")
+ (eq (symbol_ref "shl_and_length (insn)") (const_int 4))
+ (const_string "8")]
+ (const_string "10")))
+ (set_attr "type" "arith")])
+
+;; shift left / and combination with a scratch register: The combine pass
+;; does not accept the individual instructions, even though they are
+;; cheap. But it needs a precise description so that it is usable after
+;; reload.
+(define_insn "and_shl_scratch"
+ [(set (match_operand:SI 0 "register_operand" "=r,&r")
+ (lshiftrt:SI (ashift:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
+ (match_operand:SI 2 "const_int_operand" "N,n"))
+ (match_operand:SI 3 "" "0,r"))
+ (match_operand:SI 4 "const_int_operand" "n,n"))
+ (match_operand:SI 5 "const_int_operand" "n,n")))
+ (clobber (reg:SI 18))]
+ ""
+ "#"
+ [(set (attr "length")
+ (cond [(eq (symbol_ref "shl_and_scr_length (insn)") (const_int 2))
+ (const_string "4")
+ (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 3))
+ (const_string "6")
+ (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 4))
+ (const_string "8")
+ (eq (symbol_ref "shl_and_scr_length (insn)") (const_int 5))
+ (const_string "10")]
+ (const_string "12")))
+ (set_attr "type" "arith")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r,&r")
+ (lshiftrt:SI (ashift:SI (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0")
+ (match_operand:SI 2 "const_int_operand" "N,n"))
+ (match_operand:SI 3 "register_operand" "0,r"))
+ (match_operand:SI 4 "const_int_operand" "n,n"))
+ (match_operand:SI 5 "const_int_operand" "n,n")))
+ (clobber (reg:SI 18))]
+ ""
+ [(use (reg:SI 0))]
+ "
+{
+ rtx and_source = operands[rtx_equal_p (operands[0], operands[1]) ? 3 : 1];
+
+ if (INTVAL (operands[2]))
+ {
+ gen_shifty_op (LSHIFTRT, operands);
+ }
+ emit_insn (gen_andsi3 (operands[0], operands[0], and_source));
+ operands[2] = operands[4];
+ gen_shifty_op (ASHIFT, operands);
+ if (INTVAL (operands[5]))
+ {
+ operands[2] = operands[5];
+ gen_shifty_op (LSHIFTRT, operands);
+ }
+ DONE;
+}")
+
+;; signed left/right shift combination.
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:SI 18))]
+ ""
+ [(use (reg:SI 0))]
+ "if (gen_shl_sext (operands[0], operands[2], operands[3], operands[1])) FAIL;
+ DONE;")
+
+(define_insn "shl_sext_ext"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:SI 18))]
+ "(unsigned)shl_sext_kind (operands[2], operands[3], 0) - 1 < 5"
+ "#"
+ [(set (attr "length")
+ (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 1))
+ (const_string "2")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 2))
+ (const_string "4")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
+ (const_string "6")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
+ (const_string "8")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
+ (const_string "10")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
+ (const_string "12")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 7))
+ (const_string "14")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 8))
+ (const_string "16")]
+ (const_string "18")))
+ (set_attr "type" "arith")])
+
+(define_insn "shl_sext_sub"
+ [(set (match_operand:SI 0 "register_operand" "=z")
+ (sign_extract:SI (ashift:SI (match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (match_operand:SI 3 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:SI 18))]
+ "(shl_sext_kind (operands[2], operands[3], 0) & ~1) == 6"
+ "#"
+ [(set (attr "length")
+ (cond [(eq (symbol_ref "shl_sext_length (insn)") (const_int 3))
+ (const_string "6")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 4))
+ (const_string "8")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 5))
+ (const_string "10")
+ (eq (symbol_ref "shl_sext_length (insn)") (const_int 6))
+ (const_string "12")]
+ (const_string "14")))
+ (set_attr "type" "arith")])
+
+;; These patterns are found in expansions of DImode shifts by 16, and
+;; allow the xtrct instruction to be generated from C source.
+
+(define_insn "xtrct_left"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (ior:SI (ashift:SI (match_operand:SI 1 "arith_reg_operand" "r")
+ (const_int 16))
+ (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand" "0")
+ (const_int 16))))]
+ ""
+ "xtrct %1,%0"
+ [(set_attr "type" "arith")])
+
+(define_insn "xtrct_right"
+ [(set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (const_int 16))
+ (ashift:SI (match_operand:SI 2 "arith_reg_operand" "r")
+ (const_int 16))))]
+ ""
+ "xtrct %2,%0"
+ [(set_attr "type" "arith")])
;; -------------------------------------------------------------------------
;; Unary arithmetic
@@ -1048,13 +1701,8 @@
;; ??? This should be a define expand.
;; ??? Or perhaps it should be dropped?
-(define_insn "extendsidi2"
- [(set (match_operand:DI 0 "arith_reg_operand" "=r")
- (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
- (clobber (reg:SI 18))]
- ""
- "mov %1,%S0\;mov %1,%R0\;shll %S0\;subc %S0,%S0"
- [(set_attr "length" "8")])
+/* There is no point in defining extendsidi2; convert_move generates good
+ code for that. */
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "arith_reg_operand" "=r,r")
@@ -1111,6 +1759,28 @@
[(set_attr "type" "load,pload,load")
(set_attr "hit_stack" "yes")])
+(define_insn "push_e"
+ [(set (mem:SF (pre_dec:SI (reg:SI 15)))
+ (match_operand:SF 0 "register_operand" "r,f,y"))]
+ "TARGET_SH3E"
+ "@
+ mov.l %0,@-r15
+ fmov.s %0,@-r15
+ sts.l %0,@-r15"
+ [(set_attr "type" "store")
+ (set_attr "hit_stack" "yes")])
+
+(define_insn "pop_e"
+ [(set (match_operand:SF 0 "register_operand" "=r,f,y")
+ (mem:SF (post_inc:SI (reg:SI 15))))]
+ "TARGET_SH3E"
+ "@
+ mov.l @r15+,%0
+ fmov.s @r15+,%0
+ lds.l @r15+,%0"
+ [(set_attr "type" "load")
+ (set_attr "hit_stack" "yes")])
+
;; These two patterns can happen as the result of optimization, when
;; comparisons get simplified to a move of zero or 1 into the T reg.
;; They don't disappear completely, because the T reg is a fixed hard reg.
@@ -1125,15 +1795,17 @@
""
"sett")
-;; t/z is first, so that it will be preferred over r/r when reloading a move
+;; t/r is first, so that it will be preferred over r/r when reloading a move
;; of a pseudo-reg into the T reg
(define_insn "movsi_i"
- [(set (match_operand:SI 0 "general_movdst_operand" "=t,r,r,r,r,r,m,<,xl,xl,r")
- (match_operand:SI 1 "general_movsrc_operand" "z,Q,rI,m,xl,t,r,xl,r,>,i"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
+ [(set (match_operand:SI 0 "general_movdst_operand" "=t,r,r,r,r,r,m,<,<,xl,x,l,r")
+ (match_operand:SI 1 "general_movsrc_operand" "r,Q,rI,m,xl,t,r,x,l,r,>,>,i"))]
+ "
+ ! TARGET_SH3E
+ && (register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode))"
"@
- tst %1,%1\;rotcl %1\;xor #1,%1\;rotcr %1
+ cmp/pl %1
mov.l %1,%0
mov %1,%0
mov.l %1,%0
@@ -1141,12 +1813,58 @@
movt %0
mov.l %1,%0
sts.l %1,%0
+ sts.l %1,%0
lds %1,%0
lds.l %1,%0
+ lds.l %1,%0
fake %1,%0"
- [(set_attr "type" "move,pcload,move,load,move,store,store,move,load,move,move")
- (set_attr "length" "8,*,*,*,*,*,*,*,*,*,*")])
-
+ [(set_attr "type" "*,pcload_si,move,load_si,move,move,store,store,pstore,move,load,pload,pcload_si")
+ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*")])
+
+;; t/r must come after r/r, lest reload will try to reload stuff like
+;; (subreg:SI (reg:SF 38 fr14) 0) into T (compiling stdlib/strtod.c -m3e -O2)
+;; ??? This allows moves from macl to fpul to be recognized, but these moves
+;; will require a reload.
+(define_insn "movsi_ie"
+ [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,m,<,<,xl,x,l,r,y,r,y")
+ (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,m,xl,t,r,x,l,r,>,>,i,r,y,y"))]
+ "TARGET_SH3E
+ && (register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode))"
+ "@
+ mov.l %1,%0
+ mov %1,%0
+ cmp/pl %1
+ mov.l %1,%0
+ sts %1,%0
+ movt %0
+ mov.l %1,%0
+ sts.l %1,%0
+ sts.l %1,%0
+ lds %1,%0
+ lds.l %1,%0
+ lds.l %1,%0
+ fake %1,%0
+ lds %1,%0
+ sts %1,%0
+ ! move optimized away"
+ [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,pcload_si,gp_fpul,gp_fpul,nil")
+ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
+
+(define_insn "movsi_i_lowpart"
+ [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,r,m,r"))
+ (match_operand:SI 1 "general_movsrc_operand" "Q,rI,m,xl,t,r,i"))]
+ "register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode)"
+ "@
+ mov.l %1,%0
+ mov %1,%0
+ mov.l %1,%0
+ sts %1,%0
+ movt %0
+ mov.l %1,%0
+ fake %1,%0"
+ [(set_attr "type" "pcload,move,load,move,move,store,pcload")])
(define_expand "movsi"
[(set (match_operand:SI 0 "general_movdst_operand" "")
(match_operand:SI 1 "general_movsrc_operand" ""))]
@@ -1187,7 +1905,7 @@
sts %1,%0
lds %1,%0
fake %1,%0"
- [(set_attr "type" "pcload,move,load,move,store,move,move,move")])
+ [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")])
(define_expand "movhi"
[(set (match_operand:HI 0 "general_movdst_operand" "")
@@ -1197,14 +1915,16 @@
;; ??? This should be a define expand.
+;; x/r can be created by inlining/cse, e.g. for execute/961213-1.c
+;; compiled with -m2 -ml -O3 -funroll-loops
(define_insn ""
- [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r")
- (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,i,x"))]
+ [(set (match_operand:DI 0 "general_movdst_operand" "=r,r,r,m,r,r,r,*!x")
+ (match_operand:DI 1 "general_movsrc_operand" "Q,r,m,r,I,i,x,r"))]
"arith_reg_operand (operands[0], DImode)
|| arith_reg_operand (operands[1], DImode)"
"* return output_movedouble (insn, operands, DImode);"
[(set_attr "length" "4")
- (set_attr "type" "pcload,move,load,store,move,move")])
+ (set_attr "type" "pcload,move,load,store,move,pcload,move,move")])
;; If the output is a register and the input is memory or a register, we have
;; to be careful and see which word needs to be loaded first.
@@ -1262,13 +1982,13 @@
;; ??? This should be a define expand.
(define_insn "movdf_k"
- [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,m")
- (match_operand:DF 1 "general_movsrc_operand" "r,m,r"))]
+ [(set (match_operand:DF 0 "general_movdst_operand" "=r,r,r,m")
+ (match_operand:DF 1 "general_movsrc_operand" "r,FQ,m,r"))]
"arith_reg_operand (operands[0], DFmode)
|| arith_reg_operand (operands[1], DFmode)"
"* return output_movedouble (insn, operands, DFmode);"
[(set_attr "length" "4")
- (set_attr "type" "move,load,store")])
+ (set_attr "type" "move,pcload,load,store")])
;; If the output is a register and the input is memory or a register, we have
;; to be careful and see which word needs to be loaded first.
@@ -1317,38 +2037,161 @@
FAIL;
}")
+;; If a base address generated by LEGITIMIZE_ADDRESS for SImode is
+;; used only once, let combine add in the index again.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "" ""))
+ (clobber (match_operand 2 "register_operand" ""))]
+ "! reload_in_progress && ! reload_completed"
+ [(use (reg:SI 0))]
+ "
+{
+ rtx addr, reg, const_int;
+
+ if (GET_CODE (operands[1]) != MEM)
+ FAIL;
+ addr = XEXP (operands[1], 0);
+ if (GET_CODE (addr) != PLUS)
+ FAIL;
+ reg = XEXP (addr, 0);
+ const_int = XEXP (addr, 1);
+ if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT)
+ FAIL;
+ emit_move_insn (operands[2], const_int);
+ emit_move_insn (operands[0],
+ change_address (operands[1], VOIDmode,
+ gen_rtx (PLUS, SImode, reg, operands[2])));
+ DONE;
+}")
+
+(define_split
+ [(set (match_operand:SI 1 "" "")
+ (match_operand:SI 0 "register_operand" ""))
+ (clobber (match_operand 2 "register_operand" ""))]
+ "! reload_in_progress && ! reload_completed"
+ [(use (reg:SI 0))]
+ "
+{
+ rtx addr, reg, const_int;
+
+ if (GET_CODE (operands[1]) != MEM)
+ FAIL;
+ addr = XEXP (operands[1], 0);
+ if (GET_CODE (addr) != PLUS)
+ FAIL;
+ reg = XEXP (addr, 0);
+ const_int = XEXP (addr, 1);
+ if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT)
+ FAIL;
+ emit_move_insn (operands[2], const_int);
+ emit_move_insn (change_address (operands[1], VOIDmode,
+ gen_rtx (PLUS, SImode, reg, operands[2])),
+ operands[0]);
+ DONE;
+}")
+
(define_expand "movdf"
[(set (match_operand:DF 0 "general_movdst_operand" "")
(match_operand:DF 1 "general_movsrc_operand" ""))]
""
- "{ if (prepare_move_operands (operands, DFmode)) DONE; }")
+ "
+{
+ if (prepare_move_operands (operands, DFmode)) DONE;
+}")
+
(define_insn "movsf_i"
- [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,m,l,r")
- (match_operand:SF 1 "general_movsrc_operand" "r,I,m,r,r,l"))]
- "arith_reg_operand (operands[0], SFmode)
- || arith_reg_operand (operands[1], SFmode)"
+ [(set (match_operand:SF 0 "general_movdst_operand" "=r,r,r,r,m,l,r")
+ (match_operand:SF 1 "general_movsrc_operand" "r,I,FQ,m,r,r,l"))]
+ "
+ ! TARGET_SH3E
+ && (arith_reg_operand (operands[0], SFmode)
+ || arith_reg_operand (operands[1], SFmode))"
"@
mov %1,%0
mov %1,%0
mov.l %1,%0
mov.l %1,%0
+ mov.l %1,%0
lds %1,%0
sts %1,%0"
- [(set_attr "type" "move,move,load,store,move,move")])
+ [(set_attr "type" "move,move,pcload,load,store,move,move")])
+
+;; We may not split the ry/yr/XX alternatives to movsi_ie, since
+;; update_flow_info would not know where to put REG_EQUAL notes
+;; when the destination changes mode.
+(define_insn "movsf_ie"
+ [(set (match_operand:SF 0 "general_movdst_operand"
+ "=f,r,f,f,fy,f,m,r,r,m,f,y,y,rf,r,y,y")
+ (match_operand:SF 1 "general_movsrc_operand"
+ "f,r,G,H,FQ,m,f,FQ,m,r,y,f,>,fr,y,r,y"))
+ (clobber (match_scratch:SI 2 "=X,X,X,X,&z,X,X,X,X,X,X,X,X,y,X,X,X"))]
+
+ "TARGET_SH3E
+ && (arith_reg_operand (operands[0], SFmode)
+ || arith_reg_operand (operands[1], SFmode))"
+ "@
+ fmov %1,%0
+ mov %1,%0
+ fldi0 %0
+ fldi1 %0
+ #
+ fmov.s %1,%0
+ fmov.s %1,%0
+ mov.l %1,%0
+ mov.l %1,%0
+ mov.l %1,%0
+ fsts fpul,%0
+ flds %1,fpul
+ lds.l %1,%0
+ #
+ sts %1,%0
+ lds %1,%0
+ ! move optimized away"
+ [(set_attr "type" "fmove,move,fmove,fmove,pcload,load,store,pcload,load,store,fmove,fmove,load,*,gp_fpul,gp_fpul,nil")
+ (set_attr "length" "*,*,*,*,4,*,*,*,*,*,2,2,2,*,2,2,0")])
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (match_operand:SF 1 "register_operand" ""))
+ (clobber (reg:SI 22))]
+ ""
+ [(parallel [(set (reg:SF 22) (match_dup 1))
+ (clobber (scratch:SI))])
+ (parallel [(set (match_dup 0) (reg:SF 22))
+ (clobber (scratch:SI))])]
+ "")
(define_expand "movsf"
[(set (match_operand:SF 0 "general_movdst_operand" "")
- (match_operand:SF 1 "general_movsrc_operand" ""))]
+ (match_operand:SF 1 "general_movsrc_operand" ""))]
+ ""
+ "
+{
+ if (prepare_move_operands (operands, SFmode))
+ DONE;
+ if (TARGET_SH3E)
+ {
+ emit_insn (gen_movsf_ie (operands[0], operands[1]));
+ DONE;
+ }
+}")
+
+(define_expand "reload_insf"
+ [(parallel [(set (match_operand:SF 0 "register_operand" "=f")
+ (match_operand:SF 1 "immediate_operand" "FQ"))
+ (clobber (match_operand:SI 2 "register_operand" "=&z"))])]
""
- "{ if (prepare_move_operands (operands, SFmode)) DONE; }")
+ "")
;; ------------------------------------------------------------------------
;; Define the real conditional branch instructions.
;; ------------------------------------------------------------------------
(define_insn "branch_true"
- [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 1))
+ [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
@@ -1356,122 +2199,150 @@
[(set_attr "type" "cbranch")])
(define_insn "branch_false"
- [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 1))
+ [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return output_branch (0, insn, operands);"
[(set_attr "type" "cbranch")])
-(define_insn "inverse_branch_true"
- [(set (pc) (if_then_else (eq (reg:SI 18) (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+;; Patterns to prevent reorg from re-combining a condbranch with a branch
+;; which destination is too far away.
+;; The const_int_operand is distinct for each branch target; it avoids
+;; unwanted matches with redundant_insn.
+(define_insn "block_branch_redirect"
+ [(set (pc) (unspec [(match_operand 0 "const_int_operand" "")] 4))]
""
- "* return output_branch (0, insn, operands);"
- [(set_attr "type" "cbranch")])
+ ""
+ [(set_attr "length" "0")])
-(define_insn "inverse_branch_false"
- [(set (pc) (if_then_else (ne (reg:SI 18) (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+;; This one has the additional purpose to record a possible scratch register
+;; for the following branch.
+(define_insn "indirect_jump_scratch"
+ [(set (match_operand 0 "register_operand" "r")
+ (unspec [(match_operand 1 "const_int_operand" "")] 4))]
""
- "* return output_branch (1, insn, operands);"
- [(set_attr "type" "cbranch")])
+ ""
+ [(set_attr "length" "0")])
;; Conditional branch insns
(define_expand "beq"
- [(set (reg:SI 18) (eq:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
+ [(set (pc)
+ (if_then_else (ne (reg:SI 18) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"from_compare (operands, EQ);")
-; There is no bne compare, so we reverse the branch arms.
-
(define_expand "bne"
- [(set (reg:SI 18) (eq:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+ [(set (pc)
+ (if_then_else (eq (reg:SI 18) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
- "from_compare (operands, NE);")
+ "from_compare (operands, EQ);")
(define_expand "bgt"
- [(set (reg:SI 18) (gt:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
+ [(set (pc)
+ (if_then_else (ne (reg:SI 18) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"from_compare (operands, GT);")
(define_expand "blt"
- [(set (reg:SI 18) (ge:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+ [(set (pc)
+ (if_then_else (eq (reg:SI 18) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
- "from_compare (operands, LT);")
+ "
+{
+ if (GET_MODE (sh_compare_op0) == SFmode)
+ {
+ rtx tmp = sh_compare_op0;
+ sh_compare_op0 = sh_compare_op1;
+ sh_compare_op1 = tmp;
+ emit_insn (gen_bgt (operands[0]));
+ DONE;
+ }
+ from_compare (operands, GE);
+}")
(define_expand "ble"
- [(set (reg:SI 18) (gt:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+ [(set (pc)
+ (if_then_else (eq (reg:SI 18) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
- "from_compare (operands, LE);")
+ "
+{
+ if (TARGET_SH3E
+ && TARGET_IEEE
+ && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
+ {
+ rtx tmp = sh_compare_op0;
+ sh_compare_op0 = sh_compare_op1;
+ sh_compare_op1 = tmp;
+ emit_insn (gen_bge (operands[0]));
+ DONE;
+ }
+ from_compare (operands, GT);
+}")
(define_expand "bge"
- [(set (reg:SI 18) (ge:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
+ [(set (pc)
+ (if_then_else (ne (reg:SI 18) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
- "from_compare (operands, GE);")
+ "
+{
+ if (TARGET_SH3E
+ && ! TARGET_IEEE
+ && GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
+ {
+ rtx tmp = sh_compare_op0;
+ sh_compare_op0 = sh_compare_op1;
+ sh_compare_op1 = tmp;
+ emit_insn (gen_ble (operands[0]));
+ DONE;
+ }
+ from_compare (operands, GE);
+}")
(define_expand "bgtu"
- [(set (reg:SI 18) (gtu:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
+ [(set (pc)
+ (if_then_else (ne (reg:SI 18) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"from_compare (operands, GTU); ")
(define_expand "bltu"
- [(set (reg:SI 18) (geu:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+ [(set (pc)
+ (if_then_else (eq (reg:SI 18) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
- "from_compare (operands, LTU);")
+ "from_compare (operands, GEU);")
(define_expand "bgeu"
- [(set (reg:SI 18) (geu:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
+ [(set (pc)
+ (if_then_else (ne (reg:SI 18) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"from_compare (operands, GEU);")
(define_expand "bleu"
- [(set (reg:SI 18) (gtu:SI (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (eq (reg:SI 18) (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
+ [(set (pc)
+ (if_then_else (eq (reg:SI 18) (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
""
- "from_compare (operands, LEU);")
+ "from_compare (operands, GTU);")
;; ------------------------------------------------------------------------
;; Jump and linkage insns
@@ -1484,7 +2355,7 @@
"*
{
/* The length is 16 if the delay slot is unfilled. */
- if (get_attr_length(insn) >= 14)
+ if (get_attr_length(insn) > 4)
return output_far_jump(insn, operands[0]);
else
return \"bra %l0%#\";
@@ -1531,40 +2402,98 @@
(match_operand:SI 0 "arith_reg_operand" "r"))]
""
"jmp @%0%#"
- [(set_attr "needs_delay_slot" "yes")])
+ [(set_attr "needs_delay_slot" "yes")
+ (set_attr "type" "jump_ind")])
+
+;; The use of operand 1 / 2 helps us distinguish case table jumps
+;; which can be present in structured code from indirect jumps which can not
+;; be present in structured code. This allows -fprofile-arcs to work.
+
+;; For SH1 processors.
+(define_insn "casesi_jump_1"
+ [(set (pc)
+ (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "jmp @%0%#"
+ [(set_attr "needs_delay_slot" "yes")
+ (set_attr "type" "jump_ind")])
+
+;; For all later processors.
+(define_insn "casesi_jump_2"
+ [(set (pc) (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand 1 "braf_label_ref_operand" "")))
+ (use (label_ref (match_operand 2 "" "")))]
+ ""
+ "braf %0%#"
+ [(set_attr "needs_delay_slot" "yes")
+ (set_attr "type" "jump_ind")])
+
+(define_insn "dummy_jump"
+ [(set (pc) (const_int 0))]
+ ""
+ ""
+ [(set_attr "length" "0")])
+
+;; Call subroutine returning any type.
+;; ??? This probably doesn't work.
+
+(define_expand "untyped_call"
+ [(parallel [(call (match_operand 0 "" "")
+ (const_int 0))
+ (match_operand 1 "" "")
+ (match_operand 2 "" "")])]
+ "TARGET_SH3E"
+ "
+{
+ int i;
+
+ emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx, const0_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;
+}")
;; ------------------------------------------------------------------------
;; Misc insns
;; ------------------------------------------------------------------------
-;; ??? This combiner pattern does not work, because combine does not combine
-;; instructions that set a hard register when SMALL_REGISTER_CLASSES is
-;; defined. Perhaps use a pseudo-reg for the T bit?
-
(define_insn "dect"
- [(parallel [(set (match_operand:SI 0 "arith_reg_operand" "=r")
- (plus:SI (match_dup 0)
- (const_int -1)))
- (set (reg:SI 18)
- (eq:SI (plus:SI (match_dup 0) (const_int -1))
- (const_int 0)))])]
+ [(set (reg:SI 18)
+ (eq:SI (match_operand:SI 0 "arith_reg_operand" "+r") (const_int 1)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
"TARGET_SH2"
- "dt %0")
+ "dt %0"
+ [(set_attr "type" "arith")])
(define_insn "nop"
[(const_int 0)]
""
"nop")
-;; Load address of a label. This is only generated by the casesi expand.
-;; This must use unspec, because this only works immediately before a casesi.
+;; Load address of a label. This is only generated by the casesi expand,
+;; and by machine_dependent_reorg (fixing up fp moves).
+;; This must use unspec, because this only works for labels that are
+;; within range,
(define_insn "mova"
[(set (reg:SI 0)
(unspec [(label_ref (match_operand 0 "" ""))] 1))]
""
"mova %O0,r0"
- [(set_attr "in_delay_slot" "no")])
+ [(set_attr "in_delay_slot" "no")
+ (set_attr "type" "arith")])
;; case instruction for switch statements.
@@ -1574,55 +2503,157 @@
;; operand 3 is CODE_LABEL for the table;
;; operand 4 is the CODE_LABEL to go to if index out of range.
-;; ??? There should be a barrier after the jump at the end.
-
(define_expand "casesi"
- [(set (match_dup 5) (match_operand:SI 0 "arith_reg_operand" ""))
- (set (match_dup 5) (minus:SI (match_dup 5)
- (match_operand:SI 1 "arith_operand" "")))
- (set (reg:SI 18)
- (gtu:SI (match_dup 5)
- (match_operand:SI 2 "arith_reg_operand" "")))
- (set (pc)
- (if_then_else (eq (reg:SI 18)
- (const_int 1))
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (set (match_dup 6) (match_dup 5))
- (set (match_dup 6) (ashift:SI (match_dup 6) (match_dup 7)))
- (set (reg:SI 0) (unspec [(label_ref (match_operand 3 "" ""))] 1))
- (parallel [(set (reg:SI 0) (plus:SI (reg:SI 0)
- (mem:HI (plus:SI (reg:SI 0)
- (match_dup 6)))))
- (set (match_dup 6) (mem:HI (plus:SI (reg:SI 0) (match_dup 6))))])
- (set (pc) (reg:SI 0))]
+ [(match_operand:SI 0 "arith_reg_operand" "")
+ (match_operand:SI 1 "arith_reg_operand" "")
+ (match_operand:SI 2 "arith_reg_operand" "")
+ (match_operand 3 "" "") (match_operand 4 "" "")]
""
"
{
+ rtx reg = gen_reg_rtx (SImode);
+ rtx reg2 = gen_reg_rtx (SImode);
operands[1] = copy_to_mode_reg (SImode, operands[1]);
operands[2] = copy_to_mode_reg (SImode, operands[2]);
- operands[5] = gen_reg_rtx (SImode);
- operands[6] = gen_reg_rtx (SImode);
- operands[7] = GEN_INT (TARGET_BIGTABLE ? 2 : 1);
+ /* If optimizing, casesi_worker depends on the mode of the instruction
+ before label it 'uses' - operands[3]. */
+ emit_insn (gen_casesi_0 (operands[0], operands[1], operands[2], operands[4],
+ reg));
+ emit_insn (gen_casesi_worker_0 (reg2, reg, operands[3]));
+ if (TARGET_SH2)
+ {
+ rtx lab = gen_label_rtx ();
+ emit_jump_insn (gen_casesi_jump_2 (reg2,
+ gen_rtx (LABEL_REF, VOIDmode, lab),
+ operands[3]));
+ emit_label (lab);
+ /* Put a fake jump after the label, lest some optimization might
+ delete the barrier and LAB. */
+ emit_jump_insn (gen_dummy_jump ());
+ }
+ else
+ {
+ emit_jump_insn (gen_casesi_jump_1 (reg2, operands[3]));
+ }
+ /* For SH2 and newer, the ADDR_DIFF_VEC is not actually relative to
+ operands[3], but to lab. We will fix this up in
+ machine_dependent_reorg. */
+ emit_barrier ();
+ DONE;
}")
-(define_insn "casesi_worker"
- [(set (reg:SI 0)
- (plus:SI (reg:SI 0)
- (mem:HI (plus:SI (reg:SI 0)
- (match_operand:SI 0 "arith_reg_operand" "+r")))))
- (set (match_dup 0) (mem:HI (plus:SI (reg:SI 0)
- (match_dup 0))))]
+(define_expand "casesi_0"
+ [(set (match_operand:SI 4 "" "") (match_operand:SI 0 "arith_reg_operand" ""))
+ (set (match_dup 4) (minus:SI (match_dup 4)
+ (match_operand:SI 1 "arith_operand" "")))
+ (set (reg:SI 18)
+ (gtu:SI (match_dup 4)
+ (match_operand:SI 2 "arith_reg_operand" "")))
+ (set (pc)
+ (if_then_else (ne (reg:SI 18)
+ (const_int 0))
+ (label_ref (match_operand 3 "" ""))
+ (pc)))]
+ ""
+ "")
+
+;; ??? reload might clobber r0 if we use it explicitly in the RTL before
+;; reload; using a R0_REGS pseudo reg is likely to give poor code.
+;; So we keep the use of r0 hidden in a R0_REGS clobber until after reload.
+
+(define_insn "casesi_worker_0"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec [(match_operand 1 "register_operand" "0,r")
+ (label_ref (match_operand 2 "" ""))] 2))
+ (clobber (match_scratch:SI 3 "=X,1"))
+ (clobber (match_scratch:SI 4 "=&z,z"))]
+ ""
+ "#")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec [(match_operand 1 "register_operand" "")
+ (label_ref (match_operand 2 "" ""))] 2))
+ (clobber (match_scratch:SI 3 ""))
+ (clobber (match_scratch:SI 4 ""))]
+ "! TARGET_SH2 && reload_completed"
+ [(set (reg:SI 0) (unspec [(label_ref (match_dup 2))] 1))
+ (parallel [(set (match_dup 0)
+ (unspec [(reg:SI 0) (match_dup 1) (label_ref (match_dup 2))] 2))
+ (clobber (match_dup 3))])
+ (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI 0)))]
+ "LABEL_NUSES (operands[2])++;")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec [(match_operand 1 "register_operand" "")
+ (label_ref (match_operand 2 "" ""))] 2))
+ (clobber (match_scratch:SI 3 ""))
+ (clobber (match_scratch:SI 4 ""))]
+ "TARGET_SH2 && reload_completed"
+ [(set (reg:SI 0) (unspec [(label_ref (match_dup 2))] 1))
+ (parallel [(set (match_dup 0)
+ (unspec [(reg:SI 0) (match_dup 1) (label_ref (match_dup 2))] 2))
+ (clobber (match_dup 3))])]
+ "LABEL_NUSES (operands[2])++;")
+
+(define_insn "*casesi_worker"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec [(reg:SI 0) (match_operand 1 "register_operand" "0,r")
+ (label_ref (match_operand 2 "" ""))] 2))
+ (clobber (match_scratch:SI 3 "=X,1"))]
""
"*
{
- if (TARGET_BIGTABLE)
- return \"mov.l @(r0,%0),%0\;add %0,r0\";
- else
- return \"mov.w @(r0,%0),%0\;add %0,r0\";
+ enum machine_mode mode
+ = optimize
+ ? GET_MODE (PATTERN (prev_real_insn (operands[2])))
+ : sh_addr_diff_vec_mode;
+ switch (mode)
+ {
+ case SImode:
+ return \"shll2 %1\;mov.l @(r0,%1),%0\";
+ case HImode:
+ return \"add %1,%1\;mov.w @(r0,%1),%0\";
+ case QImode:
+ {
+ rtx adj = PATTERN (prev_real_insn (operands[2]));
+ if ((insn_addresses[INSN_UID (XEXP ( XVECEXP (adj, 0, 1), 0))]
+ - insn_addresses[INSN_UID (XEXP (XVECEXP (adj, 0, 2), 0))])
+ <= 126)
+ return \"mov.b @(r0,%1),%0\";
+ return \"mov.b @(r0,%1),%0\;extu.b %0,%0\";
+ }
+ default:
+ abort ();
+ }
}"
[(set_attr "length" "4")])
+;; Include ADDR_DIFF_VECS in the shorten_branches pass; we have to
+;; use a negative-length instruction to actually accomplish this.
+(define_insn "addr_diff_vec_adjust"
+ [(unspec_volatile [(label_ref (match_operand 0 "" ""))
+ (label_ref (match_operand 1 "" ""))
+ (label_ref (match_operand 2 "" ""))
+ (match_operand 3 "const_int_operand" "")] 7)]
+ ""
+ "*
+{
+ /* ??? ASM_OUTPUT_ADDR_DIFF_ELT gets passed no context information, so
+ we must use a kludge with a global variable. */
+ sh_addr_diff_vec_mode = GET_MODE (PATTERN (insn));
+ return \"\";
+}"
+;; Need a variable length for this to be processed in each shorten_branch pass.
+;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes
+;; need to be (a choice of) constants.
+;; We use the calculated length before ADJUST_INSN_LENGTH to
+;; determine if the insn_addresses array contents are valid.
+ [(set (attr "length")
+ (if_then_else (eq (pc) (const_int -1))
+ (const_int 2) (const_int 0)))])
+
(define_insn "return"
[(return)]
"reload_completed"
@@ -1654,7 +2685,8 @@
[(set (match_operand:SI 0 "arith_reg_operand" "=r")
(eq:SI (reg:SI 18) (const_int 1)))]
""
- "movt %0")
+ "movt %0"
+ [(set_attr "type" "arith")])
(define_expand "seq"
[(set (match_operand:SI 0 "arith_reg_operand" "")
@@ -1669,10 +2701,16 @@
"operands[1] = prepare_scc_operands (LT);")
(define_expand "sle"
- [(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))]
+ [(match_operand:SI 0 "arith_reg_operand" "")]
""
- "operands[1] = prepare_scc_operands (LE);")
+ "
+{
+ rtx tmp = sh_compare_op0;
+ sh_compare_op0 = sh_compare_op1;
+ sh_compare_op1 = tmp;
+ emit_insn (gen_sge (operands[0]));
+ DONE;
+}")
(define_expand "sgt"
[(set (match_operand:SI 0 "arith_reg_operand" "")
@@ -1684,7 +2722,30 @@
[(set (match_operand:SI 0 "arith_reg_operand" "")
(match_dup 1))]
""
- "operands[1] = prepare_scc_operands (GE);")
+ "
+{
+ if (GET_MODE (sh_compare_op0) == SFmode)
+ {
+ if (TARGET_IEEE)
+ {
+ rtx t_reg = gen_rtx (REG, SImode, T_REG);
+ rtx lab = gen_label_rtx ();
+ emit_insn (gen_rtx (SET, VOIDmode, t_reg,
+ gen_rtx (EQ, SImode, sh_compare_op0,
+ sh_compare_op1)));
+ emit_jump_insn (gen_branch_true (lab));
+ emit_insn (gen_rtx (SET, VOIDmode, t_reg,
+ gen_rtx (GT, SImode, sh_compare_op0,
+ sh_compare_op1)));
+ emit_label (lab);
+ emit_insn (gen_movt (operands[0]));
+ }
+ else
+ emit_insn (gen_movnegt (operands[0], prepare_scc_operands (LT)));
+ DONE;
+ }
+ operands[1] = prepare_scc_operands (GE);
+}")
(define_expand "sgtu"
[(set (match_operand:SI 0 "arith_reg_operand" "")
@@ -1710,12 +2771,53 @@
""
"operands[1] = prepare_scc_operands (GEU);")
+;; sne moves the complement of the T reg to DEST like this:
+;; cmp/eq ...
+;; mov #-1,temp
+;; negc temp,dest
+;; This is better than xoring compare result with 1 because it does
+;; not require r0 and further, the -1 may be CSE-ed or lifted out of a
+;; loop.
+
(define_expand "sne"
+ [(set (match_dup 2) (const_int -1))
+ (parallel [(set (match_operand:SI 0 "arith_reg_operand" "")
+ (neg:SI (plus:SI (match_dup 1)
+ (match_dup 2))))
+ (set (reg:SI 18)
+ (ne:SI (ior:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))])]
+ ""
+ "
+{
+ operands[1] = prepare_scc_operands (EQ);
+ operands[2] = gen_reg_rtx (SImode);
+}")
+
+;; Use the same trick for FP sle / sge
+(define_expand "movnegt"
+ [(set (match_dup 2) (const_int -1))
+ (parallel [(set (match_operand 0 "" "")
+ (neg:SI (plus:SI (match_dup 1)
+ (match_dup 2))))
+ (set (reg:SI 18)
+ (ne:SI (ior:SI (match_operand 1 "" "") (match_dup 2))
+ (const_int 0)))])]
+ ""
+ "operands[2] = gen_reg_rtx (SImode);")
+
+;; Recognize mov #-1/negc/neg sequence, and change it to movt/add #-1.
+;; This prevents a regression that occurred when we switched from xor to
+;; mov/neg for sne.
+
+(define_split
[(set (match_operand:SI 0 "arith_reg_operand" "")
- (match_dup 1))
- (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))]
+ (plus:SI (reg:SI 18)
+ (const_int -1)))]
""
- "operands[1] = prepare_scc_operands (EQ);")
+ [(set (match_dup 0) (eq:SI (reg:SI 18) (const_int 1)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))]
+ "")
;; -------------------------------------------------------------------------
;; Instructions to cope with inline literal tables
@@ -1760,22 +2862,72 @@
[(set_attr "length" "8")
(set_attr "in_delay_slot" "no")])
+; 4 byte floating point
+
+(define_insn "consttable_sf"
+ [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")] 4)]
+ ""
+ "*
+{
+ union real_extract u;
+ bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
+ assemble_real (u.d, SFmode);
+ return \"\";
+}"
+ [(set_attr "length" "4")
+ (set_attr "in_delay_slot" "no")])
+
+; 8 byte floating point
+
+(define_insn "consttable_df"
+ [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")] 6)]
+ ""
+ "*
+{
+ union real_extract u;
+ bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
+ assemble_real (u.d, DFmode);
+ return \"\";
+}"
+ [(set_attr "length" "8")
+ (set_attr "in_delay_slot" "no")])
+
+;; Alignment is needed for some constant tables; it may also be added for
+;; Instructions at the start of loops, or after unconditional branches.
+;; ??? We would get more accurate lengths if we did instruction
+;; alignment based on the value of INSN_CURRENT_ADDRESS; the approach used
+;; here is too conservative.
+
; align to a two byte boundary
(define_insn "align_2"
- [(unspec_volatile [(const_int 0)] 10)]
+ [(unspec_volatile [(const_int 1)] 1)]
""
".align 1"
[(set_attr "length" "0")
(set_attr "in_delay_slot" "no")])
; align to a four byte boundary
+;; align_4 and align_log are instructions for the starts of loops, or
+;; after unconditional branches, which may take up extra room.
-(define_insn "align_4"
- [(unspec_volatile [(const_int 0)] 5)]
+(define_expand "align_4"
+ [(unspec_volatile [(const_int 2)] 1)]
""
- ".align 2"
- [(set_attr "in_delay_slot" "no")])
+ "")
+
+; align to a cache line boundary
+
+(define_insn "align_log"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "")] 1)]
+ ""
+ ".align %O0"
+;; Need a variable length for this to be processed in each shorten_branch pass.
+;; The actual work is done in ADJUST_INSN_LENGTH, because length attributes
+;; need to be (a choice of) constants.
+ [(set (attr "length")
+ (if_then_else (ne (pc) (pc)) (const_int 2) (const_int 0)))
+ (set_attr "in_delay_slot" "no")])
; emitted at the end of the literal table, used to emit the
; 32bit branch labels if needed.
@@ -1834,7 +2986,187 @@
"jsr @%0%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
+
+;; -------------------------------------------------------------------------
+;; Floating point instructions.
+;; -------------------------------------------------------------------------
+
+;; ??? All patterns should have a type attribute.
+
+(define_insn "addsf3"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (plus:SF (match_operand:SF 1 "arith_reg_operand" "%0")
+ (match_operand:SF 2 "arith_reg_operand" "f")))]
+ "TARGET_SH3E"
+ "fadd %2,%0"
+ [(set_attr "type" "fp")])
+
+(define_insn "subsf3"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (minus:SF (match_operand:SF 1 "arith_reg_operand" "0")
+ (match_operand:SF 2 "arith_reg_operand" "f")))]
+ "TARGET_SH3E"
+ "fsub %2,%0"
+ [(set_attr "type" "fp")])
+
+(define_insn "mulsf3"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (mult:SF (match_operand:SF 1 "arith_reg_operand" "%0")
+ (match_operand:SF 2 "arith_reg_operand" "f")))]
+ "TARGET_SH3E"
+ "fmul %2,%0"
+ [(set_attr "type" "fp")])
+
+(define_insn "*macsf3"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (plus:SF (mult:SF (match_operand:SF 1 "arith_reg_operand" "%w")
+ (match_operand:SF 2 "arith_reg_operand" "f"))
+ (match_operand:SF 3 "arith_reg_operand" "0")))]
+ "TARGET_SH3E"
+ "fmac fr0,%2,%0"
+ [(set_attr "type" "fp")])
+
+(define_insn "divsf3"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (div:SF (match_operand:SF 1 "arith_reg_operand" "0")
+ (match_operand:SF 2 "arith_reg_operand" "f")))]
+ "TARGET_SH3E"
+ "fdiv %2,%0"
+ [(set_attr "type" "fdiv")])
+
+(define_expand "floatsisf2"
+ [(set (reg:SI 22)
+ (match_operand:SI 1 "arith_reg_operand" ""))
+ (set (match_operand:SF 0 "arith_reg_operand" "")
+ (float:SF (reg:SI 22)))]
+ "TARGET_SH3E"
+ "")
+
+(define_insn "*floatsisf2_ie"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (float:SF (reg:SI 22)))]
+ "TARGET_SH3E"
+ "float fpul,%0"
+ [(set_attr "type" "fp")])
+
+(define_expand "fix_truncsfsi2"
+ [(set (reg:SI 22)
+ (fix:SI (match_operand:SF 1 "arith_reg_operand" "f")))
+ (set (match_operand:SI 0 "arith_reg_operand" "=r")
+ (reg:SI 22))]
+ "TARGET_SH3E"
+ "")
+
+(define_insn "*fixsfsi"
+ [(set (reg:SI 22)
+ (fix:SI (match_operand:SF 0 "arith_reg_operand" "f")))]
+ "TARGET_SH3E"
+ "ftrc %0,fpul"
+ [(set_attr "type" "fp")])
+
+(define_insn "cmpgtsf_t"
+ [(set (reg:SI 18) (gt:SI (match_operand:SF 0 "arith_reg_operand" "f")
+ (match_operand:SF 1 "arith_reg_operand" "f")))]
+ "TARGET_SH3E"
+ "fcmp/gt %1,%0"
+ [(set_attr "type" "fp")])
+
+(define_insn "cmpeqsf_t"
+ [(set (reg:SI 18) (eq:SI (match_operand:SF 0 "arith_reg_operand" "f")
+ (match_operand:SF 1 "arith_reg_operand" "f")))]
+ "TARGET_SH3E"
+ "fcmp/eq %1,%0"
+ [(set_attr "type" "fp")])
+
+(define_insn "ieee_ccmpeqsf_t"
+ [(set (reg:SI 18) (ior:SI (reg:SI 18)
+ (eq:SI (match_operand:SF 0 "arith_reg_operand" "f")
+ (match_operand:SF 1 "arith_reg_operand" "f"))))]
+ "TARGET_SH3E && TARGET_IEEE"
+ "* return output_ieee_ccmpeq (insn, operands);"
+ [(set_attr "length" "4")])
+
+
+(define_expand "cmpsf"
+ [(set (reg:SI 18) (compare (match_operand:SF 0 "arith_operand" "")
+ (match_operand:SF 1 "arith_operand" "")))]
+ "TARGET_SH3E"
+ "
+{
+ sh_compare_op0 = operands[0];
+ sh_compare_op1 = operands[1];
+ DONE;
+}")
+
+(define_insn "negsf2"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (neg:SF (match_operand:SF 1 "arith_reg_operand" "0")))]
+ "TARGET_SH3E"
+ "fneg %0"
+ [(set_attr "type" "fp")])
+
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (sqrt:DF (match_operand:SF 1 "arith_reg_operand" "0")))]
+ "TARGET_SH3E"
+ "fsqrt %0"
+ [(set_attr "type" "fdiv")])
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "arith_reg_operand" "=f")
+ (abs:SF (match_operand:SF 1 "arith_reg_operand" "0")))]
+ "TARGET_SH3E"
+ "fabs %0"
+ [(set_attr "type" "fp")])
+
+;; Bit field extract patterns. These give better code for packed bitfields,
+;; because they allow auto-increment addresses to be generated.
+
+(define_expand "insv"
+ [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "")
+ (match_operand:SI 1 "immediate_operand" "")
+ (match_operand:SI 2 "immediate_operand" ""))
+ (match_operand:SI 3 "general_operand" ""))]
+ "! TARGET_LITTLE_ENDIAN"
+ "
+{
+ rtx addr_target, orig_address, shift_reg;
+ HOST_WIDE_INT size;
+
+ /* ??? expmed doesn't care for non-register predicates. */
+ if (! memory_operand (operands[0], VOIDmode)
+ || ! immediate_operand (operands[1], VOIDmode)
+ || ! immediate_operand (operands[2], VOIDmode)
+ || ! general_operand (operands[3], VOIDmode))
+ FAIL;
+ /* If this isn't a 16 / 24 / 32 bit field, or if
+ it doesn't start on a byte boundary, then fail. */
+ size = INTVAL (operands[1]);
+ if (size < 16 || size > 32 || size % 8 != 0
+ || (INTVAL (operands[2]) % 8) != 0)
+ FAIL;
+
+ size /= 8;
+ orig_address = XEXP (operands[0], 0);
+ addr_target = gen_reg_rtx (SImode);
+ shift_reg = gen_reg_rtx (SImode);
+ emit_insn (gen_movsi (shift_reg, operands[3]));
+ emit_insn (gen_addsi3 (addr_target, orig_address, GEN_INT (size - 1)));
+
+ operands[0] = change_address (operands[0], QImode, addr_target);
+ emit_insn (gen_movqi (operands[0], gen_rtx (SUBREG, QImode, shift_reg, 0)));
+ while (size -= 1)
+ {
+ emit_insn (gen_lshrsi3_k (shift_reg, shift_reg, GEN_INT (8)));
+ emit_insn (gen_addsi3 (addr_target, addr_target, GEN_INT (-1)));
+ emit_insn (gen_movqi (operands[0],
+ gen_rtx (SUBREG, QImode, shift_reg, 0)));
+ }
+
+ DONE;
+}")
+
;; -------------------------------------------------------------------------
;; Peepholes
;; -------------------------------------------------------------------------
@@ -1930,7 +3262,11 @@
(plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
(set (mem:SF (match_dup 0))
(match_operand:SF 2 "general_movsrc_operand" ""))]
- "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+ "REGNO (operands[0]) == 0
+ && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
+ || (GET_CODE (operands[2]) == SUBREG
+ && REGNO (SUBREG_REG (operands[2])) < 16))
+ && reg_unused_after (operands[0], insn)"
"mov.l %2,@(%0,%1)")
(define_peephole
@@ -1939,5 +3275,57 @@
(set (match_operand:SF 2 "general_movdst_operand" "")
(mem:SF (match_dup 0)))]
- "REGNO (operands[0]) == 0 && reg_unused_after (operands[0], insn)"
+ "REGNO (operands[0]) == 0
+ && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) < 16)
+ || (GET_CODE (operands[2]) == SUBREG
+ && REGNO (SUBREG_REG (operands[2])) < 16))
+ && reg_unused_after (operands[0], insn)"
"mov.l @(%0,%1),%2")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
+ (set (mem:SF (match_dup 0))
+ (match_operand:SF 2 "general_movsrc_operand" ""))]
+ "REGNO (operands[0]) == 0
+ && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) >= FIRST_FP_REG)
+ || (GET_CODE (operands[2]) == SUBREG
+ && REGNO (SUBREG_REG (operands[2])) >= FIRST_FP_REG))
+ && reg_unused_after (operands[0], insn)"
+ "fmov{.s|} %2,@(%0,%1)")
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))
+ (set (match_operand:SF 2 "general_movdst_operand" "")
+
+ (mem:SF (match_dup 0)))]
+ "REGNO (operands[0]) == 0
+ && ((GET_CODE (operands[2]) == REG && REGNO (operands[2]) >= FIRST_FP_REG)
+ || (GET_CODE (operands[2]) == SUBREG
+ && REGNO (SUBREG_REG (operands[2])) >= FIRST_FP_REG))
+ && reg_unused_after (operands[0], insn)"
+ "fmov{.s|} @(%0,%1),%2")
+
+;; Switch to a new stack with its address in sp_switch (a SYMBOL_REF). */
+(define_insn "sp_switch_1"
+ [(const_int 1)]
+ ""
+ "*
+{
+ rtx xoperands[1];
+
+ xoperands[0] = sp_switch;
+ output_asm_insn (\"mov.l r0,@-r15\;mov.l %0,r0\", xoperands);
+ output_asm_insn (\"mov.l @r0,r0\;mov.l r15,@-r0\", xoperands);
+ return \"mov r0,r15\";
+}"
+ [(set_attr "length" "10")])
+
+;; Switch back to the original stack for interrupt functions with the
+;; sp_switch attribute. */
+(define_insn "sp_switch_2"
+ [(const_int 2)]
+ ""
+ "mov.l @r15+,r15\;mov.l @r15+,r0"
+ [(set_attr "length" "4")])
diff --git a/gnu/usr.bin/gcc/config/sh/t-sh b/gnu/usr.bin/gcc/config/sh/t-sh
index e4761b13853..7f925529c4f 100644
--- a/gnu/usr.bin/gcc/config/sh/t-sh
+++ b/gnu/usr.bin/gcc/config/sh/t-sh
@@ -21,8 +21,8 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-MULTILIB_OPTIONS = ml m2
-MULTILIB_DIRNAMES = ml m2
+MULTILIB_OPTIONS= ml m2/m3e
+MULTILIB_DIRNAMES=
MULTILIB_MATCHES = m2=m3
LIBGCC = stmp-multilib
diff --git a/gnu/usr.bin/gcc/config/sh/xm-sh.h b/gnu/usr.bin/gcc/config/sh/xm-sh.h
index 3d8ef8410b8..f51b787f6df 100644
--- a/gnu/usr.bin/gcc/config/sh/xm-sh.h
+++ b/gnu/usr.bin/gcc/config/sh/xm-sh.h
@@ -1,5 +1,6 @@
/* Configuration for GNU C-compiler for Hitachi SH.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1997 Free Software Foundation, Inc.
+
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
@@ -32,9 +33,6 @@ Boston, MA 02111-1307, USA. */
#define alloca __builtin_alloca
#endif
-/* We have the vprintf function. */
-#define HAVE_VPRINTF 1
-
/* target machine dependencies.
tm.h is a symbolic link to the actual target specific file. */
#include "tm.h"
diff --git a/gnu/usr.bin/gcc/config/sparc/gmon-sol2.c b/gnu/usr.bin/gcc/config/sparc/gmon-sol2.c
index ba1549b036e..9b41c649297 100644
--- a/gnu/usr.bin/gcc/config/sparc/gmon-sol2.c
+++ b/gnu/usr.bin/gcc/config/sparc/gmon-sol2.c
@@ -39,11 +39,11 @@
static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91";
#endif /* not lint */
-#include <unistd.h>
-
-#ifdef DEBUG
#include <stdio.h>
-#endif
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
#if 0
#include "sparc/gmon.h"
@@ -172,6 +172,7 @@ monstartup(lowpc, highpc)
moncontrol(1);
}
+void
_mcleanup()
{
int fd;
@@ -180,11 +181,35 @@ _mcleanup()
char *frompc;
int toindex;
struct rawarc rawarc;
+ char *profdir;
+ char *proffile;
+ char *progname;
+ char buf[PATH_MAX];
+ extern char **___Argv;
moncontrol(0);
- fd = creat( "gmon.out" , 0666 );
+
+ 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/%d.%s", profdir, getpid(), progname);
+ proffile = buf;
+ } else {
+ proffile = "gmon.out";
+ }
+
+ fd = creat( proffile, 0666 );
if ( fd < 0 ) {
- perror( "mcount: gmon.out" );
+ perror( proffile );
return;
}
# ifdef DEBUG
diff --git a/gnu/usr.bin/gcc/config/sparc/lb1spc.asm b/gnu/usr.bin/gcc/config/sparc/lb1spc.asm
index c74ef6a93a5..ec9532d3ec0 100644
--- a/gnu/usr.bin/gcc/config/sparc/lb1spc.asm
+++ b/gnu/usr.bin/gcc/config/sparc/lb1spc.asm
@@ -87,14 +87,14 @@ mul_shortway:
.udiv:
save %sp, -64, %sp
b divide
- mov 0, %i2 ! result always positive
+ mov 0, %l2 ! result always positive
.global .div
.proc 4
.div:
save %sp, -64, %sp
orcc %i1, %i0, %g0 ! is either operand negative
bge divide ! if not, skip this junk
- xor %i1, %i0, %i2 ! record sign of result in sign of %i2
+ xor %i1, %i0, %l2 ! record sign of result in sign of %l2
tst %i1
bge 2f
tst %i0
@@ -110,7 +110,7 @@ divide:
te 2 ! if %i1 = 0
mov %i0, %i3
mov 0, %i2
- sethi %hi(1<<(32-2-1)), %l3
+ sethi %hi(1<<(32-4-1)), %l3
cmp %i3, %l3
blu not_really_big
mov 0, %l0
@@ -137,7 +137,7 @@ divide:
! We are here if the %i1 overflowed when Shifting.
! This means that %i3 has the high-order bit set.
! Restore %l1 and subtract from %i3.
- sll %l3, 2, %l3
+ sll %l3, 4, %l3
srl %l1, 1, %l1
add %l1, %l3, %l1
b do_single_div
@@ -271,7 +271,7 @@ end_regular_divide:
! non-restoring fixup here
dec %i2
got_result:
- tst %i2
+ tst %l2
bge 1f
restore
! answer < 0
@@ -289,14 +289,14 @@ got_result:
.urem:
save %sp, -64, %sp
b divide
- mov 0, %i2 ! result always positive
+ mov 0, %l2 ! result always positive
.global .rem
.proc 4
.rem:
save %sp, -64, %sp
orcc %i1, %i0, %g0 ! is either operand negative
bge divide ! if not, skip this junk
- mov %i0, %i2 ! record sign of result in sign of %i2
+ mov %i0, %l2 ! record sign of result in sign of %i2
tst %i1
bge 2f
tst %i0
@@ -312,7 +312,7 @@ divide:
te 2 ! if %i1 = 0
mov %i0, %i3
mov 0, %i2
- sethi %hi(1<<(32-2-1)), %l3
+ sethi %hi(1<<(32-4-1)), %l3
cmp %i3, %l3
blu not_really_big
mov 0, %l0
@@ -339,7 +339,7 @@ divide:
! We are here if the %i1 overflowed when Shifting.
! This means that %i3 has the high-order bit set.
! Restore %l1 and subtract from %i3.
- sll %l3, 2, %l3
+ sll %l3, 4, %l3
srl %l1, 1, %l1
add %l1, %l3, %l1
b do_single_div
@@ -473,7 +473,7 @@ end_regular_divide:
! non-restoring fixup here
add %i3, %i1, %i3
got_result:
- tst %i2
+ tst %l2
bge 1f
restore
! answer < 0
diff --git a/gnu/usr.bin/gcc/config/sparc/lite.h b/gnu/usr.bin/gcc/config/sparc/lite.h
index c7154e9ea1a..55c232ac779 100644
--- a/gnu/usr.bin/gcc/config/sparc/lite.h
+++ b/gnu/usr.bin/gcc/config/sparc/lite.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1996 Free Software Foundation, Inc.
Contributed by Jim Wilson (wilson@cygnus.com).
This file is part of GNU CC.
@@ -27,10 +27,10 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparclite)");
-/* Enable sparclite and epilogue options. Do not enable the fpu. */
+/* Enable app-regs and epilogue options. Do not enable the fpu. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (1024+130)
+#define TARGET_DEFAULT (MASK_APP_REGS + MASK_EPILOGUE)
/* US Software GOFAST library support. */
#include "gofast.h"
diff --git a/gnu/usr.bin/gcc/config/sparc/litecoff.h b/gnu/usr.bin/gcc/config/sparc/litecoff.h
index cd1604f2da4..bd89e1b4686 100644
--- a/gnu/usr.bin/gcc/config/sparc/litecoff.h
+++ b/gnu/usr.bin/gcc/config/sparc/litecoff.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SPARClite w/o FPU, COFF.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com).
This file is part of GNU CC.
@@ -32,47 +32,11 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dsparc -Dsparclite -Acpu(sparc) -Amachine(sparc)"
-/* just in case */
-#undef DBX_DEBUGGING_INFO
-#undef PREFERRED_DEBUGGING_TYPE
-#define DBX_DEBUGGING_INFO
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-/* These are all necessary because this is how gdb expects gcc to output
- stabs in coff. */
-
-/* Be function-relative for block and source line stab directives. */
-
-#define DBX_BLOCKS_FUNCTION_RELATIVE 1
+/* Default to stabs in COFF. */
-/* but, to make this work, functions must appear prior to line info. */
-
-#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\nLetext:\n", N_SO)
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-/* This is copied from final.c and sparc.h. */
-#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; \
- 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; \
- } }
+#include "dbxcoff.h"
/* Support the ctors and dtors sections for g++. */
@@ -89,7 +53,7 @@ Boston, MA 02111-1307, USA. */
given time. */
#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_const, in_bss, in_ctors, in_dtors
+#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
/* A list of extra section function definitions. */
diff --git a/gnu/usr.bin/gcc/config/sparc/lynx-ng.h b/gnu/usr.bin/gcc/config/sparc/lynx-ng.h
index bd3f4ddc224..9e9f82cf10b 100644
--- a/gnu/usr.bin/gcc/config/sparc/lynx-ng.h
+++ b/gnu/usr.bin/gcc/config/sparc/lynx-ng.h
@@ -28,7 +28,7 @@ Boston, MA 02111-1307, USA. */
#define CPP_SPEC "%{mthreads:-D_MULTITHREADED} \
%{mposix:-D_POSIX_SOURCE} \
%{msystem-v:-I/usr/include_v} \
- %{msparclite:-D__sparclite__} %{mv8:-D__sparc_v8__}"
+ %(cpp_cpu)"
/* Names to predefine in the preprocessor for this target machine. */
diff --git a/gnu/usr.bin/gcc/config/sparc/lynx.h b/gnu/usr.bin/gcc/config/sparc/lynx.h
index dac5ee4e5d0..99b319a0df2 100644
--- a/gnu/usr.bin/gcc/config/sparc/lynx.h
+++ b/gnu/usr.bin/gcc/config/sparc/lynx.h
@@ -1,5 +1,5 @@
/* Definitions for SPARC running LynxOS.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -35,7 +35,7 @@ Boston, MA 02111-1307, USA. */
#define CPP_SPEC "%{mthreads:-D_MULTITHREADED} \
%{mposix:-D_POSIX_SOURCE} \
%{msystem-v:-I/usr/include_v} \
- %{msparclite:-D__sparclite__} %{mv8:-D__sparc_v8__}"
+ %(cpp_cpu)"
/* Names to predefine in the preprocessor for this target machine. */
diff --git a/gnu/usr.bin/gcc/config/sparc/pbd.h b/gnu/usr.bin/gcc/config/sparc/pbd.h
index 156c99d72cb..6fb6cb621e8 100644
--- a/gnu/usr.bin/gcc/config/sparc/pbd.h
+++ b/gnu/usr.bin/gcc/config/sparc/pbd.h
@@ -1,9 +1,6 @@
-/* Definitions of target machine for GNU compiler.
-
- Citicorp/TTI Unicom PBD version
- (using GAS and COFF (encapsulated is unacceptable) )
-
- Copyright (C) 1990 Free Software Foundation, Inc.
+/* 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.
@@ -105,9 +102,10 @@ Boston, MA 02111-1307, USA. */
}
*/
-#undef ASM_OUTPUT_LABELREF
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, "%s", NAME)
+/* The prefix to add to user-visible assembler symbols. */
+
+#undef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
/* fixes: */
/*
diff --git a/gnu/usr.bin/gcc/config/sparc/sol2.h b/gnu/usr.bin/gcc/config/sparc/sol2.h
index d0772dfe88c..ff3339d0f1f 100644
--- a/gnu/usr.bin/gcc/config/sparc/sol2.h
+++ b/gnu/usr.bin/gcc/config/sparc/sol2.h
@@ -1,7 +1,6 @@
/* Definitions of target machine for GNU compiler, for SPARC running Solaris 2
- Copyright 1992, 1995 Free Software Foundation, Inc.
-
- Written by Ron Guilmette (rfg@netcom.com).
+ Copyright 1992, 1995, 1996, 1997 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.
@@ -26,29 +25,47 @@ Boston, MA 02111-1307, USA. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES \
- "-Dsun -Dsparc -Dunix -D__svr4__ -D__SVR4 \
- -Asystem(unix) -Asystem(svr4) -Acpu(sparc) -Amachine(sparc)\
- -D__GCC_NEW_VARARGS__"
+"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 \
+-Asystem(unix) -Asystem(svr4)"
-#undef CPP_SPEC
-#define CPP_SPEC "\
- %{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude}\
- %{msparclite:-D__sparclite__} %{mv8:-D__sparc_v8__}\
- %{msupersparc:-D__supersparc__ -D__sparc_v8__}"
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "\
+%{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:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
- %{fpic:-K PIC} %{fPIC:-K PIC}"
+#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) (REGNO)
+#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. */
@@ -60,17 +77,12 @@ Boston, MA 02111-1307, USA. */
#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"
+/* 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. */
@@ -102,7 +114,10 @@ do { \
#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{!shared: \
%{!symbolic: \
- %{p:mcrt1.o%s}%{!p:crt1.o%s} %{pg:gmon.o%s}}} \
+ %{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: \
@@ -124,11 +139,11 @@ do { \
/* 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 %{!h*:%{o*:-h %*}}} \
- %{symbolic:-Bsymbolic -G -dy -z text %{!h*:%{o*:-h %*}}} \
+ %{shared:-G -dy %{!mimpure-text:-z text}} \
+ %{symbolic:-Bsymbolic -G -dy -z text} \
%{G:-G} \
%{YP,*} \
%{R*} \
@@ -148,17 +163,10 @@ do { \
#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) == 'x' \
|| (CHAR) == 'z')
/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h.
@@ -166,3 +174,8 @@ do { \
/* 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
diff --git a/gnu/usr.bin/gcc/config/sparc/sp64-aout.h b/gnu/usr.bin/gcc/config/sparc/sp64-aout.h
index 4bec40f90ac..fbd4ef372f9 100644
--- a/gnu/usr.bin/gcc/config/sparc/sp64-aout.h
+++ b/gnu/usr.bin/gcc/config/sparc/sp64-aout.h
@@ -1,6 +1,5 @@
-/* Definitions of target machine for GNU compiler,
- for Sun SPARC-V9 on a hypothetical a.out format machine.
- Copyright (C) 1994 Free Software Foundation, Inc.
+/* Definitions of target machine for GNU compiler, for SPARC64, a.out.
+ Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
Contributed by Doug Evans, dje@cygnus.com.
This file is part of GNU CC.
@@ -20,31 +19,17 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This is a v9 only compiler. -mv8 is not expected to work. If you want
- a v8/v9 compiler, this isn't the place to do it. */
-/* ??? Until real v9 machines exist, all of this is subject to change. */
-/* ??? This file should really be called sp64-sunos4.h or some such but that
- would be a bit misleading since no such machines exist yet. The current
- name is also misleading since the term "aout" is more properly applied to
- embedded configurations. */
-
-#define SPARCV9 /* See sparc.h. */
-
#include "sparc/sparc.h"
+#include "aoutos.h"
-/* A v9 compiler with 32 bit integers and 64 bit pointers,
- in a Medium/Low code model with only 32 bit assembler support. */
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparc64-aout)")
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (MASK_V9 + MASK_MEDLOW + MASK_ENV32 + MASK_PTR64 + MASK_HARD_QUAD + MASK_EPILOGUE + MASK_FPU)
-
-/* ??? Disabled for v9 as the current implementation of the Medium/Anywhere
- code model needs this in the data segment (still true?). Let's hope the
- assembler is fixed. */
-#undef JUMP_TABLES_IN_TEXT_SECTION
-
-/* Put all data in the data segment (necessary for the current implementation
- of the Medium/Anywhere code model - see if still true). */
+ (MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \
+ + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
-#define READONLY_DATA_SECTION data_section
+/* The only code model supported is Medium/Low. */
+#undef SPARC_DEFAULT_CMODEL
+#define SPARC_DEFAULT_CMODEL CM_MEDLOW
diff --git a/gnu/usr.bin/gcc/config/sparc/sp64-elf.h b/gnu/usr.bin/gcc/config/sparc/sp64-elf.h
index e6d50d22928..0c0bb6bfbab 100644
--- a/gnu/usr.bin/gcc/config/sparc/sp64-elf.h
+++ b/gnu/usr.bin/gcc/config/sparc/sp64-elf.h
@@ -1,6 +1,5 @@
-/* Definitions of target machine for GNU compiler,
- for Sun SPARC-V9 on a hypothetical elf format machine.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+/* Definitions of target machine for GNU compiler, for SPARC64, ELF.
+ Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Doug Evans, dje@cygnus.com.
This file is part of GNU CC.
@@ -20,59 +19,48 @@ 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 a v9 only compiler. -mv8 is not expected to work. If you want
- a v8/v9 compiler, this isn't the place to do it. */
-/* ??? Until real v9 machines exist, all of this is subject to change. */
-/* ??? This file should really be called sp64-sol2.h or some such but that
- would be a bit misleading since no such machines exist yet. The current
- name is also misleading since the term "elf" is more properly applied to
- embedded configurations. */
-
-#define SPARCV9 /* See sparc.h. */
-
/* ??? 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). Until real sparc64 machines exist, it's not clear
- which is better. */
+ (suitably cleaned up). */
#include "sparc/sol2.h"
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc64-elf)")
-/* A v9 compiler with stack-bias, 32 bit integers and 64 bit pointers,
- in a Medium/Anywhere code model environment. */
+/* A 64 bit v9 compiler without stack-bias,
+ in a Medium/Anywhere code model environment.
+ There is no stack bias as this configuration is intended for
+ embedded systems. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (MASK_V9 + MASK_STACK_BIAS + MASK_MEDANY + MASK_PTR64 + MASK_HARD_QUAD + MASK_EPILOGUE + MASK_FPU)
+(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \
+ + MASK_APP_REGS + MASK_EPILOGUE + MASK_FPU)
-/* __svr4__ is used by the C library */
-#undef CPP_PREDEFINES
-#define CPP_PREDEFINES "\
--D__sparc__ -D__sparc_v9__ -D__svr4__ \
--Acpu(sparc64) -Amachine(sparc64) \
-"
+#undef SPARC_DEFAULT_CMODEL
+#define SPARC_DEFAULT_CMODEL CM_EMBMEDANY
-#undef CPP_SPEC
-#define CPP_SPEC "\
-%{mint64:-D__INT_MAX__=9223372036854775807LL -D__LONG_MAX__=9223372036854775807LL} \
-%{mlong64:-D__LONG_MAX__=9223372036854775807LL} \
-"
+/* __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:%{!V:-V}} -s %{fpic:-K PIC} %{fPIC:-K PIC} \
+%{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:%{!V:-V}} \
+%{v:-V} \
+%{mlittle-endian:-EL} \
"
/* We need something a little simpler for the embedded environment.
@@ -84,20 +72,22 @@ crtbegin.o%s \
"
#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "%{!nostartfiles:crtend.o%s}"
+#define ENDFILE_SPEC "crtend.o%s"
/* Use the default (for now). */
#undef LIB_SPEC
-/* Unfortunately, svr4.h redefines these so we have to restore them to
- their original values in sparc.h. */
-/* ??? It might be possible to eventually get svr4.h to do the right thing. */
+/* V9 chips can handle either endianness. */
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES \
+{"big-endian", -MASK_LITTLE_ENDIAN}, \
+{"little-endian", MASK_LITTLE_ENDIAN},
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long long int"
+#undef BYTES_BIG_ENDIAN
+#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
-#undef SIZE_TYPE
-#define SIZE_TYPE "long long unsigned int"
+#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
@@ -106,21 +96,37 @@ crtbegin.o%s \
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 16
-/* ??? Disabled for v9 as the current implementation of the Medium/Anywhere
- code model needs this in the data segment (still true?). Let's hope the
- assembler is fixed. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 128
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long long int"
+#undef SIZE_TYPE
+#define SIZE_TYPE "long long unsigned int"
+
+/* 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
/* 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 DWARF_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?),
diff --git a/gnu/usr.bin/gcc/config/sparc/sparc.c b/gnu/usr.bin/gcc/config/sparc/sparc.c
index 04494919f98..58da5ac35fc 100644
--- a/gnu/usr.bin/gcc/config/sparc/sparc.c
+++ b/gnu/usr.bin/gcc/config/sparc/sparc.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Sun SPARC.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ 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.
@@ -21,8 +21,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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "rtl.h"
#include "regs.h"
@@ -39,15 +39,17 @@ Boston, MA 02111-1307, USA. */
/* 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. */
+ 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_V9 && current_function_returns_struct)
+#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. */
-/* Says what architecture we're compiling for. */
-enum arch_type sparc_arch_type;
-
/* 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
@@ -62,17 +64,6 @@ static int actual_fsize;
rtx sparc_compare_op0, sparc_compare_op1;
-/* Count of named arguments (v9 only).
- ??? INIT_CUMULATIVE_ARGS initializes these, and FUNCTION_ARG_ADVANCE
- increments SPARC_ARG_COUNT. They are then used by
- FUNCTION_ARG_CALLEE_COPIES to determine if the argument is really a named
- argument or not. This hack is necessary because the NAMED argument to the
- FUNCTION_ARG_XXX macros is not what it says it is: it does not include the
- last named argument. */
-
-int sparc_arg_count;
-int sparc_n_named_args;
-
/* 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;
@@ -97,7 +88,7 @@ char leaf_reg_remap[] =
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};
+ 96, 97, 98, 99, 100};
#endif
@@ -109,46 +100,224 @@ char leaf_reg_remap[] =
static char *frame_base_name;
static int frame_base_offset;
-static rtx find_addr_reg ();
-static void sparc_init_modes ();
+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 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 }
+};
+
+/* 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 ()
{
- /* Check for any conflicts in the choice of options. */
- /* ??? This stuff isn't really usable yet. */
+ 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 }
+ };
+ 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 },
+ /* "v8plus" is what Sun calls Solaris2.5 running on UltraSPARC's. */
+ { "v8plus", PROCESSOR_V8PLUS, MASK_ISA, MASK_V9 },
+ { "v9", PROCESSOR_V9, MASK_ISA, MASK_V9 },
+ /* TI ultrasparc */
+ { "ultrasparc", PROCESSOR_ULTRASPARC, MASK_ISA, MASK_V9 },
+ { 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
- if (! TARGET_V9)
+ /* Code model selection. */
+ sparc_cmodel = SPARC_DEFAULT_CMODEL;
+ if (sparc_cmodel_string != NULL)
{
- if (target_flags & MASK_CODE_MODEL)
- error ("code model support is only available with -mv9");
- if (TARGET_INT64)
- error ("-mint64 is only available with -mv9");
- if (TARGET_LONG64)
- error ("-mlong64 is only available with -mv9");
- if (TARGET_PTR64)
- error ("-mptr64 is only available with -mv9");
- if (TARGET_ENV32)
- error ("-menv32 is only available with -mv9");
- if (TARGET_STACK_BIAS)
- error ("-mstack-bias is only available with -mv9");
+ 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;
+
+ /* 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
{
- /* ??? Are there any options that aren't usable with v9.
- -munaligned-doubles? */
+ /* ??? This relies on ASM_OUTPUT_ALIGN to not emit the alignment if
+ its 0. This sounds a bit kludgey. */
+ sparc_align_loops = 0;
}
- /* Check for conflicts in cpu specification.
- If we use -mcpu=xxx, this can be removed. */
+ /* 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;
+ }
- if ((TARGET_V8 != 0) + (TARGET_SPARCLITE != 0) + (TARGET_V9 != 0) > 1)
- error ("conflicting architectures defined");
+ /* 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;
/* Do various machine dependent initializations. */
sparc_init_modes ();
@@ -171,7 +340,7 @@ static rtx fpconv_stack_temp;
/* Called once for each function. */
void
-sparc64_init_expanders ()
+sparc_init_expanders ()
{
fpconv_stack_temp = NULL_RTX;
}
@@ -182,10 +351,10 @@ rtx
sparc64_fpconv_stack_temp ()
{
if (fpconv_stack_temp == NULL_RTX)
- fpconv_stack_temp =
- assign_stack_local (DImode, GET_MODE_SIZE (DImode), 0);
+ fpconv_stack_temp =
+ assign_stack_local (DImode, GET_MODE_SIZE (DImode), 0);
- return fpconv_stack_temp;
+ return fpconv_stack_temp;
}
/* Miscellaneous utilities. */
@@ -204,13 +373,19 @@ v9_regcmp_p (code)
/* Operand constraints. */
/* Return non-zero only if OP is a register of mode MODE,
- or const0_rtx. */
+ 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 (op == const0_rtx || register_operand (op, 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
@@ -224,6 +399,7 @@ reg_or_0_operand (op, mode)
}
/* Nonzero if OP is a floating point value with value 0.0. */
+
int
fp_zero_operand (op)
rtx op;
@@ -231,7 +407,7 @@ fp_zero_operand (op)
REAL_VALUE_TYPE r;
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- return REAL_VALUES_EQUAL (r, dconst0);
+ return (REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r));
}
/* Nonzero if OP is an integer register. */
@@ -242,32 +418,56 @@ intreg_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, SImode)
- || (TARGET_V9 && register_operand (op, DImode)));
+ || (TARGET_ARCH64 && register_operand (op, DImode)));
}
/* Nonzero if OP is a floating point condition code register. */
int
-ccfp_reg_operand (op, mode)
+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 || REGNO (op) == 0)
+ if (GET_CODE (op) != REG)
return 0;
- if (GET_MODE (op) != mode)
+
+ 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 %fcc1-3 are pseudos first. See gen_compare_reg(). */
+#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) - 96 < 4;
+ 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)
@@ -346,10 +546,49 @@ symbolic_memory_operand (op, mode)
|| 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;
+{
+ /* 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 MEDANY_BASE_REG. */
+ are accessed with EMBMEDANY_BASE_REG. */
int
data_segment_operand (op, mode)
@@ -361,7 +600,8 @@ data_segment_operand (op, mode)
case SYMBOL_REF :
return ! SYMBOL_REF_FLAG (op);
case PLUS :
- /* Assume canonical format of symbol + constant. */
+ /* Assume canonical format of symbol + constant.
+ Fall through. */
case CONST :
return data_segment_operand (XEXP (op, 0));
default :
@@ -384,7 +624,8 @@ text_segment_operand (op, mode)
case SYMBOL_REF :
return SYMBOL_REF_FLAG (op);
case PLUS :
- /* Assume canonical format of symbol + constant. */
+ /* Assume canonical format of symbol + constant.
+ Fall through. */
case CONST :
return text_segment_operand (XEXP (op, 0));
default :
@@ -442,7 +683,7 @@ move_operand (op, mode)
if (register_operand (op, mode))
return 1;
if (GET_CODE (op) == CONST_INT)
- return (SMALL_INT (op) || (INTVAL (op) & 0x3ff) == 0);
+ return SMALL_INT (op) || SPARC_SETHI_P (INTVAL (op));
if (GET_MODE (op) != mode)
return 0;
@@ -458,17 +699,6 @@ move_operand (op, mode)
}
int
-move_pic_label (op, mode)
- rtx op;
- enum machine_mode mode;
-{
- /* Special case for PIC. */
- if (flag_pic && GET_CODE (op) == LABEL_REF)
- return 1;
- return 0;
-}
-
-int
splittable_symbolic_memory_operand (op, mode)
rtx op;
enum machine_mode mode;
@@ -598,9 +828,9 @@ cc_arithopn (op, mode)
|| GET_CODE (op) == IOR);
}
-/* Return true if OP is a register, or is a CONST_INT that can fit in a 13
- bit immediate field. This is an acceptable SImode operand for most 3
- address instructions. */
+/* 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)
@@ -611,9 +841,9 @@ arith_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
}
-/* Return true if OP is a register, or is a CONST_INT that can fit in an 11
- bit immediate field. This is an acceptable SImode operand for the movcc
- instructions. */
+/* 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)
@@ -621,13 +851,12 @@ arith11_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
- && ((unsigned) (INTVAL (op) + 0x400) < 0x800)));
+ || (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 an 10
- bit immediate field. This is an acceptable SImode operand for the movrcc
- instructions. */
+/* 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)
@@ -635,8 +864,7 @@ arith10_operand (op, mode)
enum machine_mode mode;
{
return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
- && ((unsigned) (INTVAL (op) + 0x200) < 0x400)));
+ || (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
@@ -653,13 +881,13 @@ arith_double_operand (op, mode)
{
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_INT && SMALL_INT (op))
- || (! TARGET_V9
+ || (! TARGET_ARCH64
&& GET_CODE (op) == CONST_DOUBLE
- && (unsigned) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
- && (unsigned) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000)
- || (TARGET_V9
+ && (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) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
+ && (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
@@ -679,14 +907,14 @@ arith11_double_operand (op, mode)
return (register_operand (op, mode)
|| (GET_CODE (op) == CONST_DOUBLE
&& (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800
+ && (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) (INTVAL (op) + 0x400) < 0x800));
+ && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800));
}
/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
@@ -709,7 +937,7 @@ arith10_double_operand (op, mode)
&& (CONST_DOUBLE_LOW (op) & 0x200) == 0)))
|| (GET_CODE (op) == CONST_INT
&& (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned) (INTVAL (op) + 0x200) < 0x400));
+ && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400));
}
/* Return truth value of whether OP is a integer which fits the
@@ -775,7 +1003,7 @@ gen_compare_reg (code, x, y)
rtx cc_reg;
/* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
- fpcc regs (cse can't tell they're really call clobbered regs and will
+ 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
@@ -795,8 +1023,8 @@ gen_compare_reg (code, x, y)
{
int reg;
/* We cycle through the registers to ensure they're all exercised. */
- static int next_fpcc_reg = 0;
- /* Previous x,y for each fpcc reg. */
+ 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. */
@@ -805,18 +1033,20 @@ gen_compare_reg (code, x, y)
break;
if (reg == 4)
{
- reg = next_fpcc_reg;
+ reg = next_fcc_reg;
prev_args[reg][0] = x;
prev_args[reg][1] = y;
- next_fpcc_reg = (next_fpcc_reg + 1) & 3;
+ next_fcc_reg = (next_fcc_reg + 1) & 3;
}
- cc_reg = gen_rtx (REG, mode, reg + 96);
+ 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, 0);
+ cc_reg = gen_rtx (REG, mode, SPARC_ICC_REG);
emit_insn (gen_rtx (SET, VOIDmode, cc_reg,
gen_rtx (COMPARE, mode, x, y)));
@@ -833,11 +1063,11 @@ gen_compare_reg (code, x, y)
This function is needed to turn
(set (reg:SI 110)
- (gt (reg:CCX 0 %g0)
+ (gt (reg:CCX 100 %icc)
(const_int 0)))
into
(set (reg:SI 110)
- (gt:DI (reg:CCX 0 %g0)
+ (gt:DI (reg:CCX 100 %icc)
(const_int 0)))
IE: The instruction recognizer needs to see the mode of the comparison to
@@ -845,61 +1075,66 @@ gen_compare_reg (code, x, y)
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.
-
- ??? Some of this is outdated as the scc insns set the mode of the
- comparison now.
-
- ??? We optimize for the case where op1 is 0 and the comparison allows us to
- use the "movrCC" insns. This reduces the generated code from three to two
- insns. This way seems too brute force though. Is there a more elegant way
- to achieve the same effect?
-
- Currently, this function always returns 1. ??? Can it ever fail? */
+ sparc_compare_op1. */
int
gen_v9_scc (compare_code, operands)
enum rtx_code compare_code;
register rtx *operands;
{
- rtx temp;
+ rtx temp, op0, op1;
- if (GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT
- && sparc_compare_op1 == const0_rtx
- && (compare_code == EQ || compare_code == NE
- || compare_code == LT || compare_code == LE
- || compare_code == GT || compare_code == GE))
+ 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
- op0 can be clobbered. We store to a temp, and then clobber the temp,
- but the combiner will remove the first insn. */
+ 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 (sparc_compare_op0) == DImode)
+ && GET_MODE (op0) == DImode)
{
- emit_insn (gen_rtx (SET, VOIDmode, operands[0], sparc_compare_op0));
+ emit_insn (gen_rtx (SET, VOIDmode, operands[0], op0));
emit_insn (gen_rtx (SET, VOIDmode, operands[0],
- gen_rtx (IF_THEN_ELSE, VOIDmode,
+ gen_rtx (IF_THEN_ELSE, DImode,
gen_rtx (compare_code, DImode,
- sparc_compare_op0, const0_rtx),
+ op0, const0_rtx),
const1_rtx,
operands[0])));
return 1;
}
emit_insn (gen_rtx (SET, VOIDmode, operands[0], const0_rtx));
- if (GET_MODE (sparc_compare_op0) != DImode)
+ if (GET_MODE (op0) != DImode)
{
temp = gen_reg_rtx (DImode);
- convert_move (temp, sparc_compare_op0, 0);
+ convert_move (temp, op0, 0);
}
else
- {
- temp = sparc_compare_op0;
- }
+ temp = op0;
emit_insn (gen_rtx (SET, VOIDmode, operands[0],
- gen_rtx (IF_THEN_ELSE, VOIDmode,
+ gen_rtx (IF_THEN_ELSE, GET_MODE (operands[0]),
gen_rtx (compare_code, DImode,
temp, const0_rtx),
const1_rtx,
@@ -908,8 +1143,7 @@ gen_v9_scc (compare_code, operands)
}
else
{
- operands[1] = gen_compare_reg (compare_code,
- sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (compare_code, op0, op1);
switch (GET_MODE (operands[1]))
{
@@ -921,14 +1155,14 @@ gen_v9_scc (compare_code, operands)
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, VOIDmode,
- gen_rtx (compare_code,
- GET_MODE (operands[1]),
- operands[1], const0_rtx),
- const1_rtx, operands[0])));
- return 1;
+ 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 (compare_code,
+ GET_MODE (operands[1]),
+ operands[1], const0_rtx),
+ const1_rtx, operands[0])));
+ return 1;
}
}
@@ -970,60 +1204,85 @@ eligible_for_epilogue_delay (trial, slot)
if (slot >= 1)
return 0;
- if (GET_CODE (trial) != INSN
- || GET_CODE (PATTERN (trial)) != SET)
+
+ 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 ((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. */
- pat = PATTERN (trial);
if (GET_CODE (SET_DEST (pat)) != REG
- || REGNO (SET_DEST (pat)) == 0
|| 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]". */
if (arith_operand (src, GET_MODE (src)))
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
- if (arith_double_operand (src, GET_MODE (src)))
+
+ /* This matches "*return_di". */
+ else if (arith_double_operand (src, GET_MODE (src)))
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (DImode);
- if (GET_CODE (src) == PLUS)
- {
- if (register_operand (XEXP (src, 0), SImode)
- && arith_operand (XEXP (src, 1), SImode))
- return 1;
- if (register_operand (XEXP (src, 1), SImode)
- && arith_operand (XEXP (src, 0), SImode))
- return 1;
- if (register_operand (XEXP (src, 0), DImode)
- && arith_double_operand (XEXP (src, 1), DImode))
- return 1;
- if (register_operand (XEXP (src, 1), DImode)
- && arith_double_operand (XEXP (src, 0), DImode))
- return 1;
- }
- if (GET_CODE (src) == MINUS
- && register_operand (XEXP (src, 0), SImode)
- && small_int (XEXP (src, 1), VOIDmode))
+
+ /* 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;
- if (GET_CODE (src) == MINUS
- && register_operand (XEXP (src, 0), DImode)
- && !register_operand (XEXP (src, 1), DImode)
- && arith_double_operand (XEXP (src, 1), DImode))
+
+ /* This matches "*return_subsi". */
+ else if (GET_CODE (src) == MINUS
+ && register_operand (XEXP (src, 0), SImode)
+ && small_int (XEXP (src, 1), VOIDmode)
+ && INTVAL (XEXP (src, 1)) != -4096)
return 1;
+
return 0;
}
@@ -1073,9 +1332,8 @@ reg_unused_after (reg, insn)
return 1;
}
-/* The rtx for the global offset table which is a special form
- that *is* a position independent symbolic constant. */
-static rtx pic_pc_rtx;
+/* The table we use to reference PIC data. */
+static rtx global_offset_table;
/* Ensure that we are not using patterns that are not OK with PIC. */
@@ -1088,7 +1346,11 @@ check_pic (i)
case 1:
if (GET_CODE (recog_operand[i]) == SYMBOL_REF
|| (GET_CODE (recog_operand[i]) == CONST
- && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
+ && ! (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:
@@ -1149,16 +1411,9 @@ legitimize_pic_address (orig, mode, reg)
won't get confused into thinking that these two instructions
are loading in the true address of the symbol. If in the
future a PIC rtx exists, that should be used instead. */
- emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
- gen_rtx (HIGH, Pmode,
- gen_rtx (UNSPEC, Pmode,
- gen_rtvec (1, orig),
- 0))));
- emit_insn (gen_rtx (SET, VOIDmode, temp_reg,
- gen_rtx (LO_SUM, Pmode, temp_reg,
- gen_rtx (UNSPEC, Pmode,
- gen_rtvec (1, orig),
- 0))));
+ 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
@@ -1214,6 +1469,7 @@ legitimize_pic_address (orig, mode, reg)
return gen_rtx (PLUS, Pmode, base, offset);
}
else if (GET_CODE (orig) == LABEL_REF)
+ /* ??? Why do we do this? */
current_function_uses_pic_offset_table = 1;
return orig;
@@ -1227,56 +1483,47 @@ initialize_pic ()
{
}
-/* Emit special PIC prologues and epilogues. */
+/* Return the RTX for insns to set the PIC register. */
-void
-finalize_pic ()
+static rtx
+pic_setup_code ()
{
- /* The table we use to reference PIC data. */
- rtx global_offset_table;
- /* Labels to get the PC in the prologue of this function. */
+ rtx pic_pc_rtx;
rtx l1, l2;
rtx seq;
- int orig_flag_pic = flag_pic;
-
- if (current_function_uses_pic_offset_table == 0)
- return;
-
- if (! flag_pic)
- abort ();
-
- flag_pic = 0;
- l1 = gen_label_rtx ();
- l2 = gen_label_rtx ();
start_sequence ();
- emit_label (l1);
- /* Note that we pun calls and jumps here! */
- emit_jump_insn (gen_rtx (PARALLEL, VOIDmode,
- gen_rtvec (2,
- gen_rtx (SET, VOIDmode, pc_rtx, gen_rtx (LABEL_REF, VOIDmode, l2)),
- gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, 15), gen_rtx (LABEL_REF, VOIDmode, l2)))));
- emit_label (l2);
+ l1 = gen_label_rtx ();
- /* 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_");
pic_pc_rtx = gen_rtx (CONST, Pmode,
gen_rtx (MINUS, Pmode,
global_offset_table,
gen_rtx (CONST, Pmode,
gen_rtx (MINUS, Pmode,
- gen_rtx (LABEL_REF, VOIDmode, l1),
+ gen_rtx (LABEL_REF,
+ VOIDmode, l1),
pc_rtx))));
- if (Pmode == DImode)
- emit_insn (gen_rtx (PARALLEL, VOIDmode,
- gen_rtvec (2,
- gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
- gen_rtx (HIGH, Pmode, pic_pc_rtx)),
- gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, Pmode, 1)))));
- else
+ /* sparc64: the RDPC instruction doesn't pair, and puts 4 bubbles in the
+ pipe to boot. So don't use it here, especially when we're
+ doing a save anyway because of %l7. */
+
+ l2 = gen_label_rtx ();
+ emit_label (l1);
+
+ /* Iff we are doing delay branch optimization, slot the sethi up
+ here so that it will fill the delay slot of the call. */
+ if (flag_delayed_branch)
+ emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
+ gen_rtx (HIGH, Pmode, pic_pc_rtx)));
+
+ /* Note that we pun calls and jumps here! */
+ emit_jump_insn (gen_get_pc_via_call (l2, l1));
+
+ emit_label (l2);
+
+ if (!flag_delayed_branch)
emit_insn (gen_rtx (SET, VOIDmode, pic_offset_table_rtx,
gen_rtx (HIGH, Pmode, pic_pc_rtx)));
@@ -1287,18 +1534,53 @@ finalize_pic ()
emit_insn (gen_rtx (SET, VOIDmode,
pic_offset_table_rtx,
gen_rtx (PLUS, Pmode,
- pic_offset_table_rtx, gen_rtx (REG, Pmode, 15))));
+ pic_offset_table_rtx,
+ gen_rtx (REG, Pmode, 15))));
+
/* emit_insn (gen_rtx (ASM_INPUT, VOIDmode, "!#PROLOGUE# 1")); */
LABEL_PRESERVE_P (l1) = 1;
LABEL_PRESERVE_P (l2) = 1;
- flag_pic = orig_flag_pic;
seq = gen_sequence ();
end_sequence ();
- emit_insn_after (seq, get_insns ());
+
+ 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 ();
+
+ /* 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_");
+ 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. */
+ 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));
}
@@ -1338,7 +1620,8 @@ emit_move_sequence (operands, mode)
}
else if (GET_CODE (operand0) == MEM)
{
- if (register_operand (operand1, mode) || operand1 == const0_rtx)
+ if (register_operand (operand1, mode)
+ || (operand1 == const0_rtx && ! TARGET_LIVE_G0))
{
/* Run this case quickly. */
emit_insn (gen_rtx (SET, VOIDmode, operand0, operand1));
@@ -1351,10 +1634,33 @@ emit_move_sequence (operands, mode)
}
}
- /* Simplify the source if we need to. Must handle DImode HIGH operators
- here because such a move needs a clobber added. */
- if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
- || (GET_CODE (operand1) == HIGH && GET_MODE (operand1) == DImode))
+ if (GET_CODE (operand1) == LABEL_REF
+ && mode == SImode && flag_pic)
+ {
+ if (TARGET_ARCH64)
+ abort ();
+ emit_insn (gen_move_pic_label_si (operand0, operand1));
+ return 1;
+ }
+ /* Non-pic LABEL_REF's in sparc64 are expensive to do the normal way,
+ so always use special code. */
+ else if (GET_CODE (operand1) == LABEL_REF
+ && mode == DImode)
+ {
+ if (! TARGET_ARCH64)
+ abort ();
+ emit_insn (gen_move_label_di (operand0, operand1));
+ return 1;
+ }
+ /* DImode HIGH values in sparc64 need a clobber added. */
+ else 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))
{
@@ -1364,10 +1670,10 @@ emit_move_sequence (operands, mode)
}
else if (GET_CODE (operand1) == CONST_INT
? (! SMALL_INT (operand1)
- && (INTVAL (operand1) & 0x3ff) != 0)
- : (GET_CODE (operand1) == CONST_DOUBLE
- ? ! arith_double_operand (operand1, DImode)
- : 1))
+ && ! 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
@@ -1385,59 +1691,31 @@ emit_move_sequence (operands, mode)
rtx temp = ((reload_in_progress || mode == DImode)
? operand0 : gen_reg_rtx (mode));
- if (TARGET_V9 && mode == DImode)
- {
- int high_operand = 0;
-
- /* If the operand is already a HIGH, then remove the HIGH so
- that we won't get duplicate HIGH operators in this insn.
- Also, we must store the result into the original dest,
- because that is where the following LO_SUM expects it. */
- if (GET_CODE (operand1) == HIGH)
- {
- operand1 = XEXP (operand1, 0);
- high_operand = 1;
- }
-
- emit_insn (gen_rtx (PARALLEL, VOIDmode,
- gen_rtvec (2,
- gen_rtx (SET, VOIDmode, temp,
- gen_rtx (HIGH, mode, operand1)),
- gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, DImode, 1)))));
-
- /* If this was a high operand, then we are now finished. */
- if (high_operand)
- return 1;
- }
+ 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)));
+ 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);
operands[1] = gen_rtx (LO_SUM, mode, temp, operand1);
}
}
- if (GET_CODE (operand1) == LABEL_REF && flag_pic)
- {
- /* The procedure for doing this involves using a call instruction to
- get the pc into o7. We need to indicate this explicitly because
- the tablejump pattern assumes that it can use this value also. */
- emit_insn (gen_rtx (PARALLEL, VOIDmode,
- gen_rtvec (2,
- gen_rtx (SET, VOIDmode, operand0,
- operand1),
- gen_rtx (SET, VOIDmode,
- gen_rtx (REG, mode, 15),
- pc_rtx))));
- return 1;
- }
-
/* 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 fullword. */
+ 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)
@@ -1463,7 +1741,7 @@ singlemove_string (operands)
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
REAL_VALUE_TO_TARGET_SINGLE (r, i);
- operands[1] = gen_rtx (CONST_INT, VOIDmode, i);
+ operands[1] = GEN_INT (i);
if (CONST_OK_FOR_LETTER_P (i, 'I'))
return "mov %1,%0";
@@ -1475,10 +1753,11 @@ singlemove_string (operands)
else if (GET_CODE (operands[1]) == CONST_INT
&& ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
{
- int i = INTVAL (operands[1]);
+ HOST_WIDE_INT i = INTVAL (operands[1]);
/* 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
@@ -1487,7 +1766,59 @@ singlemove_string (operands)
/* 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. */
@@ -1629,7 +1960,7 @@ output_move_double (operands)
latehalf[1] = adj_offsettable_operand (op1, 4);
else if (optype1 == CNSTOP)
{
- if (TARGET_V9)
+ if (TARGET_ARCH64)
{
if (arith_double_operand (op1, DImode))
{
@@ -1657,9 +1988,9 @@ output_move_double (operands)
/* 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_V9 || (REGNO (op0) & 1) == 0))
+ && (TARGET_ARCH64 || (REGNO (op0) & 1) == 0))
|| (optype0 != REGOP && optype0 != CNSTOP && optype1 == REGOP
- && (TARGET_V9 || (REGNO (op1) & 1) == 0)))
+ && (TARGET_ARCH64 || (REGNO (op1) & 1) == 0)))
{
register rtx mem,reg;
@@ -1678,14 +2009,14 @@ output_move_double (operands)
the register number. */
|| (TARGET_V9 && REGNO (reg) >= 64))
{
- if (FP_REG_P (reg) || ! TARGET_V9)
+ 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_V9)
+ if (TARGET_ARCH64)
{
if (optype0 == REGOP && optype1 == REGOP)
{
@@ -1828,17 +2159,25 @@ output_move_quad (operands)
if (optype0 == REGOP)
{
- wordpart[0][0] = gen_rtx (REG, SImode, REGNO (op0) + 0);
- wordpart[1][0] = gen_rtx (REG, SImode, REGNO (op0) + 1);
- wordpart[2][0] = gen_rtx (REG, SImode, REGNO (op0) + 2);
- wordpart[3][0] = gen_rtx (REG, SImode, REGNO (op0) + 3);
+ wordpart[0][0] = gen_rtx (REG, word_mode, REGNO (op0) + 0);
+ 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);
+ }
}
else if (optype0 == OFFSOP)
{
wordpart[0][0] = adj_offsettable_operand (op0, 0);
- wordpart[1][0] = adj_offsettable_operand (op0, 4);
- wordpart[2][0] = adj_offsettable_operand (op0, 8);
- wordpart[3][0] = adj_offsettable_operand (op0, 12);
+ 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
{
@@ -1850,17 +2189,25 @@ output_move_quad (operands)
if (optype1 == REGOP)
{
- wordpart[0][1] = gen_rtx (REG, SImode, REGNO (op1) + 0);
- wordpart[1][1] = gen_rtx (REG, SImode, REGNO (op1) + 1);
- wordpart[2][1] = gen_rtx (REG, SImode, REGNO (op1) + 2);
- wordpart[3][1] = gen_rtx (REG, SImode, REGNO (op1) + 3);
+ wordpart[0][1] = gen_rtx (REG, word_mode, REGNO (op1) + 0);
+ 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);
- wordpart[1][1] = adj_offsettable_operand (op1, 4);
- wordpart[2][1] = adj_offsettable_operand (op1, 8);
- wordpart[3][1] = adj_offsettable_operand (op1, 12);
+ 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)
{
@@ -1907,40 +2254,57 @@ output_move_quad (operands)
/* 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))
+ || (TARGET_V9 && REGNO (reg) >= SPARC_FIRST_V9_FP_REG))
{
- if (TARGET_V9 && FP_REG_P (reg))
+ if (TARGET_V9 && FP_REG_P (reg) && TARGET_HARD_QUAD)
{
if ((REGNO (reg) & 3) != 0)
abort ();
+ /* ??? Can `mem' have an inappropriate alignment here? */
return (mem == op1 ? "ldq %1,%0" : "stq %1,%0");
}
operands[2] = adj_offsettable_operand (mem, 8);
+ /* ??? In arch64 case, shouldn't we use ldd/std for fp regs. */
if (mem == op1)
- return TARGET_V9 ? "ldx %1,%0;ldx %2,%R0" : "ldd %1,%0;ldd %2,%S0";
+ return TARGET_ARCH64 ? "ldx %1,%0;ldx %2,%R0" : "ldd %1,%0;ldd %2,%S0";
else
- return TARGET_V9 ? "stx %1,%0;stx %R1,%2" : "std %1,%0;std %S1,%2";
+ return TARGET_ARCH64 ? "stx %1,%0;stx %R1,%2" : "std %1,%0;std %S1,%2";
}
}
/* 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 (wordpart[1][3])
- || REGNO (op0) == REGNO (wordpart[1][2])
- || REGNO (op0) == REGNO (wordpart[1][1])))
+ /* Overlapping registers? */
+ if (TARGET_ARCH32)
{
- /* 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. */
- return singlemove_string (wordpart[0]);
+ 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 "";
+ }
+ }
+
/* Loading into a register which overlaps a register used in the address. */
if (optype0 == REGOP && optype1 != REGOP
&& reg_overlap_mentioned_p (op0, op1))
@@ -1953,42 +2317,64 @@ output_move_quad (operands)
abort ();
}
- /* Normal case: move the four words in lowest to highest address order. */
+ /* Normal case: move the words in lowest to highest address order. */
- output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]);
+ if (TARGET_ARCH32)
+ {
+ output_asm_insn (singlemove_string (wordpart[0]), wordpart[0]);
- /* Make any unoffsettable addresses point at the second word. */
- if (addreg0)
- output_asm_insn ("add %0,0x4,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,0x4,%0", &addreg1);
+ /* Make any unoffsettable addresses point at the second word. */
+ if (addreg0)
+ output_asm_insn ("add %0,0x4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,0x4,%0", &addreg1);
- /* Do the second word. */
- output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
+ /* Do the second word. */
+ output_asm_insn (singlemove_string (wordpart[1]), wordpart[1]);
- /* Make any unoffsettable addresses point at the third word. */
- if (addreg0)
- output_asm_insn ("add %0,0x4,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,0x4,%0", &addreg1);
+ /* Make any unoffsettable addresses point at the third word. */
+ if (addreg0)
+ output_asm_insn ("add %0,0x4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,0x4,%0", &addreg1);
- /* Do the third word. */
- output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
+ /* Do the third word. */
+ output_asm_insn (singlemove_string (wordpart[2]), wordpart[2]);
- /* Make any unoffsettable addresses point at the fourth word. */
- if (addreg0)
- output_asm_insn ("add %0,0x4,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,0x4,%0", &addreg1);
+ /* Make any unoffsettable addresses point at the fourth word. */
+ if (addreg0)
+ output_asm_insn ("add %0,0x4,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,0x4,%0", &addreg1);
- /* Do the fourth word. */
- output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
+ /* Do the fourth word. */
+ output_asm_insn (singlemove_string (wordpart[3]), wordpart[3]);
- /* Undo the adds we just did. */
- if (addreg0)
- output_asm_insn ("add %0,-0xc,%0", &addreg0);
- if (addreg1)
- output_asm_insn ("add %0,-0xc,%0", &addreg1);
+ /* Undo the adds we just did. */
+ if (addreg0)
+ output_asm_insn ("add %0,-0xc,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,-0xc,%0", &addreg1);
+ }
+ else /* TARGET_ARCH64 */
+ {
+ output_asm_insn (doublemove_string (wordpart[0]), wordpart[0]);
+
+ /* Make any unoffsettable addresses point at the second word. */
+ 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. */
+ if (addreg0)
+ output_asm_insn ("add %0,-0x8,%0", &addreg0);
+ if (addreg1)
+ output_asm_insn ("add %0,-0x8,%0", &addreg1);
+ }
return "";
}
@@ -2038,8 +2424,10 @@ output_fp_move_quad (operands)
{
if (FP_REG_P (op1))
{
- if (TARGET_V9)
+ if (TARGET_V9 && TARGET_HARD_QUAD)
return "fmovq %1,%0";
+ else if (TARGET_V9)
+ return "fmovd %1,%0\n\tfmovd %S1,%S0";
else
return "fmovs %1,%0\n\tfmovs %R1,%R0\n\tfmovs %S1,%S0\n\tfmovs %T1,%T0";
}
@@ -2113,7 +2501,7 @@ output_sized_memop (opname, mode, signedp)
fprintf (asm_out_file, "\t%s%s", opname, modename);
}
-
+
void
output_move_with_extension (operands)
rtx *operands;
@@ -2300,7 +2688,7 @@ output_block_move (operands)
if (align > UNITS_PER_WORD)
abort ();
- if (TARGET_V9 && align >= 8)
+ if (TARGET_ARCH64 && align >= 8)
{
for (i = (size >> 3) - 1; i >= 0; i--)
{
@@ -2421,9 +2809,9 @@ output_block_move (operands)
{
char pattern[200];
register char *ld_suffix = ((align == 1) ? "ub" : (align == 2) ? "uh"
- : (align == 8 && TARGET_V9) ? "x" : "");
+ : (align == 8 && TARGET_ARCH64) ? "x" : "");
register char *st_suffix = ((align == 1) ? "b" : (align == 2) ? "h"
- : (align == 8 && TARGET_V9) ? "x" : "");
+ : (align == 8 && TARGET_ARCH64) ? "x" : "");
sprintf (pattern, "ld%s [%%1+%%2],%%%%g1\n\tsubcc %%2,%%4,%%2\n\tbge %s\n\tst%s %%%%g1,[%%0+%%2]\n%s:", ld_suffix, &label3[1], st_suffix, &label5[1]);
output_asm_insn (pattern, xoperands);
@@ -2484,7 +2872,8 @@ output_scc_insn (operands, insn)
LABEL_NUSES (label) += 1;
- operands[2] = label;
+ /* operands[3] is an unused slot. */
+ operands[3] = label;
/* If we are in a delay slot, assume it is the delay slot of an fpcc
insn since our type isn't allowed anywhere else. */
@@ -2507,17 +2896,17 @@ output_scc_insn (operands, insn)
if (final_sequence)
{
strcpy (string, "mov 0,%0\n\t");
- strcat (string, output_cbranch (operands[1], 0, 2, 0, 1, 0));
+ strcat (string, output_cbranch (operands[2], 3, 0, 1, 0));
strcat (string, "\n\tmov 1,%0");
}
else
{
- strcpy (string, output_cbranch (operands[1], 0, 2, 0, 1, 0));
+ strcpy (string, output_cbranch (operands[2], 3, 0, 1, 0));
strcat (string, "\n\tmov 1,%0\n\tmov 0,%0");
}
if (need_label)
- strcat (string, "\n%l2:");
+ strcat (string, "\n%l3:");
return string;
}
@@ -2532,15 +2921,11 @@ output_scc_insn (operands, insn)
mapped into one sparc_mode_class mode. */
enum sparc_mode_class {
- C_MODE, CCFP_MODE,
S_MODE, D_MODE, T_MODE, O_MODE,
- SF_MODE, DF_MODE, TF_MODE, OF_MODE
+ SF_MODE, DF_MODE, TF_MODE, OF_MODE,
+ CC_MODE, CCFP_MODE
};
-/* Modes for condition codes. */
-#define C_MODES ((1 << (int) C_MODE) | (1 << (int) CCFP_MODE))
-#define CCFP_MODES (1 << (int) CCFP_MODE)
-
/* Modes for single-word and smaller quantities. */
#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
@@ -2562,7 +2947,8 @@ enum sparc_mode_class {
#define DF_MODES64 (SF_MODES | DF_MODE /* | D_MODE*/)
/* Modes for double-float only quantities. */
-/* ??? Sparc64 fp regs cannot hold DImode values. */
+/* ??? Sparc64 fp regs cannot hold DImode values.
+ See fix_truncsfdi2. */
#define DF_ONLY_MODES ((1 << (int) DF_MODE) /*| (1 << (int) D_MODE)*/)
/* Modes for double-float and larger quantities. */
@@ -2574,20 +2960,25 @@ enum sparc_mode_class {
/* Modes for quad-float and smaller quantities. */
#define TF_MODES (DF_MODES | TF_ONLY_MODES)
-/* ??? Sparc64 fp regs cannot hold DImode values. */
+/* ??? Sparc64 fp regs cannot hold DImode values.
+ See fix_truncsfdi2. */
#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. */
+ 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[] = {
- C_MODES, S_MODES, T_MODES, S_MODES, T_MODES, S_MODES, D_MODES, S_MODES,
+ 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,
@@ -2596,10 +2987,23 @@ static int hard_32bit_mode_classes[] = {
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[] = {
- C_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES, T_MODES, D_MODES,
+ 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,
@@ -2609,8 +3013,7 @@ static int hard_64bit_mode_classes[] = {
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,
- /* The remaining registers do not exist on a non-v9 sparc machine.
- FP regs f32 to f63. Only the even numbered registers actually exist,
+ /* 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,
@@ -2618,18 +3021,21 @@ static int hard_64bit_mode_classes[] = {
DF_UP_MODES, 0, DF_ONLY_MODES, 0, DF_UP_MODES, 0, DF_ONLY_MODES, 0,
/* %fcc[0123] */
- CCFP_MODE, CCFP_MODE, CCFP_MODE, CCFP_MODE
+ 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;
- sparc_arch_type = TARGET_V9 ? ARCH_64BIT : ARCH_32BIT;
-
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
switch (GET_MODE_CLASS (i))
@@ -2668,49 +3074,62 @@ sparc_init_modes ()
if (i == (int) CCFPmode || i == (int) CCFPEmode)
sparc_mode_class[i] = 1 << (int) CCFP_MODE;
else if (i == (int) CCmode || i == (int) CC_NOOVmode
-#ifdef SPARCV9
- || i == (int) CCXmode
- || i == (int) CCX_NOOVmode
-#endif
- )
- sparc_mode_class[i] = 1 << (int) C_MODE;
+ || i == (int) CCXmode || i == (int) CCX_NOOVmode)
+ sparc_mode_class[i] = 1 << (int) CC_MODE;
else
sparc_mode_class[i] = 0;
break;
}
}
- if (TARGET_V9)
+ 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 < 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. */
-#ifdef __GNUC__
-__inline__
-#endif
static int
-save_regs (file, low, high, base, offset, n_regs)
+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_V9 && high <= 32)
+ 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),
- n_regs += 2;
+ {
+ 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
@@ -2719,17 +3138,33 @@ save_regs (file, low, high, base, offset, n_regs)
{
if (regs_ever_live[i] && ! call_used_regs[i])
if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tstd %s,[%s+%d]\n",
- reg_names[i], base, offset + 4 * n_regs),
- n_regs += 2;
+ {
+ 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], base, offset + 4 * n_regs),
+ 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;
- 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),
- n_regs += 2;
+ }
}
}
return n_regs;
@@ -2740,9 +3175,6 @@ save_regs (file, low, high, base, offset, n_regs)
N_REGS is the number of 4-byte regs saved thus far. This applies even to
v9 int regs as it simplifies the code. */
-#ifdef __GNUC__
-__inline__
-#endif
static int
restore_regs (file, low, high, base, offset, n_regs)
FILE *file;
@@ -2753,7 +3185,7 @@ restore_regs (file, low, high, base, offset, n_regs)
{
int i;
- if (TARGET_V9 && high <= 32)
+ if (TARGET_ARCH64 && high <= 32)
{
for (i = low; i < high; i++)
{
@@ -2801,17 +3233,14 @@ compute_frame_size (size, leaf_function)
{
int n_regs = 0, i;
int outgoing_args_size = (current_function_outgoing_args_size
-#ifndef SPARCV9
- + REG_PARM_STACK_SPACE (current_function_decl)
-#endif
- );
+ + 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_V9)
+ if (TARGET_ARCH64)
{
for (i = 0; i < 8; i++)
if (regs_ever_live[i] && ! call_used_regs[i])
@@ -2851,10 +3280,9 @@ compute_frame_size (size, leaf_function)
/* 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 v9 we need an additional 8 bytes of reserved space, apparently
- it's needed by v8 as well. */
+ ??? For v8 we apparently need an additional 8 bytes of reserved space. */
if (leaf_function == 0 || size > 0)
- actual_fsize += (16 * UNITS_PER_WORD) + 8;
+ actual_fsize += (16 * UNITS_PER_WORD) + (TARGET_ARCH64 ? 0 : 8);
return SPARC_STACK_ALIGN (actual_fsize);
}
@@ -2868,13 +3296,13 @@ build_big_number (file, num, reg)
int num;
char *reg;
{
- if (num >= 0 || ! TARGET_V9)
+ 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_V9 */
+ 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
@@ -2914,50 +3342,93 @@ output_function_prologue (file, size, leaf_function)
}
/* This is only for the human reader. */
- fprintf (file, "\t!#PROLOGUE# 0\n");
+ fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START);
if (actual_fsize == 0)
/* do nothing. */ ;
- else if (actual_fsize <= 4096)
+ else if (! leaf_function && ! TARGET_BROKEN_SAVERESTORE)
{
- if (! leaf_function)
+ 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
- fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize);
+ {
+ build_big_number (file, -actual_fsize, "%g1");
+ fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
+ }
}
- else if (actual_fsize <= 8192)
+ else if (! leaf_function && TARGET_BROKEN_SAVERESTORE)
{
- /* For frames in the range 4097..8192, we can use just two insns. */
- if (! leaf_function)
+ /* 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, "\tsave %%sp,-4096,%%sp\n");
- fprintf (file, "\tadd %%sp,-%d,%%sp\n", actual_fsize - 4096);
+ 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");
+ }
}
- else
+
+ if (dwarf2out_do_frame () && actual_fsize)
{
- build_big_number (file, -actual_fsize, "%g1");
+ 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)
- fprintf (file, "\tsave %%sp,%%g1,%%sp\n");
- else
- fprintf (file, "\tadd %%sp,%%g1,%%sp\n");
+ {
+ /* 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!#PROLOGUE# 1\n");
+ 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, n_regs;
+ 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)
{
@@ -2979,12 +3450,13 @@ output_function_prologue (file, size, leaf_function)
if (TARGET_EPILOGUE && ! leaf_function)
/* ??? Originally saved regs 0-15 here. */
- n_regs = save_regs (file, 0, 8, base, offset, 0);
+ 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);
+ 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);
+ save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs,
+ real_offset);
}
leaf_label = 0;
@@ -3012,6 +3484,13 @@ output_function_epilogue (file, size, leaf_function)
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
+
/* Restore any call saved registers. */
if (num_gfregs)
{
@@ -3099,87 +3578,671 @@ output_function_epilogue (file, size, leaf_function)
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. */
-/* Do what is necessary for `va_start'. The argument is ignored.
- !v9: We look at the current function to determine if stdarg or varargs
- is used and return the address of the first unnamed parameter.
- v9: We save the argument integer and floating point regs in a buffer, and
- return the address of this buffer. The rest is handled in va-sparc.h. */
-/* ??? This is currently conditioned on #ifdef SPARCV9 because
- current_function_args_info is different in each compiler. */
+void
+init_cumulative_args (cum, fntype, libname, indirect)
+ CUMULATIVE_ARGS *cum;
+ tree fntype, libname;
+ int indirect;
+{
+ cum->words = 0;
+ cum->prototype_p = fntype && TYPE_ARG_TYPES (fntype);
+ cum->libcall_p = fntype == 0;
+}
-#ifdef SPARCV9
+/* 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 0;
+ 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 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
-sparc_builtin_saveregs (arglist)
- tree arglist;
+function_arg (cum, mode, type, named, incoming_p)
+ const CUMULATIVE_ARGS *cum;
+ enum machine_mode mode;
+ tree type;
+ int named;
+ int incoming_p;
{
- tree fntype = TREE_TYPE (current_function_decl);
- /* First unnamed integer register. */
- int first_intreg = current_function_args_info.arg_count[(int) SPARC_ARG_INT];
- /* Number of integer registers we need to save. */
- int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg);
- /* First unnamed SFmode float reg (no, you can't pass SFmode floats as
- unnamed arguments, we just number them that way). We must round up to
- the next double word float reg - that is the first one to save. */
- int first_floatreg = current_function_args_info.arg_count[(int) SPARC_ARG_FLOAT] + 1 & ~1;
- /* Number of SFmode float regs to save. */
- int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
- int ptrsize = GET_MODE_SIZE (Pmode);
- rtx valist, regbuf, fpregs;
- int bufsize, adjust, regno;
-
- /* Allocate block of memory for the regs.
- We only allocate as much as we need, but we must ensure quadword float
- regs are stored with the appropriate alignment. */
- /* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte?
- Or can assign_stack_local accept a 0 SIZE argument? */
-
- bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * (UNITS_PER_WORD / 2));
- /* Add space in front of the int regs to ensure proper alignment of quadword
- fp regs. We must add the space in front because va_start assumes this. */
- if (n_floatregs >= 4)
- adjust = ((n_intregs + first_floatreg / 2) % 2) * UNITS_PER_WORD;
+ 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,
+ &regno, &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. */
+ /* ??? 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
+ return reg;
+ }
+ else
+ {
+ if ((regno - SPARC_FP_ARG_FIRST) < SPARC_INT_ARG_MAX * 2)
+ {
+ int regbase = (incoming_p
+ ? SPARC_INCOMING_INT_ARG_FIRST
+ : SPARC_OUTGOING_INT_ARG_FIRST);
+ int intreg = regbase + (regno - SPARC_FP_ARG_FIRST) / 2;
+ return gen_rtx (PARALLEL, mode,
+ gen_rtvec (2,
+ gen_rtx (EXPR_LIST, VOIDmode,
+ gen_rtx (REG, mode, intreg),
+ const0_rtx),
+ gen_rtx (EXPR_LIST, VOIDmode,
+ reg, const0_rtx)));
+ }
+ else
+ 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 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. */
+ tree field;
+ rtx ret;
+ int i;
+ int nregs;
+ /* Starting bit position of a sequence of integer fields, counted from
+ msb of left most byte, -1 if last field wasn't an int. */
+ /* ??? This isn't entirely necessary, some simplification
+ may be possible. */
+ int start_int_bitpos;
+ /* Current bitpos in struct, counted from msb of left most byte. */
+ int bitpos, this_slotno;
+ /* 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;
+
+ if (int_size_in_bytes (type) > 16)
+ abort (); /* shouldn't get here */
+
+ /* 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. */
+ nregs = 0;
+ start_int_bitpos = -1;
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ {
+ bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
+ this_slotno = slotno + bitpos / BITS_PER_WORD;
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ && TARGET_FPU
+ && ! packed_p
+ && named)
+ {
+ /* There's no need to check this_slotno < SPARC_FP_ARG MAX.
+ If it wasn't true we wouldn't be here. */
+ nregs++;
+ start_int_bitpos = -1;
+ }
+ else if (this_slotno < SPARC_INT_ARG_MAX)
+ {
+ if (start_int_bitpos == -1)
+ {
+ nregs++;
+ start_int_bitpos = bitpos;
+ }
+ else
+ {
+ if (bitpos % BITS_PER_WORD == 0)
+ nregs++;
+ }
+ }
+ }
+ }
+ if (nregs == 0)
+ abort ();
+
+ ret = gen_rtx (PARALLEL, BLKmode, rtvec_alloc (nregs + 1));
+
+ /* ??? This causes the entire struct to be passed in memory.
+ This isn't necessary, but is left for later. */
+ XVECEXP (ret, 0, 0) = gen_rtx (EXPR_LIST, VOIDmode, NULL_RTX,
+ const0_rtx);
+
+ /* Fill in the entries. */
+ start_int_bitpos = -1;
+ for (i = 1, field = TYPE_FIELDS (type);
+ field;
+ field = TREE_CHAIN (field))
+ {
+ bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
+ this_slotno = slotno + bitpos / BITS_PER_WORD;
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ if (TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ && TARGET_FPU
+ && ! packed_p
+ && named)
+ {
+ reg = gen_rtx (REG, DECL_MODE (field),
+ (SPARC_FP_ARG_FIRST + this_slotno * 2
+ + (DECL_MODE (field) == SFmode
+ && (bitpos & 32) != 0)));
+ XVECEXP (ret, 0, i) = gen_rtx (EXPR_LIST, VOIDmode, reg,
+ GEN_INT (bitpos / BITS_PER_UNIT));
+ i++;
+ start_int_bitpos = -1;
+ }
+ else
+ {
+ if (this_slotno < SPARC_INT_ARG_MAX
+ && (start_int_bitpos == -1
+ || bitpos % BITS_PER_WORD == 0))
+ {
+ enum machine_mode mode;
+
+ /* 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 (bitpos % BITS_PER_WORD != 0)
+ mode = mode_for_size (BITS_PER_WORD - bitpos % BITS_PER_WORD,
+ MODE_INT, 0);
+ else
+ mode = word_mode;
+
+ regno = regbase + this_slotno;
+ reg = gen_rtx (REG, mode, regno);
+ XVECEXP (ret, 0, i) = gen_rtx (EXPR_LIST, VOIDmode, reg,
+ GEN_INT (bitpos / BITS_PER_UNIT));
+ i++;
+ if (start_int_bitpos == -1)
+ start_int_bitpos = bitpos;
+ }
+ }
+ }
+ }
+ if (i != nregs + 1)
+ abort ();
+
+ return ret;
+ }
+ 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, &regno, &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;
+ enum machine_mode mode;
+ tree type;
+ int named;
+{
+ if (TARGET_ARCH32)
+ {
+ return (type && AGGREGATE_TYPE_P (type)
+ || mode == TFmode || mode == TCmode);
+ }
+ else
+ {
+ return ((type && TREE_CODE (type) == ARRAY_TYPE)
+ || (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, &regno, &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
- adjust = 0;
-
- regbuf = assign_stack_local (BLKmode, bufsize + adjust,
- GET_MODE_BITSIZE (TFmode));
- regbuf = gen_rtx (MEM, BLKmode, plus_constant (XEXP (regbuf, 0), adjust));
- MEM_IN_STRUCT_P (regbuf) = 1;
-
- /* Save int args.
- This is optimized to only save the regs that are necessary. Explicitly
- named args need not be saved. */
-
- if (n_intregs > 0)
- move_block_from_reg (BASE_INCOMING_ARG_REG (SImode) + first_intreg,
- regbuf, n_intregs, n_intregs * UNITS_PER_WORD);
-
- /* Save float args.
- This is optimized to only save the regs that are necessary. Explicitly
- named args need not be saved.
- We explicitly build a pointer to the buffer because it halves the insn
- count when not optimizing (otherwise the pointer is built for each reg
- saved). */
-
- fpregs = gen_reg_rtx (Pmode);
- emit_move_insn (fpregs, plus_constant (XEXP (regbuf, 0),
- n_intregs * UNITS_PER_WORD));
- for (regno = first_floatreg; regno < NPARM_REGS (SFmode); regno += 2)
- emit_move_insn (gen_rtx (MEM, DFmode,
- plus_constant (fpregs,
- GET_MODE_SIZE (SFmode)
- * (regno - first_floatreg))),
- gen_rtx (REG, DFmode,
- BASE_INCOMING_ARG_REG (DFmode) + regno));
-
- /* Return the address of the regbuf. */
-
- return XEXP (regbuf, 0);
+ {
+ 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 && TREE_CODE (type) == RECORD_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));
}
+
+/* Do what is necessary for `va_start'. The argument is ignored.
-#else /* ! SPARCV9 */
+ 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)
@@ -3189,41 +4252,40 @@ sparc_builtin_saveregs (arglist)
int stdarg = (TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
!= void_type_node));
- int first_reg = current_function_args_info;
+ int first_reg = current_function_args_info.words;
rtx address;
int regno;
-#if 0 /* This code seemed to have no effect except to make
- varargs not work right when va_list wasn't the first arg. */
- if (! stdarg)
- first_reg = 0;
-#endif
-
- for (regno = first_reg; regno < NPARM_REGS (SImode); 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));
+ 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;
}
-
-#endif /* ! SPARCV9 */
/* Return the string to output a conditional branch to LABEL, which is
- the operand number of the label. OP is the conditional expression. The
- mode of register 0 says what kind of comparison we made.
-
- FP_COND_REG indicates which fp condition code register to use if this is
- a floating point branch.
+ 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.
@@ -3232,14 +4294,15 @@ sparc_builtin_saveregs (arglist)
NOOP is non-zero if we have to follow this branch by a noop. */
char *
-output_cbranch (op, fp_cond_reg, label, reversed, annul, noop)
- rtx op, fp_cond_reg;
+output_cbranch (op, label, reversed, annul, noop)
+ rtx op;
int 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));
+ 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";
@@ -3366,7 +4429,7 @@ output_cbranch (op, fp_cond_reg, label, reversed, annul, noop)
labeloff = 10;
labelno = v9_fcc_labelno;
/* Set the char indicating the number of the fcc reg to use. */
- labelno[6] = REGNO (fp_cond_reg) - 96 + '0';
+ labelno[6] = REGNO (cc_reg) - SPARC_FIRST_V9_FCC_REG + '0';
}
else if (mode == CCXmode || mode == CCX_NOOVmode)
labelno = v9_xcc_labelno;
@@ -3695,8 +4758,8 @@ print_operand (file, x, code)
fputs ("\n\tnop", file);
return;
case '_':
- /* Output the Medium/Anywhere code model base register. */
- fputs (MEDANY_BASE_REG, file);
+ /* 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
@@ -3715,6 +4778,20 @@ print_operand (file, x, code)
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. */
@@ -3730,6 +4807,23 @@ print_operand (file, x, code)
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));
@@ -3766,37 +4860,53 @@ print_operand (file, x, code)
}
return;
- /* This is used by the conditional move instructions. */
+ /* These are used by the conditional move instructions. */
+ case 'c' :
case 'C':
- switch (GET_CODE (x))
- {
- 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 ("Invalid %%C operand");
- }
- return;
+ {
+ 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;
+ }
- /* This is used by the movr instruction pattern. */
+ /* These are used by the movr instruction pattern. */
+ case 'd':
case 'D':
- switch (GET_CODE (x))
- {
- 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 ("Invalid %%D operand");
- }
- return;
+ {
+ 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':
{
@@ -3829,8 +4939,9 @@ print_operand (file, x, code)
else if (GET_CODE (x) == MEM)
{
fputc ('[', file);
- if (CONSTANT_P (XEXP (x, 0)))
/* 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);
@@ -3880,11 +4991,22 @@ output_double_int (file, 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_rtx (CONST_INT, VOIDmode, high));
+ ASM_OUTPUT_INT (file, gen_rtx (CONST_INT, VOIDmode, 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)
{
@@ -3896,11 +5018,12 @@ output_double_int (file, value)
else if (GET_CODE (value) == SYMBOL_REF
|| GET_CODE (value) == CONST
|| GET_CODE (value) == PLUS
- || (TARGET_V9 &&
+ || (TARGET_ARCH64 &&
(GET_CODE (value) == LABEL_REF
+ || GET_CODE (value) == CODE_LABEL
|| GET_CODE (value) == MINUS)))
{
- if (!TARGET_V9 || TARGET_ENV32)
+ if (!TARGET_V9 || TARGET_CM_MEDLOW)
{
ASM_OUTPUT_INT (file, const0_rtx);
ASM_OUTPUT_INT (file, value);
@@ -4350,7 +5473,8 @@ sparc_flat_compute_frame_size (size)
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)
+sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op,
+ doubleword_op, base_offset)
FILE *file;
char *base_reg;
unsigned int offset;
@@ -4358,6 +5482,7 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
unsigned long fmask;
char *word_op;
char *doubleword_op;
+ unsigned long base_offset;
{
int regno;
@@ -4385,9 +5510,18 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
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);
+ {
+ 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,
@@ -4399,9 +5533,13 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
else
{
if (word_op[0] == 's')
- fprintf (file, "\t%s %s,[%s+%d]\n",
- word_op, reg_names[regno],
- base_reg, offset);
+ {
+ 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]);
@@ -4419,9 +5557,13 @@ sparc_flat_save_restore (file, base_reg, offset, gmask, fmask, word_op, doublewo
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);
+ {
+ 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]);
@@ -4443,8 +5585,9 @@ sparc_flat_output_function_prologue (file, size)
unsigned long gmask = current_frame_info.gmask;
/* This is only for the human reader. */
- fprintf (file, "\t!#PROLOGUE# 0\n");
- fprintf (file, "\t!# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
+ fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START);
+ fprintf (file, "\t%s# vars= %d, regs= %d/%d, args= %d, extra= %d\n",
+ ASM_COMMENT_START,
current_frame_info.var_size,
current_frame_info.gp_reg_size / 4,
current_frame_info.fp_reg_size / 4,
@@ -4500,8 +5643,8 @@ sparc_flat_output_function_prologue (file, size)
{
fprintf (file, "\tst %s,[%s+%d]\n",
fp_str, sp_str, reg_offset);
- fprintf (file, "\tsub %s,%d,%s\t!# set up frame pointer\n",
- sp_str, -size, fp_str);
+ fprintf (file, "\tsub %s,%d,%s\t%s# set up frame pointer\n",
+ sp_str, -size, fp_str, ASM_COMMENT_START);
reg_offset += 4;
}
}
@@ -4513,21 +5656,35 @@ sparc_flat_output_function_prologue (file, size)
{
fprintf (file, "\tst %s,[%s+%d]\n",
fp_str, sp_str, reg_offset);
- fprintf (file, "\tadd %s,%s,%s\t!# set up frame pointer\n",
- sp_str, t1_str, fp_str);
+ 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");
+ "st", "std", -size);
}
else
{
@@ -4544,8 +5701,9 @@ sparc_flat_output_function_prologue (file, size)
sp_str, -size1, sp_str);
if (gmask & FRAME_POINTER_MASK)
{
- fprintf (file, "\tst %s,[%s+%d]\n\tsub %s,%d,%s\t!# set up frame pointer\n",
- fp_str, sp_str, offset, sp_str, -size1, fp_str);
+ 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;
}
}
@@ -4555,27 +5713,47 @@ sparc_flat_output_function_prologue (file, size)
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!# set up frame pointer\n",
- fp_str, sp_str, offset, sp_str, t1_str, fp_str);
+ 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");
+ "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!#PROLOGUE# 1\n");
+ fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START);
}
/* Do any necessary cleanup after a function to restore stack, frame,
@@ -4590,7 +5768,7 @@ sparc_flat_output_function_epilogue (file, size)
int noepilogue = FALSE;
/* This is only for the human reader. */
- fprintf (file, "\t!#EPILOGUE#\n");
+ 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
@@ -4632,11 +5810,11 @@ sparc_flat_output_function_epilogue (file, size)
if (frame_pointer_needed)
{
if (size > 4095)
- fprintf (file,"\tsub %s,%s,%s\t\t!# sp not trusted here\n",
- fp_str, t1_str, sp_str);
+ 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!# sp not trusted here\n",
- fp_str, size, sp_str);
+ 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? */
@@ -4676,7 +5854,7 @@ sparc_flat_output_function_epilogue (file, size)
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");
+ "ld", "ldd", 0);
/* If we had to increment %sp in two steps, record it so the second
restoration in the epilogue finishes up. */
@@ -4745,10 +5923,21 @@ sparc_flat_eligible_for_epilogue_delay (trial, slot)
rtx trial;
int slot;
{
- if (get_attr_length (trial) == 1
- && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial))
- && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial)))
+ 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;
}
diff --git a/gnu/usr.bin/gcc/config/sparc/sparc.md b/gnu/usr.bin/gcc/config/sparc/sparc.md
index bfc1e8b78bb..6efa3320852 100644
--- a/gnu/usr.bin/gcc/config/sparc/sparc.md
+++ b/gnu/usr.bin/gcc/config/sparc/sparc.md
@@ -1,5 +1,5 @@
;;- Machine description for SPARC chip for GNU C compiler
-;; Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+;; 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.
@@ -28,17 +28,36 @@
;; 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,v8plus,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 type. Arch32bit includes v7, sparclite, v8.
-
+;; Architecture size.
(define_attr "arch" "arch32bit,arch64bit"
- (const (symbol_ref "sparc_arch_type")))
+ (const
+ (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
+ (const_string "arch32bit"))))
-;; CPU type. This is only used for instruction scheduling
-(define_attr "cpu" "cypress,supersparc"
+;; Whether -mlive-g0 is in effect.
+(define_attr "live_g0" "no,yes"
(const
- (cond [(symbol_ref "TARGET_SUPERSPARC") (const_string "supersparc")]
- (const_string "cypress"))))
+ (cond [(symbol_ref "TARGET_LIVE_G0") (const_string "yes")]
+ (const_string "no"))))
;; Insn type. Used to default other attribute values.
@@ -236,6 +255,60 @@
(and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "supersparc")) 36 30)
(define_function_unit "fp_mds" 1 0
(and (eq_attr "type" "imul") (eq_attr "cpu" "supersparc")) 12 12)
+
+;; ----- 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 "type" "load") (eq_attr "cpu" "tsc701")) 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 "type" "store") (eq_attr "cpu" "tsc701")) 3 3
+ [(eq_attr "type" "load,store")])
+;; The multiply unit has a latency of 5.
+(define_function_unit "tsc701_mul" 1 0
+ (and (eq_attr "type" "imul") (eq_attr "cpu" "tsc701")) 5 5)
+
+;; ----- The UltraSPARC-1 scheduling
+;; The Ultrasparc can issue 1 - 4 insns per cycle; here we assume
+;; four insns/cycle, and hence multiply all costs by four.
+
+;; Memory delivers its result in three cycles to IU, three cycles to FP
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "load,fpload") (eq_attr "cpu" "ultrasparc")) 12 4)
+(define_function_unit "memory" 1 0
+ (and (eq_attr "type" "store,fpstore") (eq_attr "cpu" "ultrasparc")) 4 4)
+(define_function_unit "ieu" 1 0
+ (and (eq_attr "type" "ialu") (eq_attr "cpu" "ultrasparc")) 1 2)
+(define_function_unit "ieu" 1 0
+ (and (eq_attr "type" "shift") (eq_attr "cpu" "ultrasparc")) 1 4)
+(define_function_unit "ieu" 1 0
+ (and (eq_attr "type" "cmove") (eq_attr "cpu" "ultrasparc")) 8 4)
+
+;; Timings; throughput/latency
+;; ?? FADD 1/3 add/sub, format conv, compar, abs, neg
+;; ?? FMUL 1/3
+;; ?? FDIVs 1/12
+;; ?? FDIVd 1/22
+;; ?? FSQRTs 1/12
+;; ?? FSQRTd 1/22
+
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fp") (eq_attr "cpu" "ultrasparc")) 12 2)
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fpcmp") (eq_attr "cpu" "ultrasparc")) 8 2)
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fpmul") (eq_attr "cpu" "ultrasparc")) 12 2)
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fpdivs") (eq_attr "cpu" "ultrasparc")) 48 2)
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fpdivd") (eq_attr "cpu" "ultrasparc")) 88 2)
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fpsqrt") (eq_attr "cpu" "ultrasparc")) 48 2)
;; Compare instructions.
;; This controls RTL generation and register allocation.
@@ -256,7 +329,7 @@
;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
(define_expand "cmpsi"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "arith_operand" "")))]
""
@@ -268,10 +341,10 @@
}")
(define_expand "cmpdi"
- [(set (reg:CCX 0)
+ [(set (reg:CCX 100)
(compare:CCX (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "arith_double_operand" "")))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"
{
sparc_compare_op0 = operands[0];
@@ -280,7 +353,8 @@
}")
(define_expand "cmpsf"
- [(set (reg:CCFP 0)
+ ;; 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"
@@ -292,7 +366,8 @@
}")
(define_expand "cmpdf"
- [(set (reg:CCFP 0)
+ ;; 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"
@@ -304,7 +379,8 @@
}")
(define_expand "cmptf"
- [(set (reg:CCFP 0)
+ ;; 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"
@@ -315,6 +391,102 @@
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 "*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
@@ -331,18 +503,17 @@
(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 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" "")))
- (parallel [(set (match_operand:DI 0 "register_operand" "")
- (eq:DI (match_dup 3) (const_int 0)))
- (clobber (reg:CCX 0))])]
- ""
+ (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"
@@ -351,66 +522,63 @@
(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 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" "")))
- (parallel [(set (match_operand:DI 0 "register_operand" "")
- (ne:DI (match_dup 3) (const_int 0)))
- (clobber (reg:CCX 0))])]
- ""
+ (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" "")))
- (parallel [(set (match_operand:SI 0 "register_operand" "")
- (eq:SI (subreg:SI (match_dup 3) 0) (const_int 0)))
- (clobber (reg:CC 0))])]
- ""
+ (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" "")))
- (parallel [(set (match_operand:SI 0 "register_operand" "")
- (ne:SI (subreg:SI (match_dup 3) 0) (const_int 0)))
- (clobber (reg:CC 0))])]
- ""
+ (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 (subreg:SI (match_dup 3) 0)
+ [(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:DI (match_dup 3) (const_int 0)))
- (clobber (reg:CCX 0))])]
- ""
- "{ operands[3] = gen_reg_rtx (DImode); }")
+ (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 (subreg:SI (match_dup 3) 0)
+ [(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:DI (match_dup 3) (const_int 0)))
- (clobber (reg:CCX 0))])]
- ""
- "{ operands[3] = gen_reg_rtx (DImode); }")
+ (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)
@@ -420,7 +588,7 @@
if (GET_MODE (operands[0]) == SImode)
pat = gen_seqsi_special (operands[0], sparc_compare_op0,
sparc_compare_op1);
- else if (! TARGET_V9)
+ else if (! TARGET_ARCH64)
FAIL;
else
pat = gen_seqsi_special_extend (operands[0], sparc_compare_op0,
@@ -432,11 +600,11 @@
{
rtx pat;
- if (GET_MODE (operands[0]) == SImode)
+ 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 if (! TARGET_V9)
- FAIL;
else
pat = gen_seqdi_special (operands[0], sparc_compare_op0,
sparc_compare_op1);
@@ -463,7 +631,7 @@
(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)
@@ -473,7 +641,7 @@
if (GET_MODE (operands[0]) == SImode)
pat = gen_snesi_special (operands[0], sparc_compare_op0,
sparc_compare_op1);
- else if (! TARGET_V9)
+ else if (! TARGET_ARCH64)
FAIL;
else
pat = gen_snesi_special_extend (operands[0], sparc_compare_op0,
@@ -485,11 +653,11 @@
{
rtx pat;
- if (GET_MODE (operands[0]) == SImode)
+ 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 if (! TARGET_V9)
- FAIL;
else
pat = gen_snedi_special (operands[0], sparc_compare_op0,
sparc_compare_op1);
@@ -514,7 +682,7 @@
(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)
@@ -535,7 +703,7 @@
(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)
@@ -556,7 +724,7 @@
(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)
@@ -577,7 +745,7 @@
(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)
@@ -598,7 +766,7 @@
(define_expand "sgtu"
[(set (match_operand:SI 0 "intreg_operand" "")
(gtu:SI (match_dup 1) (const_int 0)))]
- ""
+ "! TARGET_LIVE_G0"
"
{
if (! TARGET_V9)
@@ -630,7 +798,7 @@
(define_expand "sltu"
[(set (match_operand:SI 0 "intreg_operand" "")
(ltu:SI (match_dup 1) (const_int 0)))]
- ""
+ "! TARGET_LIVE_G0"
"
{
if (TARGET_V9)
@@ -644,7 +812,7 @@
(define_expand "sgeu"
[(set (match_operand:SI 0 "intreg_operand" "")
(geu:SI (match_dup 1) (const_int 0)))]
- ""
+ "! TARGET_LIVE_G0"
"
{
if (TARGET_V9)
@@ -658,7 +826,7 @@
(define_expand "sleu"
[(set (match_operand:SI 0 "intreg_operand" "")
(leu:SI (match_dup 1) (const_int 0)))]
- ""
+ "! TARGET_LIVE_G0"
"
{
if (! TARGET_V9)
@@ -687,119 +855,7 @@
operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
}")
-;; Now the DEFINE_INSNs for the compare and scc cases. First the compares.
-
-(define_insn "*cmpsi_insn"
- [(set (reg:CC 0)
- (compare:CC (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "arith_operand" "rI")))]
- ""
- "cmp %r0,%1"
- [(set_attr "type" "compare")])
-
-(define_insn "*cmpsf_fpe_sp32"
- [(set (reg:CCFPE 0)
- (compare:CCFPE (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
- "! TARGET_V9 && TARGET_FPU"
- "fcmpes %0,%1"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmpdf_fpe_sp32"
- [(set (reg:CCFPE 0)
- (compare:CCFPE (match_operand:DF 0 "register_operand" "e")
- (match_operand:DF 1 "register_operand" "e")))]
- "! TARGET_V9 && TARGET_FPU"
- "fcmped %0,%1"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmptf_fpe_sp32"
- [(set (reg:CCFPE 0)
- (compare:CCFPE (match_operand:TF 0 "register_operand" "e")
- (match_operand:TF 1 "register_operand" "e")))]
- "! TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fcmpeq %0,%1"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmpsf_fp_sp32"
- [(set (reg:CCFP 0)
- (compare:CCFP (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "register_operand" "f")))]
- "! TARGET_V9 && TARGET_FPU"
- "fcmps %0,%1"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmpdf_fp_sp32"
- [(set (reg:CCFP 0)
- (compare:CCFP (match_operand:DF 0 "register_operand" "e")
- (match_operand:DF 1 "register_operand" "e")))]
- "! TARGET_V9 && TARGET_FPU"
- "fcmpd %0,%1"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmptf_fp_sp32"
- [(set (reg:CCFP 0)
- (compare:CCFP (match_operand:TF 0 "register_operand" "e")
- (match_operand:TF 1 "register_operand" "e")))]
- "! TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fcmpq %0,%1"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmpdi_sp64"
- [(set (reg:CCX 0)
- (compare:CCX (match_operand:DI 0 "register_operand" "r")
- (match_operand:DI 1 "arith_double_operand" "rHI")))]
- "TARGET_V9"
- "cmp %r0,%1"
- [(set_attr "type" "compare")])
-
-(define_insn "*cmpsf_fpe_sp64"
- [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c")
- (compare:CCFPE (match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "register_operand" "f")))]
- "TARGET_V9 && TARGET_FPU"
- "fcmpes %0,%1,%2"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmpdf_fpe_sp64"
- [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c")
- (compare:CCFPE (match_operand:DF 1 "register_operand" "e")
- (match_operand:DF 2 "register_operand" "e")))]
- "TARGET_V9 && TARGET_FPU"
- "fcmped %0,%1,%2"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmptf_fpe_sp64"
- [(set (match_operand:CCFPE 0 "ccfp_reg_operand" "=c")
- (compare:CCFPE (match_operand:TF 1 "register_operand" "e")
- (match_operand:TF 2 "register_operand" "e")))]
- "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fcmpeq %0,%1,%2"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmpsf_fp_sp64"
- [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c")
- (compare:CCFP (match_operand:SF 1 "register_operand" "f")
- (match_operand:SF 2 "register_operand" "f")))]
- "TARGET_V9 && TARGET_FPU"
- "fcmps %0,%1,%2"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmpdf_fp_sp64"
- [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c")
- (compare:CCFP (match_operand:DF 1 "register_operand" "e")
- (match_operand:DF 2 "register_operand" "e")))]
- "TARGET_V9 && TARGET_FPU"
- "fcmpd %0,%1,%2"
- [(set_attr "type" "fpcmp")])
-
-(define_insn "*cmptf_fp_sp64"
- [(set (match_operand:CCFP 0 "ccfp_reg_operand" "=c")
- (compare:CCFP (match_operand:TF 1 "register_operand" "e")
- (match_operand:TF 2 "register_operand" "e")))]
- "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
- "fcmpq %0,%1,%2"
- [(set_attr "type" "fpcmp")])
+;; 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.
@@ -808,8 +864,8 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
- (clobber (reg:CC 0))]
- ""
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
"subcc %%g0,%1,%%g0\;addx %%g0,0,%0"
[(set_attr "type" "unary")
(set_attr "length" "2")])
@@ -818,38 +874,55 @@
[(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 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 "*snedi_zero"
+(define_insn "*snesi_zero_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
- (ne:DI (match_operand:DI 1 "register_operand" "r")
+ (ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
- (clobber (reg:CCX 0))]
- "TARGET_V9"
+ (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" "unary")
(set_attr "length" "2")])
(define_insn "*neg_snedi_zero"
- [(set (match_operand:DI 0 "register_operand" "=r")
+ [(set (match_operand:DI 0 "register_operand" "=&r")
(neg:DI (ne:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 0))))
- (clobber (reg:CCX 0))]
- "TARGET_V9"
+ (const_int 0))))]
+ "TARGET_ARCH64"
"mov 0,%0\;movrnz %1,-1,%0"
[(set_attr "type" "unary")
(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" "unary")
+ (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 0))]
- ""
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
"subcc %%g0,%1,%%g0\;subx %%g0,-1,%0"
[(set_attr "type" "unary")
(set_attr "length" "2")])
@@ -858,32 +931,49 @@
[(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 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 "*seqdi_zero"
+(define_insn "*seqsi_zero_extend"
[(set (match_operand:DI 0 "register_operand" "=r")
- (eq:DI (match_operand:DI 1 "register_operand" "r")
+ (eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0)))
- (clobber (reg:CCX 0))]
- "TARGET_V9"
+ (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" "unary")
(set_attr "length" "2")])
(define_insn "*neg_seqdi_zero"
- [(set (match_operand:DI 0 "register_operand" "=r")
+ [(set (match_operand:DI 0 "register_operand" "=&r")
(neg:DI (eq:DI (match_operand:DI 1 "register_operand" "r")
- (const_int 0))))
- (clobber (reg:CCX 0))]
- "TARGET_V9"
+ (const_int 0))))]
+ "TARGET_ARCH64"
"mov 0,%0\;movrz %1,-1,%0"
[(set_attr "type" "unary")
(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" "unary")
+ (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.
@@ -893,8 +983,8 @@
(plus:SI (ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))
(match_operand:SI 2 "register_operand" "r")))
- (clobber (reg:CC 0))]
- ""
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
"subcc %%g0,%1,%%g0\;addx %2,0,%0"
[(set_attr "length" "2")])
@@ -903,8 +993,8 @@
(minus:SI (match_operand:SI 2 "register_operand" "r")
(ne:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
- (clobber (reg:CC 0))]
- ""
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
"subcc %%g0,%1,%%g0\;subx %2,0,%0"
[(set_attr "length" "2")])
@@ -913,8 +1003,8 @@
(plus:SI (eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))
(match_operand:SI 2 "register_operand" "r")))
- (clobber (reg:CC 0))]
- ""
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
"subcc %%g0,%1,%%g0\;subx %2,-1,%0"
[(set_attr "length" "2")])
@@ -923,8 +1013,8 @@
(minus:SI (match_operand:SI 2 "register_operand" "r")
(eq:SI (match_operand:SI 1 "register_operand" "r")
(const_int 0))))
- (clobber (reg:CC 0))]
- ""
+ (clobber (reg:CC 100))]
+ "! TARGET_LIVE_G0"
"subcc %%g0,%1,%%g0\;addx %2,-1,%0"
[(set_attr "length" "2")])
@@ -934,46 +1024,46 @@
(define_insn "*sltu_insn"
[(set (match_operand:SI 0 "register_operand" "=r")
- (ltu:SI (reg:CC 0) (const_int 0)))]
- ""
+ (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 0) (const_int 0))))]
- ""
+ (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 0) (const_int 0)))
+ (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 0) (const_int 0))
+ (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 0) (const_int 0)))]
- ""
+ (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 0) (const_int 0))))]
- ""
+ (neg:SI (geu:SI (reg:CC 100) (const_int 0))))]
+ "! TARGET_LIVE_G0"
"addx %%g0,-1,%0"
[(set_attr "type" "misc")])
@@ -983,15 +1073,15 @@
(define_insn "*sltu_plus_x"
[(set (match_operand:SI 0 "register_operand" "=r")
- (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
+ (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 0) (const_int 0))
+ (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"))))]
""
@@ -1000,7 +1090,7 @@
(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 0) (const_int 0))))]
+ (ltu:SI (reg:CC 100) (const_int 0))))]
""
"subx %1,0,%0"
[(set_attr "type" "unary")])
@@ -1010,21 +1100,21 @@
[(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 0) (const_int 0))))]
+ (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 0) (const_int 0))
+ (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 0) (const_int 0))
+ (plus:SI (geu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 1 "register_operand" "r")))]
""
"subx %1,-1,%0"
@@ -1033,7 +1123,7 @@
(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 0) (const_int 0))))]
+ (geu:SI (reg:CC 100) (const_int 0))))]
""
"addx %1,-1,%0"
[(set_attr "type" "unary")])
@@ -1046,7 +1136,9 @@
(define_insn "*scc_si"
[(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 1 "noov_compare_op" [(reg 0) (const_int 0)]))]
+ (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")
@@ -1054,8 +1146,10 @@
(define_insn "*scc_di"
[(set (match_operand:DI 0 "register_operand" "=r")
- (match_operator:DI 1 "noov_compare_op" [(reg 0) (const_int 0)]))]
- "TARGET_V9"
+ (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")])
@@ -1074,7 +1168,7 @@
""
"
{
- if (TARGET_V9 && sparc_compare_op1 == const0_rtx
+ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode)
{
@@ -1098,7 +1192,7 @@
""
"
{
- if (TARGET_V9 && sparc_compare_op1 == const0_rtx
+ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode)
{
@@ -1122,7 +1216,7 @@
""
"
{
- if (TARGET_V9 && sparc_compare_op1 == const0_rtx
+ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode)
{
@@ -1156,7 +1250,7 @@
""
"
{
- if (TARGET_V9 && sparc_compare_op1 == const0_rtx
+ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode)
{
@@ -1190,7 +1284,7 @@
""
"
{
- if (TARGET_V9 && sparc_compare_op1 == const0_rtx
+ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode)
{
@@ -1224,7 +1318,7 @@
""
"
{
- if (TARGET_V9 && sparc_compare_op1 == const0_rtx
+ if (TARGET_ARCH64 && sparc_compare_op1 == const0_rtx
&& GET_CODE (sparc_compare_op0) == REG
&& GET_MODE (sparc_compare_op0) == DImode)
{
@@ -1255,13 +1349,13 @@
(define_insn "*normal_branch"
[(set (pc)
(if_then_else (match_operator 0 "noov_compare_op"
- [(reg 0) (const_int 0)])
+ [(reg 100) (const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
""
"*
{
- return output_cbranch (operands[0], 0, 1, 0,
+ return output_cbranch (operands[0], 1, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence);
}"
@@ -1270,77 +1364,77 @@
(define_insn "*inverted_branch"
[(set (pc)
(if_then_else (match_operator 0 "noov_compare_op"
- [(reg 0) (const_int 0)])
+ [(reg 100) (const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
""
"*
{
- return output_cbranch (operands[0], 0, 1, 1,
+ return output_cbranch (operands[0], 1, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence);
}"
[(set_attr "type" "branch")])
-(define_insn "*normal_fp_branch_sp64"
+(define_insn "*normal_fp_branch"
[(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:CCFP 1 "ccfp_reg_operand" "c")
+ (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)))]
- "TARGET_V9"
+ ""
"*
{
- return output_cbranch (operands[0], operands[1], 2, 0,
+ return output_cbranch (operands[1], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence);
}"
[(set_attr "type" "branch")])
-(define_insn "*inverted_fp_branch_sp64"
+(define_insn "*inverted_fp_branch"
[(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:CCFP 1 "ccfp_reg_operand" "c")
+ (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 "" ""))))]
- "TARGET_V9"
+ ""
"*
{
- return output_cbranch (operands[0], operands[1], 2, 1,
+ return output_cbranch (operands[1], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence);
}"
[(set_attr "type" "branch")])
-(define_insn "*normal_fpe_branch_sp64"
+(define_insn "*normal_fpe_branch"
[(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:CCFPE 1 "ccfp_reg_operand" "c")
+ (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)))]
- "TARGET_V9"
+ ""
"*
{
- return output_cbranch (operands[0], operands[1], 2, 0,
+ return output_cbranch (operands[1], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence);
}"
[(set_attr "type" "branch")])
-(define_insn "*inverted_fpe_branch_sp64"
+(define_insn "*inverted_fpe_branch"
[(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:CCFPE 1 "ccfp_reg_operand" "c")
+ (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 "" ""))))]
- "TARGET_V9"
+ ""
"*
{
- return output_cbranch (operands[0], operands[1], 2, 1,
+ return output_cbranch (operands[1], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! final_sequence);
}"
@@ -1358,7 +1452,7 @@
(const_int 0)])
(label_ref (match_operand 2 "" ""))
(pc)))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"*
{
return output_v9branch (operands[0], 1, 2, 0,
@@ -1374,7 +1468,7 @@
(const_int 0)])
(pc)
(label_ref (match_operand 2 "" ""))))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"*
{
return output_v9branch (operands[0], 1, 2, 1,
@@ -1392,107 +1486,179 @@
""
;; 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_V9 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
+ "* 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"
+(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_V9 ? \"add %1,%%lo(%a2),%0\" : \"or %1,%%lo(%a2),%0\";"
+ "* 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"
+(define_insn "pic_sethi_si"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (unspec:SI [(match_operand 1 "" "")] 0)))]
- "check_pic (1)"
+ "flag_pic && check_pic (1)"
"sethi %%hi(%a1),%0"
[(set_attr "type" "move")
(set_attr "length" "1")])
-(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 "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 "*sethi_hi"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (high:HI (match_operand 1 "" "")))]
- "check_pic (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_via_call"
+ [(set (pc) (label_ref (match_operand 0 "" "")))
+ (set (reg:SI 15) (label_ref (match_operand 1 "" "")))]
+ ""
+ "call %l0%#"
+ [(set_attr "type" "uncond_branch")])
+
+(define_insn "get_pc_via_rdpc"
+ [(set (match_operand:DI 0 "register_operand" "=r") (pc))]
+ "TARGET_PTR64"
+ "rd %%pc,%0"
+ [(set_attr "type" "move")])
+
;; Special pic pattern, for loading the address of a label into a register.
;; It clobbers o7 because the call puts the return address (i.e. pc value)
-;; there.
+;; there. The pic tablejump pattern also uses this.
-(define_insn "*move_pic_label_si"
+(define_insn "move_pic_label_si"
[(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "move_pic_label" "i"))
+ ; This was previously (label_ref:SI (match_operand 1 "" "")) but that
+ ; loses the volatil and other flags of the original label_ref.
+ (match_operand:SI 1 "label_ref_operand" ""))
(set (reg:SI 15) (pc))]
- ""
- "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
+ "flag_pic"
+ "*
+{
+ if (get_attr_length (insn) == 2)
+ return \"\\n1:\;call 2f\;add %%o7,%%lo(%l1-1b),%0\\n2:\";
+ else
+ return \"\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0\";
+}"
[(set_attr "type" "multi")
- (set_attr "length" "4")])
-
-;; v9 special pic pattern, for loading the address of a label into a register.
+ ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
+ (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
+ (const_int 960))
+ (const_int 2)
+ (const_int 4)))])
+
+;; Special sparc64 pattern for loading the address of a label into a register.
+;; The pic and non-pic cases are the same since it's the most efficient way.
+;;
+;; ??? The non-pic case doesn't need to use %o7, we could use a scratch
+;; instead. But the pic case doesn't need to use %o7 either. We handle them
+;; both here so that when this is fixed, they can both be fixed together.
+;; Don't forget that the pic jump table stuff uses %o7 (that will need to be
+;; changed too).
-(define_insn "*move_pic_label_di"
+(define_insn "move_label_di"
[(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "move_pic_label" "i"))
+ ; This was previously (label_ref:DI (match_operand 1 "" "")) but that
+ ; loses the volatil and other flags of the original label_ref.
+ (match_operand:DI 1 "label_ref_operand" ""))
(set (reg:DI 15) (pc))]
- "TARGET_V9"
- "\\n1:\;call 2f\;sethi %%hi(%l1-1b),%0\\n2:\\tor %0,%%lo(%l1-1b),%0\;add %0,%%o7,%0"
+ "TARGET_ARCH64"
+ "*
+{
+ if (get_attr_length (insn) == 2)
+ return \"\\n1:\;rd %%pc,%%o7\;add %%o7,%l1-1b,%0\";
+ else
+ return \"\\n1:\;rd %%pc,%%o7\;sethi %%hi(%l1-1b),%0\;add %0,%%lo(%l1-1b),%0\;sra %0,0,%0\;add %0,%%o7,%0\";
+}"
[(set_attr "type" "multi")
- (set_attr "length" "4")])
+ ; 960 = 4096 bytes / 4 bytes/insn - 64 (for not always perfect length calcs)
+ (set (attr "length") (if_then_else (ltu (minus (match_dup 1) (pc))
+ (const_int 960))
+ (const_int 2)
+ (const_int 5)))])
+
+(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_V9"
+ "! 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_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2]));
- return \"or %R1,%%lo(%a2),%R0\";
+ 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")])
-;; ??? Gas does not handle %lo(DI), so we use the same code for ! TARGET_V9.
-;; ??? The previous comment is obsolete.
;; ??? 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_V9"
+ "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_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[2]));
+ 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\";
@@ -1504,7 +1670,7 @@
(define_insn "*sethi_di_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand 1 "" "")))]
- "! TARGET_V9 && check_pic (1)"
+ "! TARGET_ARCH64 && check_pic (1)"
"*
{
rtx op0 = operands[0];
@@ -1524,11 +1690,11 @@
else if (GET_CODE (op1) == CONST_DOUBLE)
{
operands[0] = operand_subword (op0, 1, 0, DImode);
- operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (op1));
+ 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_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (op1));
+ operands[1] = GEN_INT (CONST_DOUBLE_HIGH (op1));
return singlemove_string (operands);
}
else
@@ -1547,18 +1713,22 @@
;;; 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.
-;;; Gas doesn't have any 64 bit constant support, so don't use %uhi and %ulo
-;;; on constants. Symbols have to be handled by the linker, so we must use
-;;; %uhi and %ulo for them, but gas will handle these correctly.
-;;; ??? This comment is obsolete, gas handles them now.
+(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"
+(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_V9 && check_pic (1)"
+ "TARGET_ARCH64 && check_pic (1)"
"*
{
+#if HOST_BITS_PER_WIDE_INT == 32
rtx high, low;
split_double (operands[1], &high, &low);
@@ -1578,6 +1748,26 @@
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 \"\";
}"
@@ -1587,21 +1777,35 @@
;; 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.
+;; 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_MEDLOW, assume that the upper 32 bits of symbol addresses are
+;; When TARGET_CM_MEDLOW, assume that the upper 32 bits of symbol addresses are
;; always 0.
-;; When TARGET_MEDANY, the upper 32 bits of function addresses are 0.
-;; The data segment has a maximum size of 32 bits, but may be located anywhere.
-;; MEDANY_BASE_REG contains the start address, currently %g4.
-;; When TARGET_FULLANY, symbolic addresses are 64 bits.
+;; 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 "" "")))
-;; ??? Why the clobber?
+ ;; The clobber is here because emit_move_sequence assumes the worst case.
(clobber (reg:DI 1))]
- "TARGET_MEDLOW && check_pic (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")])
@@ -1609,31 +1813,22 @@
;; WARNING: %0 gets %hi(%1)+%g4.
;; You cannot OR in %lo(%1), it must be added in.
-(define_insn "*sethi_di_medany_data"
+(define_insn "*sethi_di_embmedany_data"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand 1 "data_segment_operand" "")))
-;; ??? Why the clobber?
+ ;; The clobber is here because emit_move_sequence assumes the worst case.
(clobber (reg:DI 1))]
- "TARGET_MEDANY && check_pic (1)"
- "sethi %%hi(%a1),%0; add %0,%%g4,%0"
+ "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_medany_text"
+(define_insn "*sethi_di_embmedany_text"
[(set (match_operand:DI 0 "register_operand" "=r")
(high:DI (match_operand 1 "text_segment_operand" "")))
-;; ??? Why the clobber?
+ ;; The clobber is here because emit_move_sequence assumes the worst case.
(clobber (reg:DI 1))]
- "TARGET_MEDANY && check_pic (1)"
- "sethi %%hi(%a1),%0"
- [(set_attr "type" "move")
- (set_attr "length" "1")])
-
-(define_insn "*sethi_di_fullany"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand 1 "" "")))
- (clobber (reg:DI 1))]
- "TARGET_FULLANY && check_pic (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")])
@@ -1653,16 +1848,33 @@
(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"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)
- || operands[1] == const0_rtx"
+ "! 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,*,1")])
+ (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")
@@ -1676,7 +1888,8 @@
[(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"
+ "(reload_completed || reload_in_progress)
+ && ! TARGET_PTR64"
"sethi %%hi(%a0),%2\;stb %r1,[%2+%%lo(%a0)]"
[(set_attr "type" "store")
(set_attr "length" "2")])
@@ -1694,16 +1907,33 @@
(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"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)
- || operands[1] == const0_rtx"
+ "! 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,*,1")])
+ (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")
@@ -1717,7 +1947,8 @@
[(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"
+ "(reload_completed || reload_in_progress)
+ && ! TARGET_PTR64"
"sethi %%hi(%a0),%2\;sth %r1,[%2+%%lo(%a0)]"
[(set_attr "type" "store")
(set_attr "length" "2")])
@@ -1743,9 +1974,10 @@
(define_insn "*movsi_insn"
[(set (match_operand:SI 0 "reg_or_nonsymb_mem_operand" "=r,f,r,r,f,Q,Q")
(match_operand:SI 1 "move_operand" "rI,!f,K,Q,!Q,rJ,!f"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)
- || operands[1] == const0_rtx"
+ "! TARGET_LIVE_G0
+ && (register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode)
+ || operands[1] == const0_rtx)"
"@
mov %1,%0
fmovs %1,%0
@@ -1753,15 +1985,35 @@
ld %1,%0
ld %1,%0
st %r1,%0
- st %r1,%0"
- [(set_attr "type" "move,fp,move,load,load,store,store")
- (set_attr "length" "*,*,1,*,*,*,*")])
+ st %1,%0"
+ [(set_attr "type" "move,fp,move,load,fpload,store,fpstore")
+ (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,fp,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"
+ "(reload_completed || reload_in_progress)
+ && ! TARGET_PTR64"
"sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
[(set_attr "type" "store")
(set_attr "length" "2")])
@@ -1779,7 +2031,7 @@
(define_insn "*movdi_sp32_insn"
[(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
+ "! TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)
|| operands[1] == const0_rtx)"
@@ -1803,7 +2055,7 @@
(define_insn "*movdi_sp64_insn"
[(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "=r,r,r,Q,?f,?f,?Q")
(match_operand:DI 1 "move_operand" "rI,K,Q,rJ,f,Q,f"))]
- "TARGET_V9
+ "TARGET_ARCH64
&& (register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)
|| operands[1] == const0_rtx)"
@@ -1824,8 +2076,7 @@
return \"sethi %%hi(%a1),%0\";
else
{
- operands[1] = gen_rtx (CONST_INT, VOIDmode,
- ~ INTVAL (operands[1]));
+ 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. */
@@ -1865,7 +2116,7 @@
; (clobber (match_dup 0))
; (clobber (match_dup 1))
; (clobber (match_scratch:SI 4 ""))
-; (clobber (reg:SI 0))
+; (clobber (reg:SI 100))
; (clobber (reg:SI 1))])]
; ""
; "
@@ -1891,7 +2142,7 @@
; (clobber (match_dup 0))
; (clobber (match_dup 1))
; (clobber (match_scratch:SI 4 "=&r"))
-; (clobber (reg:SI 0))
+; (clobber (reg:SI 100))
; (clobber (reg:SI 1))]
; ""
; "* return output_block_move (operands);"
@@ -1906,7 +2157,10 @@
(define_insn "*movsf_const_insn"
[(set (match_operand:SF 0 "general_operand" "=?r,f,m")
(match_operand:SF 1 "" "?F,m,G"))]
- "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
+ "TARGET_FPU
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && (GET_CODE (operands[0]) == REG
+ || fp_zero_operand (operands[1]))"
"*
{
switch (which_alternative)
@@ -1943,8 +2197,8 @@
mov %1,%0
ld %1,%0
ld %1,%0
- st %r1,%0
- st %r1,%0"
+ st %1,%0
+ st %1,%0"
[(set_attr "type" "fp,move,fpload,load,fpstore,store")])
;; Exactly the same as above, except that all `f' cases are deleted.
@@ -1960,14 +2214,15 @@
"@
mov %1,%0
ld %1,%0
- st %r1,%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"
+ "(reload_completed || reload_in_progress)
+ && ! TARGET_PTR64"
"sethi %%hi(%a0),%2\;st %r1,[%2+%%lo(%a0)]"
[(set_attr "type" "store")
(set_attr "length" "2")])
@@ -1979,7 +2234,10 @@
(define_insn "*movdf_const_insn"
[(set (match_operand:DF 0 "general_operand" "=?r,e,o")
(match_operand:DF 1 "" "?F,m,G"))]
- "TARGET_FPU && GET_CODE (operands[1]) == CONST_DOUBLE"
+ "TARGET_FPU
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && (GET_CODE (operands[0]) == REG
+ || fp_zero_operand (operands[1]))"
"*
{
switch (which_alternative)
@@ -1989,7 +2247,7 @@
case 1:
return output_fp_move_double (operands);
case 2:
- if (TARGET_V9)
+ if (TARGET_ARCH64)
{
return \"stx %%g0,%0\";
}
@@ -2044,11 +2302,13 @@
;; Must handle overlapping registers here, since parameters can be unaligned
;; in registers.
-;; ??? Do we need a v9 version of this?
+
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "register_operand" ""))]
- "! TARGET_V9 && reload_completed"
+ "! 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))]
"
@@ -2076,7 +2336,8 @@
[(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"
+ "(reload_completed || reload_in_progress)
+ && ! TARGET_PTR64"
"*
{
output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
@@ -2094,7 +2355,10 @@
(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"
+ "TARGET_FPU
+ && GET_CODE (operands[1]) == CONST_DOUBLE
+ && (GET_CODE (operands[0]) == REG
+ || fp_zero_operand (operands[1]))"
"*
{
switch (which_alternative)
@@ -2104,7 +2368,7 @@
case 1:
return output_fp_move_quad (operands);
case 2:
- if (TARGET_V9)
+ if (TARGET_ARCH64)
{
operands[1] = adj_offsettable_operand (operands[0], 8);
return \"stx %%g0,%0\;stx %%g0,%1\";
@@ -2173,7 +2437,8 @@
[(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"
+ "0 && (reload_completed || reload_in_progress)
+ && ! TARGET_PTR64"
"*
{
output_asm_insn (\"sethi %%hi(%a0),%2\", operands);
@@ -2187,19 +2452,86 @@
;; Sparc V9 conditional move instructions.
-;; We can handle larger constants here for some flavors, but for now we play
-;; it safe and only allow those constants supported by all flavours.
+;; 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 (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 (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 (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 (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
+ }
+}")
(define_expand "movsicc"
[(set (match_operand:SI 0 "register_operand" "")
- (if_then_else (match_operand 1 "comparison_operator" "")
- (match_operand:SI 2 "arith10_operand" "")
- (match_operand:SI 3 "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]);
+ 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
@@ -2218,10 +2550,10 @@
(define_expand "movdicc"
[(set (match_operand:DI 0 "register_operand" "")
- (if_then_else (match_operand 1 "comparison_operator" "")
- (match_operand:DI 2 "arith10_operand" "")
- (match_operand:DI 3 "register_operand" "")))]
- "TARGET_V9"
+ (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]);
@@ -2244,14 +2576,18 @@
(define_expand "movsfcc"
[(set (match_operand:SF 0 "register_operand" "")
- (if_then_else (match_operand 1 "comparison_operator" "")
- (match_operand:SF 2 "register_operand" "")
- (match_operand:SF 3 "register_operand" "")))]
- "TARGET_V9"
+ (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
@@ -2270,14 +2606,18 @@
(define_expand "movdfcc"
[(set (match_operand:DF 0 "register_operand" "")
- (if_then_else (match_operand 1 "comparison_operator" "")
- (match_operand:DF 2 "register_operand" "")
- (match_operand:DF 3 "register_operand" "")))]
- "TARGET_V9"
+ (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
@@ -2296,14 +2636,18 @@
(define_expand "movtfcc"
[(set (match_operand:TF 0 "register_operand" "")
- (if_then_else (match_operand 1 "comparison_operator" "")
- (match_operand:TF 2 "register_operand" "")
- (match_operand:TF 3 "register_operand" "")))]
- "TARGET_V9"
+ (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
@@ -2320,271 +2664,190 @@
}
}")
-/* Conditional move define_insns. */
-
-(define_insn "*movsi_cc_sp64"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CC 0) (const_int 0)])
- (match_operand:SI 2 "arith11_operand" "ri")
- (match_operand:SI 3 "register_operand" "0")))]
- "TARGET_V9"
- "mov%C1 %%icc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movdi_cc_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CC 0) (const_int 0)])
- (match_operand:DI 2 "arith11_double_operand" "rHI")
- (match_operand:DI 3 "register_operand" "0")))]
- "TARGET_V9"
- "mov%C1 %%icc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsi_ccx_sp64"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CCX 0) (const_int 0)])
- (match_operand:SI 2 "arith11_operand" "ri")
- (match_operand:SI 3 "register_operand" "0")))]
- "TARGET_V9"
- "mov%C1 %%xcc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movdi_ccx_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CCX 0) (const_int 0)])
- (match_operand:DI 2 "arith11_double_operand" "rHI")
- (match_operand:DI 3 "register_operand" "0")))]
- "TARGET_V9"
- "mov%C1 %%xcc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsi_ccfp_sp64"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
- (const_int 0)])
- (match_operand:SI 3 "arith11_operand" "ri")
- (match_operand:SI 4 "register_operand" "0")))]
- "TARGET_V9"
- "mov%C1 %2,%3,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsi_ccfpe_sp64"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
- (const_int 0)])
- (match_operand:SI 3 "arith11_operand" "ri")
- (match_operand:SI 4 "register_operand" "0")))]
- "TARGET_V9"
- "mov%C1 %2,%3,%0"
- [(set_attr "type" "cmove")])
+;; Conditional move define_insns.
-(define_insn "*movdi_ccfp_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
+(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:DI 3 "arith11_double_operand" "rHI")
- (match_operand:DI 4 "register_operand" "0")))]
+ (match_operand:QI 3 "arith11_operand" "rL,0")
+ (match_operand:QI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
- "mov%C1 %2,%3,%0"
+ "@
+ mov%C1 %x2,%3,%0
+ mov%c1 %x2,%4,%0"
[(set_attr "type" "cmove")])
-(define_insn "*movdi_ccfpe_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
+(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:DI 3 "arith11_double_operand" "rHI")
- (match_operand:DI 4 "register_operand" "0")))]
+ (match_operand:HI 3 "arith11_operand" "rL,0")
+ (match_operand:HI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
- "mov%C1 %2,%3,%0"
+ "@
+ mov%C1 %x2,%3,%0
+ mov%c1 %x2,%4,%0"
[(set_attr "type" "cmove")])
-(define_insn "*movsi_cc_reg_sp64"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "v9_regcmp_op"
- [(match_operand:DI 2 "register_operand" "r")
+(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 "arith10_operand" "ri")
- (match_operand:SI 4 "register_operand" "0")))]
+ (match_operand:SI 3 "arith11_operand" "rL,0")
+ (match_operand:SI 4 "arith11_operand" "0,rL")))]
"TARGET_V9"
- "movr%D1 %2,%r3,%0"
+ "@
+ mov%C1 %x2,%3,%0
+ mov%c1 %x2,%4,%0"
[(set_attr "type" "cmove")])
-(define_insn "*movdi_cc_reg_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (if_then_else (match_operator 1 "v9_regcmp_op"
- [(match_operand:DI 2 "register_operand" "r")
+;; ??? 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 "arith10_double_operand" "ri")
- (match_operand:DI 4 "register_operand" "0")))]
- "TARGET_V9"
- "movr%D1 %2,%r3,%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_reg_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (if_then_else (match_operator 1 "v9_regcmp_op"
- [(match_operand:DI 2 "register_operand" "r")
+(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")
- (match_operand:SF 4 "register_operand" "0")))]
+ (match_operand:SF 3 "register_operand" "f,0")
+ (match_operand:SF 4 "register_operand" "0,f")))]
"TARGET_V9 && TARGET_FPU"
- "fmovrs%D1 %2,%r3,%0"
+ "@
+ fmovs%C1 %x2,%3,%0
+ fmovs%c1 %x2,%4,%0"
[(set_attr "type" "cmove")])
-(define_insn "*movdf_cc_reg_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "v9_regcmp_op"
- [(match_operand:DI 2 "register_operand" "r")
+(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")
- (match_operand:DF 4 "register_operand" "0")))]
+ (match_operand:DF 3 "register_operand" "e,0")
+ (match_operand:DF 4 "register_operand" "0,e")))]
"TARGET_V9 && TARGET_FPU"
- "fmovrd%D1 %2,%r3,%0"
+ "@
+ fmovd%C1 %x2,%3,%0
+ fmovd%c1 %x2,%4,%0"
[(set_attr "type" "cmove")])
-(define_insn "*movtf_cc_reg_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "v9_regcmp_op"
- [(match_operand:DI 2 "register_operand" "r")
+(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")
- (match_operand:TF 4 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovrq%D1 %2,%r3,%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" "cmove")])
-(define_insn "*movsf_ccfp_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
+(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:SF 3 "register_operand" "f")
- (match_operand:SF 4 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovs%C1 %2,%3,%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 "*movsf_ccfpe_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
+(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:SF 3 "register_operand" "f")
- (match_operand:SF 4 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovs%C1 %2,%3,%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 "*movdf_ccfp_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
+(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:DF 3 "register_operand" "e")
- (match_operand:DF 4 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovd%C1 %2,%3,%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")])
-(define_insn "*movdf_ccfpe_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
+;; ??? 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:DF 3 "register_operand" "e")
- (match_operand:DF 4 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovd%C1 %2,%3,%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 "*movtf_ccfp_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFP 2 "ccfp_reg_operand" "c")
+(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:TF 3 "register_operand" "e")
- (match_operand:TF 4 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovq%C1 %2,%3,%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" "cmove")])
-(define_insn "*movtf_ccfpe_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFPE 2 "ccfp_reg_operand" "c")
+(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:TF 3 "register_operand" "e")
- (match_operand:TF 4 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovq%C1 %2,%3,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsf_cc_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CC 0) (const_int 0)])
- (match_operand:SF 2 "register_operand" "f")
- (match_operand:SF 3 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovs%C1 %%icc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movdf_cc_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CC 0) (const_int 0)])
- (match_operand:DF 2 "register_operand" "e")
- (match_operand:DF 3 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovd%C1 %%icc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movtf_cc_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CC 0) (const_int 0)])
- (match_operand:TF 2 "register_operand" "e")
- (match_operand:TF 3 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovq%C1 %%icc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movsf_ccx_sp64"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CCX 0) (const_int 0)])
- (match_operand:SF 2 "register_operand" "f")
- (match_operand:SF 3 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovs%C1 %%xcc,%2,%0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movdf_ccx_sp64"
- [(set (match_operand:DF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CCX 0) (const_int 0)])
- (match_operand:DF 2 "register_operand" "e")
- (match_operand:DF 3 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovd%C1 %%xcc,%2,%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" "cmove")])
-(define_insn "*movtf_ccx_sp64"
- [(set (match_operand:TF 0 "register_operand" "=e")
- (if_then_else (match_operator 1 "comparison_operator"
- [(reg:CCX 0) (const_int 0)])
- (match_operand:TF 2 "register_operand" "e")
- (match_operand:TF 3 "register_operand" "0")))]
- "TARGET_V9 && TARGET_FPU"
- "fmovq%C1 %%xcc,%2,%0"
+(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" "cmove")])
;;- zero extension instructions
@@ -2600,7 +2863,7 @@
"
{
rtx temp = gen_reg_rtx (SImode);
- rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
+ rtx shift_16 = GEN_INT (16);
int op1_subword = 0;
if (GET_CODE (operand1) == SUBREG)
@@ -2658,13 +2921,13 @@
(define_expand "zero_extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
- "TARGET_V9"
+ "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_V9 && GET_CODE (operands[1]) != CONST_INT"
+ "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
"@
and %1,0xff,%0
ldub %1,%0"
@@ -2674,11 +2937,11 @@
(define_expand "zero_extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"
{
rtx temp = gen_reg_rtx (DImode);
- rtx shift_48 = gen_rtx (CONST_INT, VOIDmode, 48);
+ rtx shift_48 = GEN_INT (48);
int op1_subword = 0;
if (GET_CODE (operand1) == SUBREG)
@@ -2697,7 +2960,7 @@
(define_insn "*zero_extendhidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"lduh %1,%0"
[(set_attr "type" "load")])
@@ -2706,13 +2969,13 @@
(define_expand "zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
- "TARGET_V9"
+ "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_V9 && GET_CODE (operands[1]) != CONST_INT"
+ "TARGET_ARCH64 && GET_CODE (operands[1]) != CONST_INT"
"@
srl %1,0,%0
lduw %1,%0"
@@ -2722,7 +2985,7 @@
;; Simplify comparisons of extended values.
(define_insn "*cmp_zero_extendqisi2"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC (zero_extend:SI (match_operand:QI 0 "register_operand" "r"))
(const_int 0)))]
""
@@ -2730,7 +2993,7 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_zero_extendqisi2_set"
- [(set (reg:CC 0)
+ [(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")
@@ -2742,7 +3005,7 @@
;; Similarly, handle SI->QI mode truncation followed by a compare.
(define_insn "*cmp_siqi_trunc"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC (subreg:QI (match_operand:SI 0 "register_operand" "r") 0)
(const_int 0)))]
""
@@ -2750,7 +3013,7 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_siqi_trunc_set"
- [(set (reg:CC 0)
+ [(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")
@@ -2772,7 +3035,7 @@
"
{
rtx temp = gen_reg_rtx (SImode);
- rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16);
+ rtx shift_16 = GEN_INT (16);
int op1_subword = 0;
if (GET_CODE (operand1) == SUBREG)
@@ -2802,7 +3065,7 @@
"
{
rtx temp = gen_reg_rtx (SImode);
- rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
+ rtx shift_24 = GEN_INT (24);
int op1_subword = 0;
int op0_subword = 0;
@@ -2839,7 +3102,7 @@
"
{
rtx temp = gen_reg_rtx (SImode);
- rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24);
+ rtx shift_24 = GEN_INT (24);
int op1_subword = 0;
if (GET_CODE (operand1) == SUBREG)
@@ -2865,11 +3128,11 @@
(define_expand "extendqidi2"
[(set (match_operand:DI 0 "register_operand" "")
(sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"
{
rtx temp = gen_reg_rtx (DImode);
- rtx shift_56 = gen_rtx (CONST_INT, VOIDmode, 56);
+ rtx shift_56 = GEN_INT (56);
int op1_subword = 0;
if (GET_CODE (operand1) == SUBREG)
@@ -2888,18 +3151,18 @@
(define_insn "*sign_extendqidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"ldsb %1,%0"
[(set_attr "type" "load")])
(define_expand "extendhidi2"
[(set (match_operand:DI 0 "register_operand" "")
(sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"
{
rtx temp = gen_reg_rtx (DImode);
- rtx shift_48 = gen_rtx (CONST_INT, VOIDmode, 48);
+ rtx shift_48 = GEN_INT (48);
int op1_subword = 0;
if (GET_CODE (operand1) == SUBREG)
@@ -2918,20 +3181,20 @@
(define_insn "*sign_extendhidi2_insn"
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_V9"
+ "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_V9"
+ "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_V9"
+ "TARGET_ARCH64"
"@
sra %1,0,%0
ldsw %1,%0"
@@ -2942,7 +3205,7 @@
;; because combine uses this as a canonical form.
(define_insn "*cmp_zero_extract"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC
(zero_extract:SI (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "small_int" "n")
@@ -2955,25 +3218,25 @@
int pos = 32 - INTVAL (operands[2]) - len;
unsigned mask = ((1 << len) - 1) << pos;
- operands[1] = gen_rtx (CONST_INT, VOIDmode, mask);
+ operands[1] = GEN_INT (mask);
return \"andcc %0,%1,%%g0\";
}")
(define_insn "*cmp_zero_extract_sp64"
- [(set (reg:CCX 0)
+ [(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_V9 && INTVAL (operands[2]) > 51"
+ "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
"*
{
int len = INTVAL (operands[1]);
int pos = 64 - INTVAL (operands[2]) - len;
- unsigned mask = ((1 << len) - 1) << pos;
+ unsigned HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
- operands[1] = gen_rtx (CONST_INT, VOIDmode, mask);
+ operands[1] = GEN_INT (mask);
return \"andcc %0,%1,%%g0\";
}")
@@ -3058,7 +3321,7 @@
(float:SF (match_operand:DI 1 "general_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"
{
operands[2] = gen_reg_rtx (DFmode);
@@ -3070,7 +3333,7 @@
(float:DF (match_operand:DI 1 "general_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"
{
operands[2] = gen_reg_rtx (DFmode);
@@ -3082,7 +3345,7 @@
(float:TF (match_operand:DI 1 "general_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"
{
operands[2] = gen_reg_rtx (DFmode);
@@ -3094,7 +3357,7 @@
(float:SF (match_operand:DI 1 "general_operand" "rm")))
(clobber (match_operand:DF 2 "register_operand" "=&e"))
(clobber (match_operand:DI 3 "memory_operand" "m"))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"*
{
if (GET_CODE (operands[1]) == MEM)
@@ -3111,7 +3374,7 @@
(float:DF (match_operand:DI 1 "general_operand" "rm")))
(clobber (match_operand:DF 2 "register_operand" "=&e"))
(clobber (match_operand:DI 3 "memory_operand" "m"))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"*
{
if (GET_CODE (operands[1]) == MEM)
@@ -3128,7 +3391,7 @@
(float:TF (match_operand:DI 1 "general_operand" "rm")))
(clobber (match_operand:DF 2 "register_operand" "=&e"))
(clobber (match_operand:DI 3 "memory_operand" "m"))])]
- "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"*
{
if (GET_CODE (operands[1]) == MEM)
@@ -3145,21 +3408,21 @@
(define_insn "floatdisf2_sp64"
[(set (match_operand:SF 0 "register_operand" "=f")
(float:SF (match_operand:DI 1 "register_operand" "e")))]
- "0 && TARGET_V9 && TARGET_FPU"
+ "0 && TARGET_ARCH64 && TARGET_FPU"
"fxtos %1,%0"
[(set_attr "type" "fp")])
(define_insn "floatdidf2_sp64"
[(set (match_operand:DF 0 "register_operand" "=e")
(float:DF (match_operand:DI 1 "register_operand" "e")))]
- "0 && TARGET_V9 && TARGET_FPU"
+ "0 && TARGET_ARCH64 && TARGET_FPU"
"fxtod %1,%0"
[(set_attr "type" "fp")])
(define_insn "floatditf2_sp64"
[(set (match_operand:TF 0 "register_operand" "=e")
(float:TF (match_operand:DI 1 "register_operand" "e")))]
- "0 && TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
+ "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"fxtoq %1,%0"
[(set_attr "type" "fp")])
@@ -3200,7 +3463,7 @@
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"
{
operands[2] = gen_reg_rtx (DFmode);
@@ -3212,7 +3475,7 @@
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"
{
operands[2] = gen_reg_rtx (DFmode);
@@ -3224,7 +3487,7 @@
(fix:DI (fix:TF (match_operand:TF 1 "register_operand" ""))))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"
{
operands[2] = gen_reg_rtx (DFmode);
@@ -3236,7 +3499,7 @@
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
(clobber (match_operand:DF 2 "register_operand" "=&e"))
(clobber (match_operand:DI 3 "memory_operand" "m"))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"*
{
output_asm_insn (\"fstox %1,%2\", operands);
@@ -3253,7 +3516,7 @@
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))
(clobber (match_operand:DF 2 "register_operand" "=&e"))
(clobber (match_operand:DI 3 "memory_operand" "m"))])]
- "TARGET_V9 && TARGET_FPU"
+ "TARGET_ARCH64 && TARGET_FPU"
"*
{
output_asm_insn (\"fdtox %1,%2\", operands);
@@ -3270,7 +3533,7 @@
(fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))
(clobber (match_operand:DF 2 "register_operand" "=&e"))
(clobber (match_operand:DI 3 "memory_operand" "m"))])]
- "TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
+ "TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"*
{
output_asm_insn (\"fqtox %1,%2\", operands);
@@ -3287,21 +3550,21 @@
(define_insn "fix_truncsfdi2_sp64"
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
- "0 && TARGET_V9 && TARGET_FPU"
+ "0 && TARGET_ARCH64 && TARGET_FPU"
"fstox %1,%0"
[(set_attr "type" "fp")])
(define_insn "fix_truncdfdi2_sp64"
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
- "0 && TARGET_V9 && TARGET_FPU"
+ "0 && TARGET_ARCH64 && TARGET_FPU"
"fdtox %1,%0"
[(set_attr "type" "fp")])
(define_insn "fix_trunctfdi2_sp64"
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:TF (match_operand:TF 1 "register_operand" "e"))))]
- "0 && TARGET_V9 && TARGET_FPU && TARGET_HARD_QUAD"
+ "0 && TARGET_ARCH64 && TARGET_FPU && TARGET_HARD_QUAD"
"fqtox %1,%0"
[(set_attr "type" "fp")])
@@ -3314,13 +3577,14 @@
""
"
{
- if (! TARGET_V9)
+ 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, SImode, 0)))));
+ gen_rtx (CLOBBER, VOIDmode,
+ gen_rtx (REG, SImode, SPARC_ICC_REG)))));
DONE;
}
}")
@@ -3329,35 +3593,29 @@
[(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:SI 0))]
- "! TARGET_V9"
+ (clobber (reg:SI 100))]
+ "! TARGET_ARCH64"
"*
{
rtx op2 = operands[2];
- /* If constant is positive, upper bits zeroed, otherwise unchanged.
- Give the assembler a chance to pick the move instruction. */
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"addcc %R1,%2,%R0\;addx %1,-1,%0\";
- return \"addcc %R1,%2,%R0\;addx %1,0,%0\";
- }
- else if (GET_CODE (op2) == CONST_DOUBLE)
+ if (GET_CODE (op2) == CONST_INT
+ || GET_CODE (op2) == CONST_DOUBLE)
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
- xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
- if (xoperands[2] == const0_rtx && xoperands[0] == xoperands[1])
- output_asm_insn (\"add %1,%3,%0\", xoperands);
+ 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 %R1,%2,%R0\;addx %1,%3,%0\", xoperands);
+ output_asm_insn (\"addcc %L1,%3,%L0\;addx %H1,%2,%H0\", xoperands);
return \"\";
}
- return \"addcc %R1,%R2,%R0\;addx %1,%2,%0\";
+ return \"addcc %L1,%L2,%L0\;addx %H1,%H2,%H0\";
}"
[(set_attr "length" "2")])
@@ -3365,7 +3623,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"add %1,%2,%0")
(define_insn "addsi3"
@@ -3377,7 +3635,7 @@
[(set_attr "type" "ialu")])
(define_insn "*cmp_cc_plus"
- [(set (reg:CC_NOOV 0)
+ [(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)))]
@@ -3386,16 +3644,16 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_plus"
- [(set (reg:CCX_NOOV 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"addcc %0,%1,%%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_plus_set"
- [(set (reg:CC_NOOV 0)
+ [(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)))
@@ -3405,13 +3663,13 @@
"addcc %1,%2,%0")
(define_insn "*cmp_ccx_plus_set"
- [(set (reg:CCX_NOOV 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"addcc %1,%2,%0")
(define_expand "subdi3"
@@ -3421,13 +3679,14 @@
""
"
{
- if (! TARGET_V9)
+ 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, SImode, 0)))));
+ gen_rtx (CLOBBER, VOIDmode,
+ gen_rtx (REG, SImode, SPARC_ICC_REG)))));
DONE;
}
}")
@@ -3436,35 +3695,29 @@
[(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:SI 0))]
- "! TARGET_V9"
+ (clobber (reg:SI 100))]
+ "! TARGET_ARCH64"
"*
{
rtx op2 = operands[2];
- /* If constant is positive, upper bits zeroed, otherwise unchanged.
- Give the assembler a chance to pick the move instruction. */
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"subcc %R1,%2,%R0\;subx %1,-1,%0\";
- return \"subcc %R1,%2,%R0\;subx %1,0,%0\";
- }
- else if (GET_CODE (op2) == CONST_DOUBLE)
+ if (GET_CODE (op2) == CONST_INT
+ || GET_CODE (op2) == CONST_DOUBLE)
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
- xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
- if (xoperands[2] == const0_rtx && xoperands[0] == xoperands[1])
- output_asm_insn (\"sub %1,%3,%0\", xoperands);
+ 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 %R1,%2,%R0\;subx %1,%3,%0\", xoperands);
+ output_asm_insn (\"subcc %L1,%3,%L0\;subx %H1,%2,%H0\", xoperands);
return \"\";
}
- return \"subcc %R1,%R2,%R0\;subx %1,%2,%0\";
+ return \"subcc %L1,%L2,%L0\;subx %H1,%H2,%H0\";
}"
[(set_attr "length" "2")])
@@ -3472,7 +3725,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"sub %1,%2,%0")
(define_insn "subsi3"
@@ -3484,7 +3737,7 @@
[(set_attr "type" "ialu")])
(define_insn "*cmp_minus_cc"
- [(set (reg:CC_NOOV 0)
+ [(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)))]
@@ -3493,16 +3746,16 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_minus_ccx"
- [(set (reg:CCX_NOOV 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"subcc %0,%1,%%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_minus_cc_set"
- [(set (reg:CC_NOOV 0)
+ [(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)))
@@ -3512,23 +3765,26 @@
"subcc %1,%2,%0")
(define_insn "*cmp_minus_ccx_set"
- [(set (reg:CCX_NOOV 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"subcc %1,%2,%0")
+
+;; Integer Multiply/Divide.
-;; This is anachronistic, and should not be used in v9 software.
-;; The v9 compiler will widen the args and use muldi3.
+;; 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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"smul %1,%2,%0"
[(set_attr "type" "imul")])
@@ -3536,7 +3792,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"mulx %1,%2,%0")
;; It is not known whether this will match.
@@ -3545,10 +3801,10 @@
[(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 0)
+ (set (reg:CC_NOOV 100)
(compare:CC_NOOV (mult:SI (match_dup 1) (match_dup 2))
(const_int 0)))]
- "TARGET_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_DEPRECATED_V8_INSNS"
"smulcc %1,%2,%0"
[(set_attr "type" "imul")])
@@ -3556,7 +3812,7 @@
[(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"
{
if (CONSTANT_P (operands[2]))
@@ -3570,9 +3826,14 @@
[(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_V8 || TARGET_SPARCLITE"
- "smul %1,%2,%R0\;rd %%y,%0"
- [(set_attr "length" "2")])
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
+ "*
+{
+ 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.
@@ -3580,9 +3841,14 @@
[(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_V8 || TARGET_SPARCLITE"
- "smul %1,%2,%R0\;rd %%y,%0"
- [(set_attr "length" "2")])
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
+ "*
+{
+ 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" "")
@@ -3590,7 +3856,7 @@
(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"
{
if (CONSTANT_P (operands[2]))
@@ -3606,7 +3872,7 @@
(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"smul %1,%2,%%g0\;rd %%y,%0"
[(set_attr "length" "2")])
@@ -3616,7 +3882,7 @@
(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"smul %1,%2,%%g0\;rd %%y,%0"
[(set_attr "length" "2")])
@@ -3624,7 +3890,7 @@
[(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"
{
if (CONSTANT_P (operands[2]))
@@ -3638,9 +3904,14 @@
[(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_V8 || TARGET_SPARCLITE"
- "umul %1,%2,%R0\;rd %%y,%0"
- [(set_attr "length" "2")])
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
+ "*
+{
+ 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.
@@ -3648,9 +3919,14 @@
[(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_V8 || TARGET_SPARCLITE"
- "umul %1,%2,%R0\;rd %%y,%0"
- [(set_attr "length" "2")])
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
+ "*
+{
+ 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_expand "umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "")
@@ -3658,7 +3934,7 @@
(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"
{
if (CONSTANT_P (operands[2]))
@@ -3674,7 +3950,7 @@
(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"umul %1,%2,%%g0\;rd %%y,%0"
[(set_attr "length" "2")])
@@ -3684,11 +3960,11 @@
(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_V8 || TARGET_SPARCLITE"
+ "TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET || TARGET_DEPRECATED_V8_INSNS"
"umul %1,%2,%%g0\;rd %%y,%0"
[(set_attr "length" "2")])
-;; The architecture specifies that there must be 3 instructions between
+;; 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"
@@ -3696,15 +3972,23 @@
(div:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "rI")))
(clobber (match_scratch:SI 3 "=&r"))]
- "TARGET_V8"
- "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdiv %1,%2,%0"
- [(set_attr "length" "6")])
+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ "*
+{
+ 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\";
+}"
+ [(set (attr "length")
+ (if_then_else (eq_attr "isa" "v9")
+ (const_int 3) (const_int 6)))])
(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_V9"
+ "TARGET_ARCH64"
"sdivx %1,%2,%0")
;; It is not known whether this will match.
@@ -3713,27 +3997,43 @@
[(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 0)
+ (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"
- "sra %1,31,%3\;wr %%g0,%3,%%y\;nop\;nop\;nop\;sdivcc %1,%2,%0"
- [(set_attr "length" "6")])
+ "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")
(udiv:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "arith_operand" "rI")))]
- "TARGET_V8"
- "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0"
- [(set_attr "length" "5")])
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ "TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
+ "*
+{
+ if (TARGET_V9)
+ return \"wr %%g0,%%g0,%%y\;udiv %1,%2,%0\";
+ else
+ return \"wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udiv %1,%2,%0\";
+}"
+ [(set (attr "length")
+ (if_then_else (eq_attr "isa" "v9")
+ (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_V9"
+ "TARGET_ARCH64"
"udivx %1,%2,%0")
;; It is not known whether this will match.
@@ -3742,16 +4042,57 @@
[(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 0)
+ (set (reg:CC 100)
(compare:CC (udiv:SI (match_dup 1) (match_dup 2))
(const_int 0)))]
- "TARGET_V8"
- "wr %%g0,%%g0,%%y\;nop\;nop\;nop\;udivcc %1,%2,%0"
- [(set_attr "length" "5")])
+ "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.
+;; 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" "")
@@ -3764,30 +4105,22 @@
[(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_V9"
+ "! TARGET_ARCH64"
"*
{
rtx op2 = operands[2];
- /* If constant is positive, upper bits zeroed, otherwise unchanged.
- Give the assembler a chance to pick the move instruction. */
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"mov %1,%0\;and %R1,%2,%R0\";
- return \"mov 0,%0\;and %R1,%2,%R0\";
- }
- else if (GET_CODE (op2) == CONST_DOUBLE)
+ if (GET_CODE (op2) == CONST_INT
+ || GET_CODE (op2) == CONST_DOUBLE)
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
- xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
- /* We could optimize then operands[1] == operands[0]
- and either half of the constant is -1. */
- output_asm_insn (\"and %R1,%2,%R0\;and %1,%3,%0\", xoperands);
+ 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\";
@@ -3798,7 +4131,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"and %1,%2,%0")
(define_insn "andsi3"
@@ -3821,14 +4154,14 @@
(set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
"
{
- operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
(define_insn "*and_not_di_sp32"
[(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_V9"
+ "! TARGET_ARCH64"
"andn %2,%1,%0\;andn %R2,%R1,%R0"
[(set_attr "length" "2")])
@@ -3836,7 +4169,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"andn %2,%1,%0")
(define_insn "*and_not_si"
@@ -3858,30 +4191,22 @@
[(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_V9"
+ "! TARGET_ARCH64"
"*
{
rtx op2 = operands[2];
- /* If constant is positive, upper bits zeroed, otherwise unchanged.
- Give the assembler a chance to pick the move instruction. */
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"mov -1,%0\;or %R1,%2,%R0\";
- return \"mov %1,%0\;or %R1,%2,%R0\";
- }
- else if (GET_CODE (op2) == CONST_DOUBLE)
+ if (GET_CODE (op2) == CONST_INT
+ || GET_CODE (op2) == CONST_DOUBLE)
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
- xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
- /* We could optimize then operands[1] == operands[0]
- and either half of the constant is 0. */
- output_asm_insn (\"or %R1,%2,%R0\;or %1,%3,%0\", xoperands);
+ 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\";
@@ -3892,7 +4217,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"or %1,%2,%0")
(define_insn "iorsi3"
@@ -3915,14 +4240,14 @@
(set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
"
{
- operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
(define_insn "*or_not_di_sp32"
[(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_V9"
+ "! TARGET_ARCH64"
"orn %2,%1,%0\;orn %R2,%R1,%R0"
[(set_attr "length" "2")])
@@ -3930,7 +4255,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"orn %2,%1,%0")
(define_insn "*or_not_si"
@@ -3952,30 +4277,22 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(xor:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))]
- "! TARGET_V9"
+ "! TARGET_ARCH64"
"*
{
rtx op2 = operands[2];
- /* If constant is positive, upper bits zeroed, otherwise unchanged.
- Give the assembler a chance to pick the move instruction. */
- if (GET_CODE (op2) == CONST_INT)
- {
- int sign = INTVAL (op2);
- if (sign < 0)
- return \"xor %1,-1,%0\;xor %R1,%2,%R0\";
- return \"mov %1,%0\;xor %R1,%2,%R0\";
- }
- else if (GET_CODE (op2) == CONST_DOUBLE)
+ if (GET_CODE (op2) == CONST_INT
+ || GET_CODE (op2) == CONST_DOUBLE)
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = operands[1];
- xoperands[2] = GEN_INT (CONST_DOUBLE_LOW (op2));
- xoperands[3] = GEN_INT (CONST_DOUBLE_HIGH (op2));
- /* We could optimize then operands[1] == operands[0]
- and either half of the constant is 0. */
- output_asm_insn (\"xor %R1,%2,%R0\;xor %1,%3,%0\", xoperands);
+ 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\";
@@ -3986,7 +4303,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"xor %r1,%2,%0")
(define_insn "xorsi3"
@@ -4009,7 +4326,7 @@
(set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
"
{
- operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
(define_split
@@ -4024,7 +4341,7 @@
(set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
"
{
- operands[4] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
+ operands[4] = GEN_INT (~INTVAL (operands[2]));
}")
;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
@@ -4033,7 +4350,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (xor:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "register_operand" "r"))))]
- "! TARGET_V9"
+ "! TARGET_ARCH64"
"xnor %1,%2,%0\;xnor %R1,%R2,%R0"
[(set_attr "length" "2")])
@@ -4041,7 +4358,7 @@
[(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_V9"
+ "TARGET_ARCH64"
"xnor %r1,%2,%0")
(define_insn "*xor_not_si"
@@ -4056,7 +4373,7 @@
;; want to set the condition code.
(define_insn "*cmp_cc_arith_op"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC
(match_operator:SI 2 "cc_arithop"
[(match_operand:SI 0 "arith_operand" "%r")
@@ -4067,18 +4384,18 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op"
- [(set (reg:CCX 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"%A2cc %0,%1,%%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_set"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC
(match_operator:SI 3 "cc_arithop"
[(match_operand:SI 1 "arith_operand" "%r")
@@ -4090,7 +4407,7 @@
"%A3cc %1,%2,%0")
(define_insn "*cmp_ccx_arith_op_set"
- [(set (reg:CCX 0)
+ [(set (reg:CCX 100)
(compare:CCX
(match_operator:DI 3 "cc_arithop"
[(match_operand:DI 1 "arith_double_operand" "%r")
@@ -4098,11 +4415,11 @@
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(match_dup 3))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"%A3cc %1,%2,%0")
(define_insn "*cmp_cc_xor_not"
- [(set (reg:CC 0)
+ [(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")))
@@ -4112,17 +4429,17 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_xor_not"
- [(set (reg:CCX 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"xnorcc %r0,%1,%%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_xor_not_set"
- [(set (reg:CC 0)
+ [(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")))
@@ -4133,18 +4450,18 @@
"xnorcc %r1,%2,%0")
(define_insn "*cmp_ccx_xor_not_set"
- [(set (reg:CCX 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"xnorcc %r1,%2,%0")
(define_insn "*cmp_cc_arith_op_not"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC
(match_operator:SI 2 "cc_arithopn"
[(not:SI (match_operand:SI 0 "arith_operand" "rI"))
@@ -4155,18 +4472,18 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_ccx_arith_op_not"
- [(set (reg:CCX 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"%B2cc %r1,%0,%%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_arith_op_not_set"
- [(set (reg:CC 0)
+ [(set (reg:CC 100)
(compare:CC
(match_operator:SI 3 "cc_arithopn"
[(not:SI (match_operand:SI 1 "arith_operand" "rI"))
@@ -4178,7 +4495,7 @@
"%B3cc %r2,%1,%0")
(define_insn "*cmp_ccx_arith_op_not_set"
- [(set (reg:CCX 0)
+ [(set (reg:CCX 100)
(compare:CCX
(match_operator:DI 3 "cc_arithopn"
[(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
@@ -4186,7 +4503,7 @@
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(match_dup 3))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"%B3cc %r2,%1,%0")
;; We cannot use the "neg" pseudo insn because the Sun assembler
@@ -4198,12 +4515,13 @@
""
"
{
- if (! TARGET_V9)
+ 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, SImode, 0)))));
+ gen_rtx (CLOBBER, VOIDmode,
+ gen_rtx (REG, SImode, SPARC_ICC_REG)))));
DONE;
}
}")
@@ -4211,16 +4529,22 @@
(define_insn "*negdi2_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_operand:DI 1 "register_operand" "r")))
- (clobber (reg:SI 0))]
- "! TARGET_V9"
- "subcc %%g0,%R1,%R0\;subx %%g0,%1,%0"
+ (clobber (reg:SI 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_V9"
+ "TARGET_ARCH64"
"sub %%g0,%1,%0"
[(set_attr "type" "unary")
(set_attr "length" "1")])
@@ -4229,42 +4553,49 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(neg:SI (match_operand:SI 1 "arith_operand" "rI")))]
""
- "sub %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "*
+{
+ 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 0)
+ [(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 0)
+ [(set (reg:CCX_NOOV 100)
(compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
(const_int 0)))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"subcc %%g0,%0,%%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_neg"
- [(set (reg:CC_NOOV 0)
+ [(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 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"subcc %%g0,%1,%0"
[(set_attr "type" "unary")])
@@ -4279,58 +4610,68 @@
(define_insn "*one_cmpldi2_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (match_operand:DI 1 "register_operand" "r")))]
- "! TARGET_V9"
- "xnor %%g0,%1,%0\;xnor %%g0,%R1,%R0"
+ "! TARGET_ARCH64"
+ "xnor %1,0,%0\;xnor %R1,0,%R0"
[(set_attr "type" "unary")
(set_attr "length" "2")])
(define_insn "*one_cmpldi2_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (match_operand:DI 1 "arith_double_operand" "rHI")))]
- "TARGET_V9"
- "xnor %%g0,%1,%0"
+ "TARGET_ARCH64"
+ "xnor %1,0,%0"
[(set_attr "type" "unary")])
(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (not:SI (match_operand:SI 1 "arith_operand" "rI")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (not:SI (match_operand:SI 1 "arith_operand" "r,I")))]
""
- "xnor %%g0,%1,%0"
- [(set_attr "type" "unary")])
+ "*
+{
+ if (which_alternative == 0)
+ return \"xnor %1,0,%0\";
+ if (TARGET_LIVE_G0)
+ output_asm_insn (\"and %%g0,0,%%g0\", operands);
+ return \"xnor %%g0,%1,%0\";
+}"
+ [(set_attr "type" "unary")
+ (set_attr_alternative "length"
+ [(const_int 1)
+ (if_then_else (eq_attr "live_g0" "yes") (const_int 2) (const_int 1))])])
(define_insn "*cmp_cc_not"
- [(set (reg:CC 0)
+ [(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 0)
+ [(set (reg:CCX 100)
(compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
(const_int 0)))]
- "TARGET_V9"
+ "TARGET_ARCH64"
"xnorcc %%g0,%0,%%g0"
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_not"
- [(set (reg:CC 0)
+ [(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 0)
+ [(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_V9"
+ "TARGET_ARCH64"
"xnorcc %%g0,%1,%0"
[(set_attr "type" "unary")])
@@ -4420,7 +4761,7 @@
[(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_V8 || TARGET_V9) && TARGET_FPU && TARGET_HARD_QUAD"
"fdmulq %1,%2,%0"
[(set_attr "type" "fpmul")])
@@ -4452,20 +4793,21 @@
(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"
"*
{
- if (TARGET_V9)
- return \"fnegd %1,%0\"; /* Can't use fnegs, won't work with upper regs. */
- else if (which_alternative == 0)
- return \"fnegs %0,%0\";
+ /* 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 \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
+ return TARGET_V9 ? \"fnegd %1,%0\;fmovd %S1,%S0\"
+ : \"fnegs %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
}"
[(set_attr "type" "fp")
(set_attr_alternative "length"
[(const_int 1)
- (if_then_else (eq_attr "arch" "arch32bit") (const_int 4) (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")
@@ -4483,7 +4825,7 @@
[(set_attr "type" "fp")
(set_attr_alternative "length"
[(const_int 1)
- (if_then_else (eq_attr "arch" "arch32bit") (const_int 2) (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")
@@ -4495,20 +4837,21 @@
(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"
"*
{
- if (TARGET_V9)
- return \"fabsd %1,%0\"; /* Can't use fabss, won't work with upper regs. */
- else if (which_alternative == 0)
- return \"fabss %0,%0\";
+ /* 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 \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
+ return TARGET_V9 ? \"fabsd %1,%0\;fmovd %S1,%S0\"
+ : \"fabss %1,%0\;fmovs %R1,%R0\;fmovs %S1,%S0\;fmovs %T1,%T0\";
}"
[(set_attr "type" "fp")
(set_attr_alternative "length"
[(const_int 1)
- (if_then_else (eq_attr "arch" "arch32bit") (const_int 4) (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")
@@ -4526,7 +4869,7 @@
[(set_attr "type" "fp")
(set_attr_alternative "length"
[(const_int 1)
- (if_then_else (eq_attr "arch" "arch32bit") (const_int 2) (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")
@@ -4566,7 +4909,7 @@
"*
{
if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned) INTVAL (operands[2]) > 31)
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
return \"sll %1,%2,%0\";
@@ -4577,18 +4920,18 @@
[(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_V9"
+ "TARGET_ARCH64"
"*
{
if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned) INTVAL (operands[2]) > 63)
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
return \"sllx %1,%2,%0\";
}")
(define_insn "*cmp_cc_ashift_1"
- [(set (reg:CC_NOOV 0)
+ [(set (reg:CC_NOOV 100)
(compare:CC_NOOV (ashift:SI (match_operand:SI 0 "register_operand" "r")
(const_int 1))
(const_int 0)))]
@@ -4597,7 +4940,7 @@
[(set_attr "type" "compare")])
(define_insn "*cmp_cc_set_ashift_1"
- [(set (reg:CC_NOOV 0)
+ [(set (reg:CC_NOOV 100)
(compare:CC_NOOV (ashift:SI (match_operand:SI 1 "register_operand" "r")
(const_int 1))
(const_int 0)))
@@ -4614,7 +4957,7 @@
"*
{
if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned) INTVAL (operands[2]) > 31)
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
return \"sra %1,%2,%0\";
@@ -4625,11 +4968,11 @@
[(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_V9"
+ "TARGET_ARCH64"
"*
{
if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned) INTVAL (operands[2]) > 63)
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
return \"srax %1,%2,%0\";
@@ -4643,7 +4986,7 @@
"*
{
if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned) INTVAL (operands[2]) > 31)
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 31)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
return \"srl %1,%2,%0\";
@@ -4654,11 +4997,11 @@
[(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_V9"
+ "TARGET_ARCH64"
"*
{
if (GET_CODE (operands[2]) == CONST_INT
- && (unsigned) INTVAL (operands[2]) > 63)
+ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 63)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
return \"srlx %1,%2,%0\";
@@ -4671,13 +5014,27 @@
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
- "b%* %l0%("
+ "*
+{
+ /* Some implementations 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 "" "")))])]
- "! TARGET_MEDANY"
+ ""
"
{
if (GET_MODE (operands[0]) != Pmode)
@@ -4725,54 +5082,6 @@
"jmp %a0%#"
[(set_attr "type" "uncond_branch")])
-(define_insn "*get_pc_sp32"
- [(set (pc) (label_ref (match_operand 0 "" "")))
- (set (reg:SI 15) (label_ref (match_dup 0)))]
- "! TARGET_PTR64"
- "call %l0%#"
- [(set_attr "type" "uncond_branch")])
-
-(define_insn "*get_pc_sp64"
- [(set (pc) (label_ref (match_operand 0 "" "")))
- (set (reg:DI 15) (label_ref (match_dup 0)))]
- "TARGET_PTR64"
- "call %l0%#"
- [(set_attr "type" "uncond_branch")])
-
-;; Implement a switch statement for the medium/anywhere code model.
-;; This wouldn't be necessary if we could distinguish label refs of the jump
-;; table from other label refs. The problem is that jump tables live in the
-;; .rodata section and thus we need to add %g4 to get their address.
-
-(define_expand "casesi"
- [(set (match_dup 5)
- (minus:SI (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "nonmemory_operand" "")))
- (set (reg:CC 0)
- (compare:CC (match_dup 5)
- (match_operand:SI 2 "nonmemory_operand" "")))
- (set (pc)
- (if_then_else (gtu (reg:CC 0)
- (const_int 0))
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (parallel [(set (match_dup 6) (high:DI (label_ref (match_operand 3 "" ""))))
- (clobber (reg:DI 1))])
- (set (match_dup 6)
- (lo_sum:DI (match_dup 6) (label_ref (match_dup 3))))
- (set (match_dup 6) (plus:DI (match_dup 6) (reg:DI 4)))
- (set (match_dup 7) (zero_extend:DI (match_dup 5)))
- (set (match_dup 7) (ashift:DI (match_dup 7) (const_int 3)))
- (set (match_dup 7) (mem:DI (plus:DI (match_dup 6) (match_dup 7))))
- (set (pc) (match_dup 7))]
- "TARGET_MEDANY"
- "
-{
- operands[5] = gen_reg_rtx (SImode);
- operands[6] = gen_reg_rtx (DImode);
- operands[7] = gen_reg_rtx (DImode);
-}")
-
;; 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.
@@ -4798,7 +5107,7 @@
if (GET_MODE (operands[0]) != FUNCTION_MODE)
abort ();
- if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
+ 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 it's delay slots can be filled.
@@ -4807,19 +5116,23 @@
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_V9 && INTVAL (operands[3]) != 0)
- emit_jump_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
- gen_rtx (SET, VOIDmode, pc_rtx,
- XEXP (operands[0], 0)),
- operands[3],
- gen_rtx (CLOBBER, VOIDmode,
- gen_rtx (REG, Pmode, 15)))));
+ 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)))));
+ 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;
}
@@ -4830,30 +5143,32 @@
means 6 on the sparc. */
#if 0
if (operands[2])
- nregs_rtx = gen_rtx (CONST_INT, VOIDmode, REGNO (operands[2]) - 8);
+ nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
else
- nregs_rtx = gen_rtx (CONST_INT, VOIDmode, 6);
+ nregs_rtx = GEN_INT (6);
#else
nregs_rtx = const0_rtx;
#endif
- if (! TARGET_V9 && INTVAL (operands[3]) != 0)
- emit_call_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (3,
- gen_rtx (CALL, VOIDmode, fn_rtx, nregs_rtx),
- operands[3],
- gen_rtx (CLOBBER, VOIDmode,
- gen_rtx (REG, Pmode, 15)))));
+ 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)))));
+ 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_V9 && INTVAL (operands[3]) > 0)
+ if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
{
rtx insn = emit_insn (operands[3]);
SCHED_GROUP_P (insn) = 1;
@@ -4910,7 +5225,7 @@
(match_operand 2 "immediate_operand" "")
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
+ "! 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")])
@@ -4922,7 +5237,7 @@
(match_operand 2 "immediate_operand" "")
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
+ "! 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")])
@@ -4934,7 +5249,7 @@
(match_operand 2 "immediate_operand" "")
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
+ "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call %a0,%1\;nop\;nop"
[(set_attr "type" "call_no_delay_slot")])
@@ -4945,7 +5260,7 @@
(match_operand 2 "immediate_operand" "")
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_V9 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
+ "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
"call %a0,%1\;nop\;nop"
[(set_attr "type" "call_no_delay_slot")])
@@ -5073,10 +5388,10 @@
"
{
rtx valreg1 = gen_rtx (REG, DImode, 24);
- rtx valreg2 = gen_rtx (REG, TARGET_V9 ? TFmode : DFmode, 32);
+ rtx valreg2 = gen_rtx (REG, TARGET_ARCH64 ? TFmode : DFmode, 32);
rtx result = operands[0];
- if (! TARGET_V9)
+ if (! TARGET_ARCH64)
{
rtx rtnreg = gen_rtx (REG, SImode, (leaf_function ? 15 : 31));
rtx value = gen_reg_rtx (SImode);
@@ -5093,7 +5408,7 @@
/* Reload the function value registers. */
emit_move_insn (valreg1, change_address (result, DImode, XEXP (result, 0)));
emit_move_insn (valreg2,
- change_address (result, TARGET_V9 ? TFmode : DFmode,
+ change_address (result, TARGET_ARCH64 ? TFmode : DFmode,
plus_constant (XEXP (result, 0), 8)));
/* Put USE insns before the return. */
@@ -5112,12 +5427,13 @@
(define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "register_operand" "r")] 0)]
- "! TARGET_V9"
+ "! TARGET_ARCH64"
"cmp %1,0\;be,a .+8\;add %0,4,%0"
[(set_attr "type" "multi")])
(define_insn "return"
- [(return)]
+ [(return)
+ (use (reg:SI 31))]
"! TARGET_EPILOGUE"
"* return output_return (operands);"
[(set_attr "type" "multi")])
@@ -5177,9 +5493,9 @@
emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx));
emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
- emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, Pmode, 8)));
/* Return, restoring reg window and jumping to goto handler. */
emit_insn (gen_goto_handler_and_restore ());
+ emit_barrier ();
DONE;
}")
@@ -5187,16 +5503,48 @@
(define_insn "flush_register_windows"
[(unspec_volatile [(const_int 0)] 1)]
""
- "* return TARGET_V9 ? \"flushw\" : \"ta 3\";"
+ ;; ??? Use TARGET_V9 instead?
+ "* return TARGET_ARCH64 ? \"flushw\" : \"ta 3\";"
[(set_attr "type" "misc")])
(define_insn "goto_handler_and_restore"
- [(unspec_volatile [(const_int 0)] 2)]
+ [(unspec_volatile [(const_int 0)] 2)
+ (use (reg:SI 8))]
""
"jmp %%o0+0\;restore"
[(set_attr "type" "misc")
(set_attr "length" "2")])
+;; 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"
@@ -5216,8 +5564,13 @@
[(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"
- "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"
+ "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")])
@@ -5228,8 +5581,8 @@
[(set (match_operand:DI 0 "register_operand" "=&r")
(ffs:DI (match_operand:DI 1 "register_operand" "r")))
(clobber (match_scratch:DI 2 "=&r"))]
- "TARGET_V9"
- "neg %1,%2\;not %2,%2\;xor %1,%2,%2\;popc %2,%0\;movrz %1,%%g0,%0"
+ "TARGET_ARCH64"
+ "neg %1,%2\;not %2,%2\;xor %1,%2,%2\;popc %2,%0\;movrz %1,0,%0"
[(set_attr "type" "multi")
(set_attr "length" "5")])
@@ -5317,7 +5670,7 @@
(lo_sum:SI (match_dup 0) (match_dup 1)))]
"")
-;; LABEL_REFs are not modified by `legitimize_pic_address`
+;; 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" "")
@@ -5340,44 +5693,44 @@
[(set (match_operand:SI 0 "register_operand" "")
(ne:SI (match_operand:SI 1 "register_operand" "")
(const_int 0)))
- (clobber (reg:CC 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (ltu:SI (reg:CC 0) (const_int 0)))]
+ [(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 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (neg:SI (ltu:SI (reg:CC 0) (const_int 0))))]
+ [(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 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (geu:SI (reg:CC 0) (const_int 0)))]
+ [(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 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (neg:SI (geu:SI (reg:CC 0) (const_int 0))))]
+ [(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
@@ -5385,11 +5738,11 @@
(plus:SI (ne:SI (match_operand:SI 1 "register_operand" "")
(const_int 0))
(match_operand:SI 2 "register_operand" "")))
- (clobber (reg:CC 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (plus:SI (ltu:SI (reg:CC 0) (const_int 0))
+ [(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)))]
"")
@@ -5398,12 +5751,12 @@
(minus:SI (match_operand:SI 2 "register_operand" "")
(ne:SI (match_operand:SI 1 "register_operand" "")
(const_int 0))))
- (clobber (reg:CC 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
+ [(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 0) (const_int 0))))]
+ (ltu:SI (reg:CC 100) (const_int 0))))]
"")
(define_split
@@ -5411,11 +5764,11 @@
(plus:SI (eq:SI (match_operand:SI 1 "register_operand" "")
(const_int 0))
(match_operand:SI 2 "register_operand" "")))
- (clobber (reg:CC 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
- (set (match_dup 0) (plus:SI (geu:SI (reg:CC 0) (const_int 0))
+ [(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)))]
"")
@@ -5424,12 +5777,12 @@
(minus:SI (match_operand:SI 2 "register_operand" "")
(eq:SI (match_operand:SI 1 "register_operand" "")
(const_int 0))))
- (clobber (reg:CC 0))]
+ (clobber (reg:CC 100))]
""
- [(set (reg:CC_NOOV 0) (compare:CC_NOOV (neg:SI (match_dup 1))
- (const_int 0)))
+ [(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 0) (const_int 0))))]
+ (geu:SI (reg:CC 100) (const_int 0))))]
"")
;; Peepholes go at the end.
@@ -5443,7 +5796,7 @@
(match_operand:SI 1 "memory_operand" ""))
(set (match_operand:SI 2 "register_operand" "=rf")
(match_operand:SI 3 "memory_operand" ""))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5454,7 +5807,7 @@
(match_operand:SI 1 "register_operand" "rf"))
(set (match_operand:SI 2 "memory_operand" "")
(match_operand:SI 3 "register_operand" "rf"))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5465,7 +5818,7 @@
(match_operand:SF 1 "memory_operand" ""))
(set (match_operand:SF 2 "register_operand" "=fr")
(match_operand:SF 3 "memory_operand" ""))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5476,7 +5829,7 @@
(match_operand:SF 1 "register_operand" "fr"))
(set (match_operand:SF 2 "memory_operand" "")
(match_operand:SF 3 "register_operand" "fr"))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5487,7 +5840,7 @@
(match_operand:SI 1 "memory_operand" ""))
(set (match_operand:SI 2 "register_operand" "=rf")
(match_operand:SI 3 "memory_operand" ""))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5498,7 +5851,7 @@
(match_operand:SI 1 "register_operand" "rf"))
(set (match_operand:SI 2 "memory_operand" "")
(match_operand:SI 3 "register_operand" "rf"))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5509,7 +5862,7 @@
(match_operand:SF 1 "memory_operand" ""))
(set (match_operand:SF 2 "register_operand" "=fr")
(match_operand:SF 3 "memory_operand" ""))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5520,7 +5873,7 @@
(match_operand:SF 1 "register_operand" "fr"))
(set (match_operand:SF 2 "memory_operand" "")
(match_operand:SF 3 "register_operand" "fr"))]
- "! TARGET_V9
+ "! TARGET_ARCH64
&& 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))"
@@ -5533,25 +5886,25 @@
(define_peephole
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operand:SI 1 "register_operand" "r"))
- (set (reg:CC 0)
+ (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,%%g0,%0")
+ "orcc %1,0,%0")
(define_peephole
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "register_operand" "r"))
- (set (reg:CCX 0)
+ (set (reg:CCX 100)
(compare:CCX (match_operand:DI 2 "register_operand" "r")
(const_int 0)))]
- "TARGET_V9
+ "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,%%g0,%0")
+ "orcc %1,0,%0")
;; Do {sign,zero}-extended compares somewhat more efficiently.
;; ??? Is this now the Right Way to do this? Or will SCRATCH
@@ -5562,44 +5915,44 @@
(match_operand:HI 1 "memory_operand" ""))
(set (match_operand:SI 2 "register_operand" "")
(sign_extend:SI (match_dup 0)))
- (set (reg:CC 0)
+ (set (reg:CC 100)
(compare:CC (match_dup 2)
(const_int 0)))]
""
- "ldsh %1,%0\;orcc %0,%%g0,%2")
+ "ldsh %1,%0\;orcc %0,0,%2")
(define_peephole
[(set (match_operand:HI 0 "register_operand" "")
(match_operand:HI 1 "memory_operand" ""))
(set (match_operand:DI 2 "register_operand" "")
(sign_extend:DI (match_dup 0)))
- (set (reg:CCX 0)
+ (set (reg:CCX 100)
(compare:CCX (match_dup 2)
(const_int 0)))]
- "TARGET_V9"
- "ldsh %1,%0\;orcc %0,%%g0,%2")
+ "TARGET_ARCH64"
+ "ldsh %1,%0\;orcc %0,0,%2")
(define_peephole
[(set (match_operand:QI 0 "register_operand" "")
(match_operand:QI 1 "memory_operand" ""))
(set (match_operand:SI 2 "register_operand" "")
(sign_extend:SI (match_dup 0)))
- (set (reg:CC 0)
+ (set (reg:CC 100)
(compare:CC (match_dup 2)
(const_int 0)))]
""
- "ldsb %1,%0\;orcc %0,%%g0,%2")
+ "ldsb %1,%0\;orcc %0,0,%2")
(define_peephole
[(set (match_operand:QI 0 "register_operand" "")
(match_operand:QI 1 "memory_operand" ""))
(set (match_operand:DI 2 "register_operand" "")
(sign_extend:DI (match_dup 0)))
- (set (reg:CCX 0)
+ (set (reg:CCX 100)
(compare:CCX (match_dup 2)
(const_int 0)))]
- "TARGET_V9"
- "ldsb %1,%0\;orcc %0,%%g0,%2")
+ "TARGET_ARCH64"
+ "ldsb %1,%0\;orcc %0,0,%2")
;; Floating-point move peepholes
;; ??? v9: Do we want similar ones?
@@ -5630,19 +5983,17 @@
"RTX_UNCHANGING_P (operands[1]) && reg_unused_after (operands[0], insn)"
"ld [%0+%%lo(%a1)],%2")
-;; Return peepholes. First the "normal" ones
-
-;; ??? There are QImode, HImode, and SImode versions of this pattern.
-;; It might be possible to write one more general pattern instead of three.
+;; 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_EPILOGUE && ! TARGET_LIVE_G0"
"*
{
- if (! TARGET_V9 && current_function_returns_struct)
+ if (! TARGET_ARCH64 && current_function_returns_struct)
return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
else
return \"ret\;restore %%g0,%1,%Y0\";
@@ -5653,10 +6004,10 @@
[(set (match_operand:HI 0 "restore_operand" "")
(match_operand:HI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
"*
{
- if (! TARGET_V9 && current_function_returns_struct)
+ if (! TARGET_ARCH64 && current_function_returns_struct)
return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
else
return \"ret\;restore %%g0,%1,%Y0\";
@@ -5667,10 +6018,10 @@
[(set (match_operand:SI 0 "restore_operand" "")
(match_operand:SI 1 "arith_operand" "rI"))
(return)]
- "! TARGET_EPILOGUE"
+ "! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
"*
{
- if (! TARGET_V9 && current_function_returns_struct)
+ if (! TARGET_ARCH64 && current_function_returns_struct)
return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
else
return \"ret\;restore %%g0,%1,%Y0\";
@@ -5684,10 +6035,10 @@
[(set (match_operand:SF 0 "restore_operand" "r")
(match_operand:SF 1 "register_operand" "r"))
(return)]
- "! TARGET_FPU && ! TARGET_EPILOGUE"
+ "! TARGET_FPU && ! TARGET_EPILOGUE && ! TARGET_LIVE_G0"
"*
{
- if (! TARGET_V9 && current_function_returns_struct)
+ if (! TARGET_ARCH64 && current_function_returns_struct)
return \"jmp %%i7+12\;restore %%g0,%1,%Y0\";
else
return \"ret\;restore %%g0,%1,%Y0\";
@@ -5699,10 +6050,12 @@
(plus:SI (match_operand:SI 1 "arith_operand" "%r")
(match_operand:SI 2 "arith_operand" "rI")))
(return)]
- "! TARGET_EPILOGUE"
+ "! TARGET_EPILOGUE && ! TARGET_LIVE_G0
+ && (register_operand (operands[1], SImode)
+ || register_operand (operands[2], SImode))"
"*
{
- if (! TARGET_V9 && current_function_returns_struct)
+ if (! TARGET_ARCH64 && current_function_returns_struct)
return \"jmp %%i7+12\;restore %r1,%2,%Y0\";
else
return \"ret\;restore %r1,%2,%Y0\";
@@ -5713,30 +6066,29 @@
[(set (match_operand:DI 0 "restore_operand" "")
(match_operand:DI 1 "arith_double_operand" "rHI"))
(return)]
- "TARGET_V9 && ! TARGET_EPILOGUE"
+ "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")
+ (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
(match_operand:DI 2 "arith_double_operand" "rHI")))
(return)]
- "TARGET_V9 && ! TARGET_EPILOGUE"
+ "TARGET_ARCH64 && ! TARGET_EPILOGUE
+ && (register_operand (operands[1], DImode)
+ || register_operand (operands[2], DImode))"
"ret\;restore %r1,%2,%Y0"
[(set_attr "type" "multi")])
-;; Turned off because it should never match (subtracting a constant
-;; is turned into addition) and because it would do the wrong thing
-;; when operand 2 is -4096 (--4096 == 4096 is not a valid immediate).
-;;(define_insn "*minus_const"
-;; [(set (match_operand:SI 0 "restore_operand" "")
-;; (minus:SI (match_operand:SI 1 "register_operand" "r")
-;; (match_operand:SI 2 "small_int" "I")))
-;; (return)]
-;; "! TARGET_EPILOGUE"
-;; "ret\;restore %1,-(%2),%Y0"
-;; [(set_attr "type" "multi")])
+(define_insn "*return_subsi"
+ [(set (match_operand:SI 0 "restore_operand" "")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "small_int" "I")))
+ (return)]
+ "! TARGET_EPILOGUE && INTVAL (operands[2]) != -4096"
+ "ret\;restore %1,%n2,%Y0"
+ [(set_attr "type" "multi")])
;; The following pattern is only generated by delayed-branch scheduling,
;; when the insn winds up in the epilogue.
@@ -5776,7 +6128,7 @@
(match_operand 2 "" "")))
(clobber (reg:DI 15))])
(set (pc) (label_ref (match_operand 3 "" "")))]
- "TARGET_V9 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
+ "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))"
"call %a1,%2\;add %%o7,(%l3-.-4),%%o7")
(define_peephole
@@ -5784,16 +6136,26 @@
(match_operand 1 "" ""))
(clobber (reg:DI 15))])
(set (pc) (label_ref (match_operand 2 "" "")))]
- "TARGET_V9 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
+ "TARGET_ARCH64 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))"
"call %a0,%1\;add %%o7,(%l2-.-4),%%o7")
;; Other miscellaneous peepholes.
+;; (reg:SI 100) is created by the {add,neg,sub}di patterns.
(define_peephole
[(parallel [(set (match_operand:SI 0 "register_operand" "=r")
(minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
- (reg:SI 0)))
- (clobber (reg:CC 0))])
- (set (reg:CC 0) (compare (match_dup 0) (const_int 0)))]
+ (reg:SI 100)))
+ (clobber (reg:CC 100))])
+ (set (reg:CC 100) (compare (match_dup 0) (const_int 0)))]
""
"subxcc %r1,0,%0")
+
+;; 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"
+ "")
diff --git a/gnu/usr.bin/gcc/config/sparc/sun4o3.h b/gnu/usr.bin/gcc/config/sparc/sun4o3.h
index 5fcb72f4a63..68ddc632794 100644
--- a/gnu/usr.bin/gcc/config/sparc/sun4o3.h
+++ b/gnu/usr.bin/gcc/config/sparc/sun4o3.h
@@ -5,6 +5,6 @@
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. */
+/* LINK_SPEC is needed only for SunOS 4. */
#undef LINK_SPEC
diff --git a/gnu/usr.bin/gcc/config/sparc/sunos4.h b/gnu/usr.bin/gcc/config/sparc/sunos4.h
index 8b17f1e2a2f..070f41aa3b5 100644
--- a/gnu/usr.bin/gcc/config/sparc/sunos4.h
+++ b/gnu/usr.bin/gcc/config/sparc/sunos4.h
@@ -20,4 +20,11 @@ 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
diff --git a/gnu/usr.bin/gcc/config/sparc/sysv4.h b/gnu/usr.bin/gcc/config/sparc/sysv4.h
index ccbe4cc9823..e8a9a603b6f 100644
--- a/gnu/usr.bin/gcc/config/sparc/sysv4.h
+++ b/gnu/usr.bin/gcc/config/sparc/sysv4.h
@@ -1,5 +1,5 @@
/* Target definitions for GNU compiler for Sparc running System V.4
- Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
Written by Ron Guilmette (rfg@netcom.com).
@@ -52,9 +52,7 @@ Boston, MA 02111-1307, USA. */
the Sparc running svr4. __svr4__ is our extension. */
#define CPP_PREDEFINES \
- "-Dsparc -Dunix -D__svr4__ \
- -Asystem(unix) -Asystem(svr4) -Acpu(sparc) -Amachine(sparc) \
- -D__GCC_NEW_VARARGS__"
+"-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
@@ -64,8 +62,8 @@ Boston, MA 02111-1307, USA. */
/* Pass -K to the assembler when PIC. */
#undef ASM_SPEC
#define ASM_SPEC \
- "%{V} %{v:%{!V:-V}} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
- %{fpic:-K PIC} %{fPIC:-K PIC}"
+ "%{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
@@ -77,11 +75,6 @@ Boston, MA 02111-1307, USA. */
const_section (); \
}
-/* This is the string used to begin an assembly language comment for the
- Sparc/svr4 assembler. */
-
-#define ASM_COMMENT_START "!"
-
/* 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
@@ -91,11 +84,16 @@ Boston, MA 02111-1307, USA. */
#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. */
@@ -175,6 +173,8 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
#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
@@ -182,53 +182,16 @@ do { ASM_OUTPUT_ALIGN ((FILE), Pmode == SImode ? 2 : 3); \
define this macro in such cases. */
#undef ASM_OUTPUT_SECTION_NAME /* Override svr4.h's definition. */
-#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
do { \
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \
- fprintf (FILE, ".section\t\"%s\",#alloc,#execinstr\n", (NAME)); \
- else if ((DECL) && TREE_READONLY (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)
-
-/* 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); \
- fprintf((FILE), "\t.long\t0x%x\n", 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 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); \
- fprintf((FILE), "\t.long\t0x%x\n", value[0]); \
- fprintf((FILE), "\t.long\t0x%x\n", value[1]); \
- } while (0)
-
-/* This is how to output an assembler line defining a `long double'
- constant. */
-
-#undef ASM_OUTPUT_LONG_DOUBLE
-#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
-do { long value[4]; \
- REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), value); \
- fprintf((FILE), "\t.long\t0x%x\n", value[0]); \
- fprintf((FILE), "\t.long\t0x%x\n", value[1]); \
- fprintf((FILE), "\t.long\t0x%x\n", value[2]); \
- fprintf((FILE), "\t.long\t0x%x\n", value[3]); \
- } while (0)
/* Output assembler code to FILE to initialize this source file's
basic block profiling info, if that has not already been done. */
@@ -236,12 +199,8 @@ do { long value[4]; \
#undef FUNCTION_BLOCK_PROFILER
#define FUNCTION_BLOCK_PROFILER(FILE, LABELNO) \
do { \
- if (TARGET_MEDANY) \
- fprintf (FILE, "\tsethi %%hi(.LLPBX0),%%o0\n\tor %%0,%%lo(.LLPBX0),%%o0\n\tld [%s+%%o0],%%o1\n\ttst %%o1\n\tbne .LLPY%d\n\tadd %%o0,%s,%%o0\n\tcall __bb_init_func\n\tnop\nLPY%d:\n", \
- MEDANY_BASE_REG, (LABELNO), MEDANY_BASE_REG, (LABELNO)); \
- else \
- 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)); \
+ 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
@@ -251,12 +210,16 @@ do { long value[4]; \
#define BLOCK_PROFILER(FILE, BLOCKNO) \
{ \
int blockn = (BLOCKNO); \
- if (TARGET_MEDANY) \
- fprintf (FILE, "\tsethi %%hi(.LLPBX2+%d),%%g1\n\tor %%g1,%%lo(.LLPBX2+%d),%%g1\n\tld [%%g1+%s],%%g2\n\tadd %%g2,1,%%g2\n\tst %%g2,[%%g1+%s]\n", \
- 4 * blockn, 4 * blockn, MEDANY_BASE_REG, MEDANY_BASE_REG); \
- else \
- fprintf (FILE, "\tsethi %%hi(.LLPBX2+%d),%%g1\n\tld [%%lo(.LLPBX2+%d)+%%g1],%%g2\n\
+ 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); \
+ 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/gnu/usr.bin/gcc/config/sparc/t-sol2 b/gnu/usr.bin/gcc/config/sparc/t-sol2
index ccafc00384d..d41254adb44 100644
--- a/gnu/usr.bin/gcc/config/sparc/t-sol2
+++ b/gnu/usr.bin/gcc/config/sparc/t-sol2
@@ -3,19 +3,22 @@
LIBGCC1 =
CROSS_LIBGCC1 =
+LIBGCC1_TEST =
# gmon build rule:
-gmon.o: $(srcdir)/config/sparc/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H)
+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
- $(AS) -o crt1.o $(srcdir)/config/sparc/sol2-c1.asm
-crti.o: $(srcdir)/config/sparc/sol2-ci.asm
- $(AS) -o crti.o $(srcdir)/config/sparc/sol2-ci.asm
-crtn.o: $(srcdir)/config/sparc/sol2-cn.asm
- $(AS) -o crtn.o $(srcdir)/config/sparc/sol2-cn.asm
+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++
@@ -23,8 +26,5 @@ crtn.o: $(srcdir)/config/sparc/sol2-cn.asm
# we will be doing that, we just always use -fPIC when compiling the
# routines in crtstuff.c.
-# Since the GNU assembler doesn't support PIC yet, we need to force gcc to
-# use the native assembler when building crtstuff. If we're a
-# cross-compiler, just give up on using PIC.
-
-CRTSTUFF_T_CFLAGS = `if [ -z "$(CROSS)" ]; then echo -fPIC -B/usr/ccs/bin/; fi`
+CRTSTUFF_T_CFLAGS = -fPIC
+TARGET_LIBGCC2_CFLAGS = -fPIC
diff --git a/gnu/usr.bin/gcc/config/sparc/t-sp64 b/gnu/usr.bin/gcc/config/sparc/t-sp64
index e0de5edd98a..99acd5d5423 100644
--- a/gnu/usr.bin/gcc/config/sparc/t-sp64
+++ b/gnu/usr.bin/gcc/config/sparc/t-sp64
@@ -1,3 +1,2 @@
LIBGCC1 =
CROSS_LIBGCC1 =
-LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) -g1
diff --git a/gnu/usr.bin/gcc/config/sparc/t-sparcbare b/gnu/usr.bin/gcc/config/sparc/t-sparcbare
index a1bea24e9e4..8bd978b068d 100644
--- a/gnu/usr.bin/gcc/config/sparc/t-sparcbare
+++ b/gnu/usr.bin/gcc/config/sparc/t-sparcbare
@@ -1,4 +1,4 @@
-# configuration file for a bare sparc cpu, aout format files
+# configuration file for a bare sparc cpu
CROSS_LIBGCC1 = libgcc1-asm.a
LIB1ASMSRC = sparc/lb1spc.asm
@@ -18,9 +18,9 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
# MULTILIB_OPTIONS should have msparclite too, but we'd have to make
# gas build...
-MULTILIB_OPTIONS=msoft-float mv8
-MULTILIB_DIRNAMES=soft v8
-MULTILIB_MATCHES=msoft-float=mno-fpu
+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/gnu/usr.bin/gcc/config/sparc/t-sparclite b/gnu/usr.bin/gcc/config/sparc/t-sparclite
index 95e3a7e6c83..7cdfbb04551 100644
--- a/gnu/usr.bin/gcc/config/sparc/t-sparclite
+++ b/gnu/usr.bin/gcc/config/sparc/t-sparclite
@@ -16,9 +16,9 @@ fp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-MULTILIB_OPTIONS=mfpu/msoft-float mflat/mno-flat
-MULTILIB_DIRNAMES=
-MULTILIB_MATCHES= mfpu=mhard-float mno-fpu=msoft-float
+MULTILIB_OPTIONS = mfpu mflat
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES = mfpu=mhard-float mfpu=mcpu?f934
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/gnu/usr.bin/gcc/config/sparc/t-sunos40 b/gnu/usr.bin/gcc/config/sparc/t-sunos40
index 2fc63dbf06d..3e10575eaea 100644
--- a/gnu/usr.bin/gcc/config/sparc/t-sunos40
+++ b/gnu/usr.bin/gcc/config/sparc/t-sunos40
@@ -4,3 +4,4 @@
LIBGCC1 =
CROSS_LIBGCC1 =
+LIBGCC1_TEST =
diff --git a/gnu/usr.bin/gcc/config/sparc/t-sunos41 b/gnu/usr.bin/gcc/config/sparc/t-sunos41
index 77924e1b129..5783d6a2625 100644
--- a/gnu/usr.bin/gcc/config/sparc/t-sunos41
+++ b/gnu/usr.bin/gcc/config/sparc/t-sunos41
@@ -2,10 +2,15 @@
LIBGCC1 =
CROSS_LIBGCC1 =
+LIBGCC1_TEST =
-MULTILIB_OPTIONS=mv8
-MULTILIB_DIRNAMES=v8
-MULTILIB_MATCHES=
+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/gnu/usr.bin/gcc/config/sparc/t-vxsparc b/gnu/usr.bin/gcc/config/sparc/t-vxsparc
index 3adba438bd9..0c7a14a4429 100644
--- a/gnu/usr.bin/gcc/config/sparc/t-vxsparc
+++ b/gnu/usr.bin/gcc/config/sparc/t-vxsparc
@@ -7,7 +7,7 @@ LIBGCC1_TEST =
# We don't want to put exit in libgcc.a for VxWorks, because VxWorks
# does not have _exit.
-LIBGCC2_CFLAGS = -O2 $(GCC_CFLAGS) -g1 -Dexit=unused_exit
+TARGET_LIBGCC2_CFLAGS = -Dexit=unused_exit
MULTILIB_OPTIONS=msoft-float mv8
MULTILIB_DIRNAMES=soft v8
diff --git a/gnu/usr.bin/gcc/config/sparc/vxsparc.h b/gnu/usr.bin/gcc/config/sparc/vxsparc.h
index f9fab34a904..18ce6ed97b7 100644
--- a/gnu/usr.bin/gcc/config/sparc/vxsparc.h
+++ b/gnu/usr.bin/gcc/config/sparc/vxsparc.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Vxworks SPARC version.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1996 Free Software Foundation, Inc.
Contributed by David Henkel-Wallace (gumby@cygnus.com)
This file is part of GNU CC.
@@ -19,7 +19,7 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "sparc/sparc-aout.h"
+#include "sparc/aout.h"
/* Specify what to link with. */
/* VxWorks does all the library stuff itself. */
@@ -38,6 +38,13 @@ Boston, MA 02111-1307, USA. */
#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
diff --git a/gnu/usr.bin/gcc/config/sparc/xm-pbd.h b/gnu/usr.bin/gcc/config/sparc/xm-pbd.h
index dad9fdc6b34..1c3f47590c7 100644
--- a/gnu/usr.bin/gcc/config/sparc/xm-pbd.h
+++ b/gnu/usr.bin/gcc/config/sparc/xm-pbd.h
@@ -3,9 +3,6 @@
#include "sparc/xm-sparc.h"
#define USG
-#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)
#ifndef __GNUC__
#define USE_C_ALLOCA
diff --git a/gnu/usr.bin/gcc/config/sparc/xm-sol2.h b/gnu/usr.bin/gcc/config/sparc/xm-sol2.h
index 234ed999d05..a799f12b946 100644
--- a/gnu/usr.bin/gcc/config/sparc/xm-sol2.h
+++ b/gnu/usr.bin/gcc/config/sparc/xm-sol2.h
@@ -4,9 +4,3 @@
#ifndef __GNUC__
#include <alloca.h>
#endif
-
-/* We have _sys_siglist, but the declaration in <signal.h> 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/gnu/usr.bin/gcc/config/sparc/xm-sparc.h b/gnu/usr.bin/gcc/config/sparc/xm-sparc.h
index 07b20cc56b7..e553a0df0b2 100644
--- a/gnu/usr.bin/gcc/config/sparc/xm-sparc.h
+++ b/gnu/usr.bin/gcc/config/sparc/xm-sparc.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for Sun Sparc.
- Copyright (C) 1988, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1993, 1995, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
This file is part of GNU CC.
diff --git a/gnu/usr.bin/gcc/config/spur/spur.c b/gnu/usr.bin/gcc/config/spur/spur.c
index 5837cbbfe3a..4145af261de 100644
--- a/gnu/usr.bin/gcc/config/spur/spur.c
+++ b/gnu/usr.bin/gcc/config/spur/spur.c
@@ -1,6 +1,6 @@
/* Subroutines for insn-output.c for SPUR. Adapted from routines for
the Motorola 68000 family.
- Copyright (C) 1988, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
diff --git a/gnu/usr.bin/gcc/config/spur/spur.h b/gnu/usr.bin/gcc/config/spur/spur.h
index 54bcd1918c6..51e1add1b27 100644
--- a/gnu/usr.bin/gcc/config/spur/spur.h
+++ b/gnu/usr.bin/gcc/config/spur/spur.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for SPUR chip.
- Copyright (C) 1988, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -415,7 +415,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FP_REGS, ALL_REGS, LIM_REG_CLASSES };
when the function gets a structure-value-address as an
invisible first argument. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = ((FNTYPE) != 0 && aggregate_value_p (TREE_TYPE ((FNTYPE)))))
/* Update the data in CUM to advance over an argument
@@ -873,11 +873,9 @@ extern int current_function_pretend_args_size;
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs (".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. */
diff --git a/gnu/usr.bin/gcc/config/svr3.h b/gnu/usr.bin/gcc/config/svr3.h
index fc6e262b7b5..3475561799b 100644
--- a/gnu/usr.bin/gcc/config/svr3.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/t-libc-ok b/gnu/usr.bin/gcc/config/t-libc-ok
index 712a4ca128d..43e4f5e9e04 100644
--- a/gnu/usr.bin/gcc/config/t-libc-ok
+++ b/gnu/usr.bin/gcc/config/t-libc-ok
@@ -1,2 +1,3 @@
LIBGCC1=libgcc1.null
CROSS_LIBGCC1=libgcc1.null
+CRTSTUFF_T_FLAGS_S=-fPIC
diff --git a/gnu/usr.bin/gcc/config/tahoe/tahoe.c b/gnu/usr.bin/gcc/config/tahoe/tahoe.c
index 6fec44418f4..9dd189bde2f 100644
--- a/gnu/usr.bin/gcc/config/tahoe/tahoe.c
+++ b/gnu/usr.bin/gcc/config/tahoe/tahoe.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Tahoe.
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -51,7 +52,7 @@ Boston, MA 02111-1307, USA. */
rtx tahoe_reg_conversion_loc;
int
-extendable_operand (op, mode)
+extensible_operand (op, mode)
rtx op;
enum machine_mode mode;
{
@@ -67,8 +68,6 @@ extendable_operand (op, mode)
/* since the modes are basically the same. I had to add a special case, */
/* though, for symbol references with offsets. */
-#include <stdio.h>
-
print_operand_address (file, addr)
FILE *file;
register rtx addr;
diff --git a/gnu/usr.bin/gcc/config/tahoe/tahoe.h b/gnu/usr.bin/gcc/config/tahoe/tahoe.h
index 7eced776b3b..b4076ce53b3 100644
--- a/gnu/usr.bin/gcc/config/tahoe/tahoe.h
+++ b/gnu/usr.bin/gcc/config/tahoe/tahoe.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Tahoe version.
- Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -356,7 +356,7 @@ enum reg_class {NO_REGS,GENERAL_REGS,FPP_REG,ALL_REGS,LIM_REG_CLASSES};
/* we just set CUM to 0 before the FUNCTION_ARG call. No matter what */
/* we make it, FUNCTION_ARG will return 0 anyway */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = 0)
/* all modes push their size rounded to the nearest word boundary */
@@ -781,10 +781,9 @@ enum reg_class {NO_REGS,GENERAL_REGS,FPP_REG,ALL_REGS,LIM_REG_CLASSES};
#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
do { fputs (".globl ", FILE); assemble_name (FILE, NAME); fputs ("\n", FILE);} while (0)
-/* output a label by appending an underscore to it */
+/* The prefix to add to user-visible assembler symbols. */
-#define ASM_OUTPUT_LABELREF(FILE,NAME) \
- fprintf (FILE, "_%s", NAME)
+#define USER_LABEL_PREFIX "_"
/* use the standard format for printing internal labels */
diff --git a/gnu/usr.bin/gcc/config/tahoe/tahoe.md b/gnu/usr.bin/gcc/config/tahoe/tahoe.md
index eaa92d05d5e..0fdbb0cb775 100644
--- a/gnu/usr.bin/gcc/config/tahoe/tahoe.md
+++ b/gnu/usr.bin/gcc/config/tahoe/tahoe.md
@@ -1,5 +1,5 @@
;; Machine description for GNU compiler, Tahoe version
-;; Copyright (C) 1989, 1994 Free Software Foundation, Inc.
+;; Copyright (C) 1989, 1994, 1996, 1997 Free Software Foundation, Inc.
;; This file is part of GNU CC.
@@ -1143,7 +1143,7 @@
(define_insn "tsthi"
[(set (cc0)
- (match_operand:HI 0 "extendable_operand" "m,!r"))]
+ (match_operand:HI 0 "extensible_operand" "m,!r"))]
"GET_MODE (operands[0]) != VOIDmode"
"*
{
@@ -1179,7 +1179,7 @@
(define_insn "tstqi"
[(set (cc0)
- (match_operand:QI 0 "extendable_operand" "m,!r"))]
+ (match_operand:QI 0 "extensible_operand" "m,!r"))]
"GET_MODE (operands[0]) != VOIDmode"
"*
{
@@ -1946,7 +1946,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(subreg:QI (match_operand:SI 1 "general_operand" "g") 0))
(const_int 0))
@@ -1958,7 +1958,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(subreg:QI (match_operand:SI 1 "general_operand" "g") 0))
(const_int 0))
@@ -1970,7 +1970,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(subreg:QI (match_operand:SI 1 "general_operand" "g") 0))
(const_int 0))
@@ -1982,7 +1982,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(subreg:QI (match_operand:SI 1 "general_operand" "g") 0))
(const_int 0))
@@ -1996,7 +1996,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(match_operand:QI 1 "register_operand" "r"))
(const_int 0))
@@ -2008,7 +2008,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(match_operand:QI 1 "register_operand" "r"))
(const_int 0))
@@ -2020,7 +2020,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (ne (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(match_operand:QI 1 "register_operand" "r"))
(const_int 0))
@@ -2032,7 +2032,7 @@
(define_insn ""
[(set (pc)
(if_then_else
- (eq (sign_extract:SI (match_operand:SI 0 "nonimmediate_operand" "rm")
+ (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "rm")
(const_int 1)
(match_operand:QI 1 "register_operand" "r"))
(const_int 0))
diff --git a/gnu/usr.bin/gcc/config/vax/netbsd.h b/gnu/usr.bin/gcc/config/vax/netbsd.h
index 0875eeb4c56..1bbda32b4e4 100644
--- a/gnu/usr.bin/gcc/config/vax/netbsd.h
+++ b/gnu/usr.bin/gcc/config/vax/netbsd.h
@@ -1,9 +1,6 @@
-#include <vax/vax.h>
-#include <netbsd.h>
-
#undef CPP_PREDEFINES
#define CPP_PREDEFINES "-Dunix -Dvax -D__NetBSD__ -Asystem(unix) -Asystem(NetBSD) -Acpu(vax) -Amachine(vax)"
-
+
/* Make gcc agree with <machine/ansi.h> */
#undef SIZE_TYPE
diff --git a/gnu/usr.bin/gcc/config/vax/ultrix.h b/gnu/usr.bin/gcc/config/vax/ultrix.h
index e2891cee281..7181e5b0019 100644
--- a/gnu/usr.bin/gcc/config/vax/ultrix.h
+++ b/gnu/usr.bin/gcc/config/vax/ultrix.h
@@ -1,11 +1,6 @@
-#include "vax/vax.h"
-
#undef CPP_PREDEFINES
#define CPP_PREDEFINES " -Dvax -Dunix -Dultrix -Dbsd4_2 -D__vax -D__unix -D__ultrix -D__bsd4_2 -Asystem(unix) -Asystem(bsd) -Acpu(vax) -Amachine(vax)"
-/* By default, allow $ to be part of an identifier. */
-#define DOLLARS_IN_IDENTIFIERS 1
-
/* These are as defined in /usr/include/sys/stdtypes.h.
These values are for ultrix 4.2 on the vax. */
#define SIZE_TYPE "unsigned int"
diff --git a/gnu/usr.bin/gcc/config/vax/vax.c b/gnu/usr.bin/gcc/config/vax/vax.c
index e0500e2ba7a..ad10c08cbcf 100644
--- a/gnu/usr.bin/gcc/config/vax/vax.c
+++ b/gnu/usr.bin/gcc/config/vax/vax.c
@@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Vax.
- Copyright (C) 1987, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1994, 1995, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,8 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
@@ -808,9 +808,6 @@ not_qsort (array, count, size, compare)
}
else /* arbitrary size */
{
-#ifdef USE_C_ALLOCA
- extern void *alloca ();
-#endif
register int i;
register char *next, *prev, *tmp = alloca (size), *base = array;
diff --git a/gnu/usr.bin/gcc/config/vax/vaxv.h b/gnu/usr.bin/gcc/config/vax/vaxv.h
index aff74fd33da..57dff406b91 100644
--- a/gnu/usr.bin/gcc/config/vax/vaxv.h
+++ b/gnu/usr.bin/gcc/config/vax/vaxv.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Vax sysV version.
- Copyright (C) 1988, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1993, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,8 +18,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 "vax/vax.h"
-
/* Cope with these under SysV */
#define SCCS_DIRECTIVE
diff --git a/gnu/usr.bin/gcc/config/vax/vms.h b/gnu/usr.bin/gcc/config/vax/vms.h
index 99b5efe3575..f6f4161ab8d 100644
--- a/gnu/usr.bin/gcc/config/vax/vms.h
+++ b/gnu/usr.bin/gcc/config/vax/vms.h
@@ -1,5 +1,5 @@
/* Output variables, constants and external declarations, for GNU compiler.
- Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -31,11 +31,10 @@ Boston, MA 02111-1307, USA. */
#undef LIB_SPEC
#undef CPP_PREDEFINES
-#undef TARGET_VERSION
+#undef TARGET_NAME
#undef TARGET_DEFAULT
#undef CALL_USED_REGISTERS
#undef MAYBE_VMS_FUNCTION_PROLOGUE
-#undef FUNCTION_PROLOGUE
#undef STARTING_FRAME_OFFSET
/* Predefine this in CPP because VMS limits the size of command options
@@ -46,9 +45,10 @@ Boston, MA 02111-1307, USA. */
/* These match the definitions used in VAXCRTL, the VMS C run-time library */
-#define SIZE_TYPE "unsigned int"
-#define PTRDIFF_TYPE "int"
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
#define WCHAR_TYPE "unsigned int"
+#define WCHAR_TYPE_SIZE 32 /* in bits */
/* Use memcpy for structure copying, and so forth. */
#define TARGET_MEM_FUNCTIONS
@@ -58,11 +58,8 @@ Boston, MA 02111-1307, USA. */
#define DEFAULT_GDB_EXTENSIONS 0
-/* By default, allow $ to be part of an identifier. */
-#define DOLLARS_IN_IDENTIFIERS 2
-
#define TARGET_DEFAULT 1
-#define TARGET_VERSION fprintf (stderr, " (vax vms)");
+#define TARGET_NAME "vax/vms"
/* The structure return address arrives as an "argument" on VMS. */
#undef STRUCT_VALUE_REGNUM
@@ -71,26 +68,15 @@ Boston, MA 02111-1307, USA. */
#define CALL_USED_REGISTERS {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}
-/* We redefine this because there is a hidden variable on the stack
- that VAXC$ESTABLISH uses. We just need to add four bytes to whatever
- gcc thinks that we need. Similarly, we need to move all local variables
- down 4 bytes in the stack. */
+/* The run-time library routine VAXC$ESTABLISH (necessary when mixing
+ VMS exception handling and setjmp/longjmp in the same program) requires
+ that a hidden automatic variable at the top of the stack be reserved
+ for its use. We accomplish this by simply adding 4 bytes to the local
+ stack for all functions, and making sure that normal local variables
+ are 4 bytes lower on the stack then they would otherwise have been. */
#define STARTING_FRAME_OFFSET -4
-#define FUNCTION_PROLOGUE(FILE, SIZE) \
-{ register int regno; \
- register int mask = 0; \
- register int newsize = SIZE + 4; \
- extern char call_used_regs[]; \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- if (regs_ever_live[regno] && !call_used_regs[regno]) \
- mask |= 1 << regno; \
- fprintf (FILE, "\t.word 0x%x\n", mask); \
- MAYBE_VMS_FUNCTION_PROLOGUE(FILE) \
- if (newsize >= 64) fprintf (FILE, "\tmovab %d(sp),sp\n", -newsize);\
- else fprintf (FILE, "\tsubl2 $%d,sp\n", newsize); }
-
#define __MAIN_NAME " main("
/*
* The MAYBE_VMS_FUNCTION_PROLOGUE macro works for both gcc and g++. It
@@ -184,11 +170,7 @@ Boston, MA 02111-1307, USA. */
is explicitly defined, then ASM_FINISH_DECLARE_OBJECT will be used. */
#define ASM_DECLARE_OBJECT_NAME(ASM_OUT_FILE,NAME,DECL) \
-{ if (output_bytecode) \
- BC_OUTPUT_LABEL ((ASM_OUT_FILE), (NAME)); \
- else \
- ASM_OUTPUT_LABEL ((ASM_OUT_FILE), (NAME)); \
-}
+ ASM_OUTPUT_LABEL ((ASM_OUT_FILE), (NAME))
/* We don't need to do anything special to finish the current object, but it
should now be safe to output any deferred external global declarations. */
@@ -375,3 +357,13 @@ do { \
} while (0)
#endif /* L__main */
+
+/* Specify the list of include file directories. */
+#define INCLUDE_DEFAULTS \
+{ \
+ { "GNU_GXX_INCLUDE:", "G++", 1, 1 }, \
+ { "GNU_CC_INCLUDE:", "GCC", 0, 0 }, /* GNU includes */ \
+ { "SYS$SYSROOT:[SYSLIB.]", 0, 0, 0 }, /* VAX-11 "C" includes */ \
+ { ".", 0, 0, 1 }, /* Make normal VMS filespecs work. */ \
+ { 0, 0, 0, 0 } \
+}
diff --git a/gnu/usr.bin/gcc/config/vax/xm-vaxv.h b/gnu/usr.bin/gcc/config/vax/xm-vaxv.h
index 35d7d8535be..aef16f04321 100644
--- a/gnu/usr.bin/gcc/config/vax/xm-vaxv.h
+++ b/gnu/usr.bin/gcc/config/vax/xm-vaxv.h
@@ -1,9 +1,3 @@
/* Config file for Vax running system V. */
-#include "vax/xm-vax.h"
-
#define USG
-
-#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/gnu/usr.bin/gcc/config/vax/xm-vms.h b/gnu/usr.bin/gcc/config/vax/xm-vms.h
index 80fa107e139..a559a039476 100644
--- a/gnu/usr.bin/gcc/config/vax/xm-vms.h
+++ b/gnu/usr.bin/gcc/config/vax/xm-vms.h
@@ -1,5 +1,5 @@
/* Configuration for GNU C-compiler for Vax.
- Copyright (C) 1987, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -22,7 +22,15 @@ Boston, MA 02111-1307, USA. */
#define FALSE 0
#define TRUE 1
-#ifdef VAXC
+/* Other configurations get these via autoconfig. */
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#ifdef __DECC
+#define HAVE_UNISTD_H 1
+#endif
+
+#if defined(VAXC) || defined(__DECC)
/* if compiling with VAXC, need to fix problem with <stdio.h>
which defines a macro called FILE_TYPE that breaks "tree.h".
Fortunately it uses #ifndef to suppress multiple inclusions.
@@ -69,15 +77,12 @@ Boston, MA 02111-1307, USA. */
/* and define a local equivalent (sort of) for unlink */
#define unlink remove
-/* Specify the list of include file directories. */
-#define INCLUDE_DEFAULTS \
-{ \
- { "GNU_GXX_INCLUDE:", 1, 1 }, \
- { "GNU_CC_INCLUDE:", 0, 0 }, /* GNU includes */ \
- { "SYS$SYSROOT:[SYSLIB.]", 0, 0 }, /* VAX-11 "C" includes */ \
- { ".", 0, 1 }, /* Make normal VMS filespecs work. */ \
- { 0, 0, 0 } \
-}
+/* Used by the preprocessor to limit size of disk I/O chunks.
+ 64K - 1 is the maximum supported by VAXCRTL. Amounts in excess
+ of 35 blocks will bypass the VMS V6.x VIOC [Virtual I/O Cache],
+ so we'll pick a limit of 16K (32 blocks). */
+#define MAX_READ_LEN (32 * 512)
+#define MAX_WRITE_LEN (32 * 512)
/* Under VMS a directory specification can be enclosed either in square
brackets or in angle brackets. Thus we need to check both. This
@@ -128,7 +133,7 @@ Boston, MA 02111-1307, USA. */
#define HAVE_VPRINTF
-#ifdef VAXC
+#if defined(VAXC) || defined(__DECC)
/* Customizations/kludges for building with DEC's VAX C compiler
rather than GCC. */
#define NO_SYS_PARAMS_H /* don't have <sys/params.h> */
@@ -137,12 +142,6 @@ Boston, MA 02111-1307, USA. */
#define QSORT_WORKAROUND /* do not use VAXCRTL's qsort */
/* use ANSI/SYSV style byte manipulation routines instead of BSD ones */
-#define bcopy(s,d,n) memcpy((d),(s),(n))
-#define bzero(d,n) memset((d),0,(n))
-#define bcmp(l,r,n) memcmp((l),(r),(n))
-#define index strchr
-#define rindex strrchr
-
/* rename all too-long external symbol names to avoid warnings */
#define bc_check_for_full_enumeration_handling bc_check_for_full_enum_handling
#define check_for_full_enumeration_handling check_for_full_enum_handling
@@ -157,11 +156,17 @@ Boston, MA 02111-1307, USA. */
#define current_function_returns_pointer curfunc_returns_pointer
#define current_function_uses_const_pool curfunc_uses_const_pool
#define current_function_uses_pic_offset_table curfunc_uses_pic_offset_table
+#define dbxout_resume_previous_source_file dbxout_resume_previous_src_file
+#define expand_builtin_extract_return_addr expand_builtin_extract_ret_addr
+#define expand_builtin_set_return_addr_reg expand_builtin_set_ret_addr_reg
#define expand_start_loop_continue_elsewhere expnd_start_loop_cont_elsewhere
#define flag_schedule_insns_after_reload flag_sched_insns_after_reload
+#define get_dynamic_handler_chain_libfunc get_dynamic_hndlr_chain_libfunc
#define lookup_name_current_level_global lookup_name_current_level_gbl
#define maybe_building_objc_message_expr maybe_building_objc_msg_expr
+#define mesg_implicit_function_declaration mesg_implicit_func_declaration
#define output_deferred_addressed_constants output_deferred_addr_constants
+#define protect_cleanup_actions_with_terminate protect_cleanup_act_w_terminate
#define reg_overlap_mentioned_for_reload_p reg_overlap_mtnd_for_reload_p
#define reposition_prologue_and_epilogue_notes repos_prolog_and_epilog_notes
#define rtx_equal_function_value_matters rtx_equal_func_value_matters
@@ -178,3 +183,24 @@ Boston, MA 02111-1307, USA. */
#ifdef QSORT_WORKAROUND
#define qsort not_qsort
#endif
+
+#ifdef __DECC
+/* DECC$SHR doesn't have VAXCRTL's bugs. */
+#undef QSORT_WORKAROUND
+#undef qsort
+/* Avoid a lot of informational level diagnostics about implicitly
+ declared functions. */
+#include <stdlib.h>
+#include <string.h>
+/* this is for genopinit.c */
+ #pragma message disable (undefescap)
+#endif
+
+#if defined(USE_C_ALLOCA) && !defined(alloca)
+/* Declare alloca() using similar logic to that in alloca.c. */
+#ifdef __STDC__
+extern void *alloca(unsigned);
+#else
+extern char *alloca();
+#endif
+#endif
diff --git a/gnu/usr.bin/gcc/config/we32k/we32k.c b/gnu/usr.bin/gcc/config/we32k/we32k.c
index 3dceb07e8c9..091f3c6680b 100644
--- a/gnu/usr.bin/gcc/config/we32k/we32k.c
+++ b/gnu/usr.bin/gcc/config/we32k/we32k.c
@@ -1,6 +1,6 @@
/* Subroutines for insn-output.c for AT&T we32000 Family.
Contributed by John Wehle (john@feith1.uucp)
- Copyright (C) 1991-1992 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1992, 1997 Free Software Foundation, Inc.
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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "real.h"
diff --git a/gnu/usr.bin/gcc/config/we32k/we32k.h b/gnu/usr.bin/gcc/config/we32k/we32k.h
index 90d4d5c1d16..460fc3d2820 100644
--- a/gnu/usr.bin/gcc/config/we32k/we32k.h
+++ b/gnu/usr.bin/gcc/config/we32k/we32k.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. AT&T we32000 version.
- Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
Contributed by John Wehle (john@feith1.uucp)
This file is part of GNU CC.
@@ -360,7 +360,7 @@ enum reg_class { NO_REGS, GENERAL_REGS,
On the we32k, the offset starts at 0. */
-#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
((CUM) = 0)
/* Update the data in CUM to advance over an argument
@@ -770,11 +770,9 @@ enum reg_class { NO_REGS, GENERAL_REGS,
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. */
diff --git a/gnu/usr.bin/gcc/config/we32k/xm-we32k.h b/gnu/usr.bin/gcc/config/we32k/xm-we32k.h
index 01175ef2505..70aa35b6bb1 100644
--- a/gnu/usr.bin/gcc/config/we32k/xm-we32k.h
+++ b/gnu/usr.bin/gcc/config/we32k/xm-we32k.h
@@ -1,12 +1,12 @@
/* Configuration for GNU C-compiler for AT&T we32000 Family.
+ Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
Contributed by John Wehle (john@feith1.uucp)
- Copyright (C) 1991, 1992, 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 1, or (at your option)
+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,
@@ -44,11 +44,6 @@ Boston, MA 02111-1307, USA. */
/* Don't try to use sys_siglist. */
#define NO_SYS_SIGLIST
-/* Don't try including wait.h. */
-#define NO_WAIT_H
-
#ifndef MAXPATHLEN
#define MAXPATHLEN 512
#endif
-
-#include "xm-svr3.h"
diff --git a/gnu/usr.bin/gcc/config/winnt/config-nt.bat b/gnu/usr.bin/gcc/config/winnt/config-nt.bat
index 59a00863931..688d1264e89 100644
--- a/gnu/usr.bin/gcc/config/winnt/config-nt.bat
+++ b/gnu/usr.bin/gcc/config/winnt/config-nt.bat
@@ -1,10 +1,17 @@
echo Configuring GCC for Windows NT on %2
rem This batch file assumes a unix-type "sed" program
-echo #include "%2/xm-winnt.h" >config.h
-echo #include "%2/xm-winnt.h" >hconfig.h
-echo #include "%2/xm-winnt.h" >tconfig.h
-echo #include "%2/win-nt.h" >tm.h
+if %2.==alpha. echo #include "alpha/xm-alpha.h" >config.h
+if %2.==alpha. echo #include "winnt/xm-winnt.h" >>config.h
+if %2.==alpha. echo #include "alpha/xm-winnt.h" >>config.h
+if not %2.==alpha. echo #include "%2/xm-winnt.h" >config.h
+copy config.h hconfig.h
+copy config.h tconfig.h
+
+if %2.==alpha. echo #define TARGET_CPU_DEFAULT 64 >tm.h
+if %2.==alpha. echo #include "alpha/alpha.h" >>tm.h
+if %2.==alpha. echo #include "alpha/win-nt.h" >>tm.h
+if not %2.==alpha. echo #include "%2/win-nt.h" >tm.h
rem This batch file assumes a unix-type "sed" program
diff --git a/gnu/usr.bin/gcc/config/winnt/win-nt.h b/gnu/usr.bin/gcc/config/winnt/win-nt.h
index 4b93f8c118d..14f3f87bcdb 100644
--- a/gnu/usr.bin/gcc/config/winnt/win-nt.h
+++ b/gnu/usr.bin/gcc/config/winnt/win-nt.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for
Windows NT 3.x.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by Douglas B. Rupp (drupp@cs.washington.edu).
This file is part of GNU CC.
@@ -29,7 +29,7 @@ Boston, MA 02111-1307, USA. */
#define LINK_SPEC "-stack 5000000,5000000 -noinhibit-exec %{g}"
#undef CPP_SPEC
-#define CPP_SPEC "-lang-c-c++-comments"
+#define CPP_SPEC ""
#undef STANDARD_EXEC_PREFIX
#define STANDARD_EXEC_PREFIX ""
@@ -51,7 +51,7 @@ Boston, MA 02111-1307, USA. */
#undef INCLUDE_DEFAULTS
#define INCLUDE_DEFAULTS \
{ \
- { 0, 0, 0 } \
+ { 0, 0, 0, 0 } \
}
#undef STDC_VALUE
diff --git a/gnu/usr.bin/gcc/config/winnt/xm-winnt.h b/gnu/usr.bin/gcc/config/winnt/xm-winnt.h
index be62d020138..f56073cb8de 100644
--- a/gnu/usr.bin/gcc/config/winnt/xm-winnt.h
+++ b/gnu/usr.bin/gcc/config/winnt/xm-winnt.h
@@ -1,5 +1,5 @@
/* Configuration for GNU compiler for processor running Windows NT 3.x.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc.
Contributed by Douglas B. Rupp (drupp@cs.washington.edu)
This file is part of GNU CC.
@@ -42,11 +42,6 @@ Boston, MA 02111-1307, USA. */
#endif
#define NO_SYS_SIGLIST 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 kill(a,b) raise(b)
#define OBJECT_SUFFIX ".obj"
@@ -66,4 +61,3 @@ Boston, MA 02111-1307, USA. */
#define S_IRWXU S_IRUSR | S_IWUSR | S_IXUSR
#define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
-
diff --git a/gnu/usr.bin/gcc/config/xm-gnu.h b/gnu/usr.bin/gcc/config/xm-gnu.h
index 57e74f23018..64e8e2fa817 100644
--- a/gnu/usr.bin/gcc/config/xm-gnu.h
+++ b/gnu/usr.bin/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 <fcntl.h>
+#endif
diff --git a/gnu/usr.bin/gcc/config/xm-linux.h b/gnu/usr.bin/gcc/config/xm-linux.h
index 5ffb0f2a56d..9a3838b7d7f 100644
--- a/gnu/usr.bin/gcc/config/xm-linux.h
+++ b/gnu/usr.bin/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 BSTRING
#define BSTRING
-#undef bcmp
-#undef bcopy
-#undef bzero
-#undef index
-#undef rindex
diff --git a/gnu/usr.bin/gcc/config/xm-svr3.h b/gnu/usr.bin/gcc/config/xm-svr3.h
index ac1000fb1cb..6f252505252 100644
--- a/gnu/usr.bin/gcc/config/xm-svr3.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/xm-svr4.h b/gnu/usr.bin/gcc/config/xm-svr4.h
index 30084322510..8534aaa75a1 100644
--- a/gnu/usr.bin/gcc/config/xm-svr4.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/convert.c b/gnu/usr.bin/gcc/convert.c
index 17e755243af..744490f9256 100644
--- a/gnu/usr.bin/gcc/convert.c
+++ b/gnu/usr.bin/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, 92, 94, 95, 1997 Free Software Foundation, Inc.
This file is part of GNU C.
@@ -20,7 +20,7 @@ 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"
@@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */
/* 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)
@@ -74,7 +74,7 @@ convert_to_pointer (type, expr)
/* 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)
@@ -397,7 +397,10 @@ convert_to_integer (type, expr)
convert (type, TREE_OPERAND (expr, 2))));
}
}
+ break;
+ default:
+ break;
}
return build1 (NOP_EXPR, type, expr);
diff --git a/gnu/usr.bin/gcc/cp/ChangeLog b/gnu/usr.bin/gcc/cp/ChangeLog
index d2ef74f206f..e20b8af122b 100644
--- a/gnu/usr.bin/gcc/cp/ChangeLog
+++ b/gnu/usr.bin/gcc/cp/ChangeLog
@@ -1,9459 +1,6572 @@
-Mon Nov 20 14:06:28 1995 Mike Stump <mrs@cygnus.com>
+Mon Dec 22 17:46:17 1997 Mark Mitchell <mmitchell@usa.net>
- * Version 2.7.2 released.
+ * method.c (build_overload_name): Fix mangling for __null.
-Mon Nov 20 14:05:00 1995 Mike Stump <mrs@cygnus.com>
+Sat Dec 13 09:23:54 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
- * g++.c (pfatal_with_name): Add missing third argument to concat.
+ * Make-lang.in (g++.c, cxxmain.o): Use $(LN).
-Thu Oct 26 13:59:54 1995 Mike Stump <mrs@cygnus.com>
+Wed Dec 3 08:47:27 1997 Paul Eggert <eggert@twinsun.com>
- * init.c (expand_aggr_init): Handle cv qualifiers on the object's
- type.
-
-Sun Nov 12 18:09:35 1995 Mike Stump <mrs@cygnus.com>
-
- * Version 2.7.1 released.
-
-Thu Nov 2 17:02:47 1995 Jason Merrill <jason@yorick.cygnus.com>
-
- * call.c (convert_harshness): Handle references to arrays.
+ * pt.c (check_explicit_specialization): Fix misspelling in
+ diagnostic: `preceeded'.
+ * typeck.c (get_delta_difference): Fix misspelling in diagnostic:
+ `conversiona'.
-Fri Oct 27 14:20:21 1995 Jason Merrill <jason@yorick.cygnus.com>
+Sun Nov 30 08:42:29 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * typeck.c (comp_target_types): Check multi-level pointer
- conversions in both directions.
+ * pt.c (do_poplevel): Allow jumps into the block.
-Tue Oct 17 21:39:05 1995 Jason Merrill <jason@yorick.cygnus.com>
+Fri Nov 28 12:35:19 1997 Scott Christley <scottc@net-community.com>
- * parse.y (explicit_instantiation): Fix 'extern template' with no
- return type.
+ * repo.c: Prototype rindex only if needed.
+ * xref.c: Likewise.
-Mon Oct 16 14:35:20 1995 Jason Merrill <jason@yorick.cygnus.com>
+Thu Nov 27 08:26:56 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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 <mrs@cygnus.com>
-
- * 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.
+ * 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.
-Tue Oct 10 15:46:01 1995 Mike Stump <mrs@cygnus.com>
+Wed Nov 26 15:13:48 1997 Jeffrey A Law (law@cygnus.com)
- * typeck.c (mark_addressable): Only call assemble_external if we
- have started the output file.
+ * lex.c (lang_init): Enable flag_exceptions by default if no
+ command line switch was specified.
-Tue Oct 10 11:27:18 1995 Jason Merrill <jason@yorick.cygnus.com>
+Mon Nov 24 12:15:55 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_function): Fix earlier cv-quals change.
+ * 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.
-Mon Oct 9 23:53:05 1995 Mike Stump <mrs@cygnus.com>
-
- * parse.y (complex_direct_notype_declarator): Only push the class if
- we are not already in the class.
+Mon Nov 17 02:01:28 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Oct 9 11:22:03 1995 Doug Evans <dje@canuck.cygnus.com>
+ * friend.c (do_friend): Warn about non-template friends in templates.
- * 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.
+ * search.c (dfs_record_inheritance): Ignore template type parms.
-Fri Oct 6 14:44:27 1995 Mike Stump <mrs@cygnus.com>
+Wed Nov 12 08:11:55 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * typeck.c (mark_addressable): Add missing call to
- assemble_external.
-
-Wed Oct 4 22:05:23 1995 Jeff Law (law@hurl.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.
-
-Wed Oct 4 15:06:39 1995 Mike Stump <mrs@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.
-
-Wed Oct 4 12:47:02 1995 Jason Merrill <jason@yorick.cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
+ * call.c (build_method_call): Call complete_type before checking
+ for destructor.
- * tree.c (unsave_expr_now): Make sure we process the argument list
- of any called functions. Fixes incorrect code generation for
- cleanups.
+Tue Nov 11 12:02:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Oct 2 13:04:16 1995 Mike Stump <mrs@cygnus.com>
+ * except.c (expand_end_catch_block): Lose call to __sjpopnthrow.
- * typeck.c (get_member_function_from_ptrfunc): Save function if it
- needs it. Cures core dump on things like (this->*(f()))().
+Tue Nov 11 02:53:44 1997 Jason Merrill <jason@lasher.cygnus.com>
-Sat Sep 23 22:51:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * except.c (do_pop_exception): Return a value.
- * 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.
+Mon Nov 10 03:04:20 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Sep 22 10:21:13 1995 Mike Stump <mrs@cygnus.com>
+ 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.
- * decl.c (pushtag): Add in the namespace name for the tag.
+Sun Nov 9 18:00:26 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-Thu Sep 21 13:11:13 1995 Mike Stump <mrs@cygnus.com>
+ * Make-lang.in (c++.distdir): Make inc subdirectory.
- * 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.
+Fri Nov 7 11:57:28 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Sep 20 12:35:27 1995 Michael Meissner <meissner@cygnus.com>
+ * decl2.c (finish_file): Put back some code.
- * decl.c (init_decl_processing): Add __builtin_expect.
+Thu Nov 6 11:28:14 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Sep 19 16:48:11 1995 Mike Stump <mrs@cygnus.com>
+ * decl2.c (finish_file): Remove redundant code.
+ * method.c (emit_thunk): Don't let the backend defer generic thunks.
- * 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.
+Wed Nov 5 23:52:50 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Sep 15 17:14:47 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+ * 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.
- * init.c (resolve_offset_ref): Fix wording of non-static member
- being referenced as a static.
+Tue Nov 4 13:45:10 1997 Doug Evans <devans@canuck.cygnus.com>
-Fri Sep 15 12:39:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (MULTIBYTE_CHARS): #undef if cross compiling.
+ (real_yylex): Record wide strings using target endianness, not host.
- * typeck.c (build_indirect_ref): Only bash pointer if we actually
- call build_expr_type_conversion.
+1997-11-03 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Sep 14 18:24:56 1995 Jason Merrill <jason@deneb.cygnus.com>
+ * 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.
- * cvt.c (build_expr_type_conversion): Handle conversion from
- reference.
- * typeck.c (build_indirect_ref): Avoid infinite recursion.
+Sun Nov 2 15:04:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Sep 14 17:23:28 1995 Mike Stump <mrs@cygnus.com>
+ * class.c (build_vbase_path): Propagate the result type properly.
- * 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.
+1997-11-01 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Sep 13 18:32:24 1995 Mike Stump <mrs@cygnus.com>
+ * except.c (expand_builtin_throw) [!DWARF2_UNWIND_INFO]: Replace
+ remaining use of saved_throw_type with a call to get_eh_type.
- * 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.
+1997-10-31 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Sep 13 16:52:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- * typeck.c (comptypes): Tighten up comparisons of template type
- parms.
+ * 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.
- * decl.c (duplicate_decls): Turn off whining about virtual functions
- redeclared inline for now.
+ * except.c (push_eh_info): Pass the number of fields - 1 down, not
+ the exact number of fields.
-Wed Sep 13 11:13:40 1995 Mike Stump <mrs@cygnus.com>
+Fri Oct 31 01:47:57 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ 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.
-Tue Sep 12 17:43:07 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+Sun Oct 26 01:28:29 1997 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
- * call.c (convert_harshness): Use comptypes, not ==, to check if
- TYPE and PARMTYPE are equivalent on a function type.
+ * typeck.c (rationalize_conditional_expr): Handle {MIN,MAX}_EXPR.
+ (unary_complex_lvalue): Call it for {MIN,MAX}_EXPR.
-Tue Sep 12 17:31:33 1995 Douglas Rupp (drupp@cs.washington.edu)
+ * decl.c (init_decl_processing): Call using_eh_for_cleanups.
- * Make-lang.in (cc1plus) : Removed unnecessary $(exeext).
+Sun Oct 26 01:52:52 1997 Jeffrey A Law (law@cygnus.com)
-Mon Sep 11 23:24:07 1995 Mike Stump <mrs@cygnus.com>
+ * Makefile.in (g++): Depend on prefix.o. Link in prefix.o.
- * except.c (expand_throw): Never allocate storage for thrown pointer
- to objects.
+Thu Oct 23 02:01:30 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Sep 11 19:36:45 1995 Mike Stump <mrs@cygnus.com>
+ * pt.c (instantiate_decl): SET_DECL_IMPLICIT_INSTANTIATION on new decl.
- * except.c (expand_start_catch_block): Pointers to objects come
- back from catch matching already dereferenced, don't dereference
- again.
+1997-10-22 Brendan Kehoe <brendan@cygnus.com>
-Mon Sep 11 15:46:28 1995 Mike Stump <mrs@cygnus.com>
+ * 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.
- * 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.
+Mon Oct 20 12:06:34 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Sep 11 13:46:45 1995 Mike Stump <mrs@cygnus.com>
+ * except.c (expand_exception_blocks): Call do_pending_stack_adust.
+ (expand_end_catch_block): Likewise.
+ (expand_end_eh_spec): Likewise.
- * error.c (dump_aggr_type): Deal with anonymous unions that don't
- have a TYPE_NAME.
-
-Fri Sep 8 20:40:27 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * lex.c (handle_sysv_pragma): Deal with getting a comma from yylex.
-
-Fri Sep 8 15:51:41 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c (expand_end_eh_spec): Handle empty EH specifications.
-
-Fri Sep 8 15:27:22 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Fri Sep 8 14:40:48 1995 Per Bothner <bothner@kalessin.cygnus.com>
-
- * lex.c (do_identifier): Use global binding in preference of
- dead for local variable.
-
-Wed Sep 6 19:32:59 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Tue Sep 5 15:56:27 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c (expand_throw): Run cleanups for the throw expression.
-
-Wed Aug 30 15:24:38 1995 Stephen L. Favor (sfavor@tigger.intecom.com)
-
- * 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 <mrs@cygnus.com>
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * except.c (expand_internal_throw): Oops, almost forgot type and
- value are now trees.
-
-Mon Aug 28 17:57:45 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- 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 <mrs@cygnus.com>
-
- * except.c: Always allow turning on exception handling. Allow cross
- compilations to use EH.
-
-Thu Aug 24 17:39:24 1995 Mike Stump <mrs@cygnus.com>
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * cvt.c (build_expr_type_conversion): Handle conversions to
- reference types.
-
-Wed Aug 23 15:33:59 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c (do_unwind): Work around backend bug with -fpic.
-
-Tue Aug 22 17:20:07 1995 Per Bothner <bothner@kalessin.cygnus.com>
-
- * 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 <jason@deneb.cygnus.com>
-
- * decl2.c (import_export_inline): Class interface hackery does not
- apply to synthesized methods.
+Mon Oct 20 11:44:20 1997 Mark Mitchell <mmitchell@usa.net>
-Sun Aug 20 16:29:00 1995 Mike Stump <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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.
+ * 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.
-Sat Aug 19 14:25:33 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- 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 <mrs@cygnus.com>
-
- * 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 <jason@deneb.cygnus.com>
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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 <brendan@lisa.cygnus.com>
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * tree.c (cp_expand_decl_cleanup): Returns int, not tree.
- * cp-tree.h: Update.
-
- * parse.y (template_type_parm): Add support for `typename'.
-
-Tue Aug 8 12:06:31 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Fri Aug 4 17:17:08 1995 Mike Stump <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * except.c (output_exception_table_entry): Enhance portability to
- weird machines.
- (emit_exception_table): Ditto.
-
-Thu Aug 3 16:41:38 1995 Mike Stump <mrs@cygnus.com>
-
- * typeck.c (build_ptrmemfunc): Handle casting of pointer to
- non-virtual member functions.
-
-Wed Aug 2 11:58:25 1995 Mike Stump <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * 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.
-
-Mon Jul 31 13:24:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * method.c (report_type_mismatch): Don't talk about an object
- parameter for non-methods.
-
-Sun Jul 30 13:13:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * 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.
-
- * method.c (report_type_mismatch): Deal with a bad_arg of 0.
-
- * init.c (expand_aggr_init): Handle volatile objects, too.
-
-Sat Jul 29 13:42:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Fri Jul 28 15:26:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (comp_target_types): Don't check const and volatile for
- function types.
- (comp_ptr_ttypes_real): Ditto.
-
-Thu Jul 27 15:40:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (comp_target_types): Fix.
-
-Thu Jul 27 15:10:48 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Thu Jul 27 10:38:43 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * parse.y (typespec): Only complain about typeof if we're not
- getting it from a system header.
-
-Thu Jul 27 10:26:23 1995 Doug Evans <dje@canuck.cygnus.com>
-
- 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.
-
-Mon Jul 24 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * typeck.c (comp_target_types): Avoid assigning D const * to B *.
-
-Mon Jul 24 08:54:46 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * pt.c (to_be_restored): Move decl to global scope.
-
-Sat Jul 22 12:22:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (start_decl): Put back clearing of DECL_IN_AGGR_P.
-
-Fri Jul 21 17:09:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (grokdeclarator): Downgrade error about 'extern int A::i'
- to pedwarn.
-
- * pt.c (instantiate_template): Also avoid instantiation if the
- function has already been declared to be a specialization.
-
- * decl2.c (check_classfn): Ignore cname argument, and return the
- matching function.
+Mon Oct 20 10:52:22 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Handle declarations of member functions
- outside of the class (i.e. specialization declarations).
+ * 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.
-Thu Jul 20 10:34:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Oct 16 15:31:09 1997 Judy Goldberg <judygold@sanwafp.com>
- * class.c (finish_struct): Don't mess with the type of bitfields.
+ * pt.c (determine_explicit_specialization): Initialize "dummy"
+ to keep Purify quiet.
- * various.c: s/TYPE_POINTER_TO/build_pointer_type/.
+Thu Oct 16 00:14:48 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jul 20 01:43:10 1995 Mike Stump <mrs@cygnus.com>
+ * method.c (build_overload_value): Handle TEMPLATE_CONST_PARMs here.
+ (build_overload_int): Not here.
- * 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.
+Wed Oct 15 00:35:28 1997 Mike Stump <mrs@wrs.com>
-Wed Jul 19 20:32:01 1995 Mike Stump <mrs@cygnus.com>
+ * class.c (build_type_pathname): Remove.
+ (prepare_fresh_vtable): Fix problem with complex MI vtable names.
- * init.c (expand_default_init): Don't allow two-level conversions
- during construction.
+1997-10-14 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Jul 19 18:06:37 1995 Mike Stump <mrs@cygnus.com>
+ * parse.y (unary_expr): Give a pedwarn if someone tries to use the
+ &&label GNU extension.
- * gc.c (build_headof): The type of dyncasting to a pointer to cv
- void, should be pointer to cv void.
+Tue Oct 14 12:01:00 1997 Mark Mitchell <mmitchell@usa.net>
-Wed Jul 19 17:25:43 1995 Mike Stump <mrs@cygnus.com>
-
- * gc.c (build_dynamic_cast): Allow casting in const.
-
-Wed Jul 19 16:34:27 1995 Mike Stump <mrs@cygnus.com>
-
- * typeck.c (build_const_cast): If we are passed error_mark_node,
- return it.
-
-Wed Jul 19 15:24:48 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * 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 <gb@alexander.cs.purdue.edu>
-
- * 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 <mrs@cygnus.com>
-
- * cvt.c (cp_convert): Always call build_cplus_new for a ctor.
-
-Tue Jul 18 14:24:53 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * 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 <brendan@lisa.cygnus.com>
-
- * 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 <wilson@chestnut.cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- * g++.1: Tiny updates.
-
-Fri Jul 7 13:05:20 1995 Mike Stump <mrs@cygnus.com>
-
- * 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 <brendan@lisa.cygnus.com>
-
- * typeck.c (comptypes, case OFFSET_REF): If either offset basetype
- is a TEMPLATE_TYPE_PARM, give a match.
-
-Mon Jul 3 15:17:20 1995 Steve Chamberlain <sac@slash.cygnus.com>
-
- * g++.c (sys/file.h): Remove change of Jun 28.
-
-Fri Jun 30 15:42:57 1995 Mike Stump <mrs@cygnus.com>
-
- * method.c (build_overload_value): Handle encoding of null pointer
- constants (or any pointer with a constant numeric value) for
- templates.
-
-Fri Jun 30 13:45:51 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * call.c (convert_harshness): Add QUAL_CODE when we're faced with
- const vs non-const for void conversions.
-
-Fri Jun 30 10:19:52 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Fri Jun 30 02:22:26 1995 Mike Stump <mrs@cygnus.com>
-
- * search.c (dfs_pushdecls): Consume 2 or 3 orders of magnitude less
- memory please when virtual bases are used.
-
-Thu Jun 29 19:03:47 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Thu Jun 29 09:35:05 1995 Mike Stump <mrs@cygnus.com>
-
- * decl.c (BOOL_TYPE_SIZE): Fix broken SLOW_BYTE_ACCESS check.
-
-Thu Jun 29 03:43:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * pt.c (instantiate_template): Don't strip 'this' twice.
-
- * pt.c (coerce_template_parms): Allow null pointer constants.
-
- * decl.c (revert_static_member_fn): But only if DECL_ARGUMENTS is
- set.
-
-Wed Jun 28 23:34:58 1995 Steve Chamberlain <sac@slash.cygnus.com>
-
- * g++.c (pfatal_with_name): Use my_strerror to get error
- string.
- (sys/file.h): Include if HAVE_FILE_H defined.
-
-Wed Jun 28 18:39:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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 <jason@yorick.cygnus.com>
- * 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.
+ * 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.
-Wed Jun 28 14:07:27 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+Mon Oct 13 17:41:26 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * parse.y (component_decl): Clear PREFIX_ATTRIBUTES here.
+ * decl.c (store_return_init): Allow classes with explicit ctors to
+ be used with the named return values extension.
-Wed Jun 28 11:05:13 1995 Mike Stump <mrs@cygnus.com>
+Fri Oct 10 12:21:11 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * pt.c (instantiate_decl): Fix previous change.
-Mon Jun 26 13:38:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Oct 9 12:08:21 1997 Jason Merrill <jason@yorick.cygnus.com>
- * expr.c (cplus_expand_expr): Don't mess with temp slots.
+ * pt.c (tsubst): Fix thinko.
+ (instantiate_decl): Really use the original template.
- * decl2.c (warn_if_unknown_interface): Don't crash if tinst_for_decl
- returns null.
+ * call.c (build_new_method_call): Use simple constructor_name for
+ error messages.
- * decl2.c (check_classfn): Use revert_static_member_fn.
- * decl.c (revert_static_member_fn): Diagnose static member functions
- declared const or volatile.
+Wed Oct 8 22:44:42 1997 Jeffrey A Law (law@cygnus.com)
- * decl2.c (grokfield): Check for missing default args here, too.
- (check_default_args): Function to do the checking.
- * decl.c (pushdecl): Use it.
+ * method.c (build_underscore_int): Don't use ANSI specific
+ features.
- * decl.c (pushdecl): Don't warn about shadowing a member of `this'
- if there is no `this'.
+Wed Oct 8 00:18:22 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sun Jun 25 11:34:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c (finish_prevtable_vardecl): Check DECL_REALLY_EXTERN
+ for our key method; it might have been inlined by -O3.
- * call.c (build_method_call): Downgrade 'called before definition'
- to a warning, as it ought to go away after Monterey.
+Tue Oct 7 23:00:12 1997 Mark Mitchell <mmitchell@usa.net>
-Sat Jun 24 14:18:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (make_typename_type): Do not try to call lookup_field for
+ non-aggregate types.
- * pt.c (coerce_template_parms): Don't do extra checking on pointer
- to member arguments.
+Tue Oct 7 22:52:10 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): const and reference members don't prevent
- a class from being an aggregate.
+ * typeck.c (build_reinterpret_cast): Tweak.
- * class.c (finish_struct): Signatures are always aggregates.
+Tue Oct 7 22:45:31 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
-Fri Jun 23 17:20:29 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (build_reinterpret_cast): converting a void pointer
+ to function pointer with a reinterpret_cast produces a warning
+ if -pedantic is issued
- * decl2.c (check_classfn): Improve error message.
+Tue Oct 7 22:43:43 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * pt.c (tsubst): Handle PROMOTE_PROTOTYPES.
+ * typeck.c (c_expand_return): Don't warn about returning a
+ reference-type variable as a reference.
-Thu Jun 22 01:50:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Tue Oct 7 21:11:22 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (comptypes): Don't ignore method quals.
+ * method.c (build_static_name): Fix typo.
- * class.c (finish_struct): Non-abstract virtuals are always USED.
+1997-10-07 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * decl.c (duplicate_decls): Make sure DECL_LANG_SPECIFIC is set on
+ OLDDECL before we try to do DECL_USE_TEMPLATE.
- * 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.
+Tue Oct 7 00:48:36 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (tsubst, PARM_TYPE): Propagate DECL_ARTIFICIAL.
+ * decl.c (duplicate_decls): Don't warn about template instances.
- * decl.c (start_function): For pre-parsed functions, layout all of
- the parm decls again.
- (grokvardecl): TREE_PUBLIC depends on DECL_THIS_EXTERN, not
+ * typeck.c (mark_addressable): Lose ancient code that unsets
DECL_EXTERNAL.
- * pt.c (coerce_template_parms): Improve checking for invalid
- template parms.
-
-Wed Jun 21 12:01:16 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * decl.c (finish_function): Clear current_class_decl.
-
- * typeck.c (build_conditional_expr): Use convert (boolean_type_node
- instead of truthvalue_conversion.
-
- * class.c (finish_struct): A data member with the same name as the
- class doesn't suppress constructors.
-
-Fri Jun 16 18:11:39 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu)
-
- * 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.
-
-Fri Jun 16 17:06:28 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (duplicate_decls): Complain about virtual functions
- redeclared to be inline.
-
-Fri Jun 16 13:20:38 1995 Mike Stump <mrs@cygnus.com>
-
- * decl.c (get_unique_name): New routine to name unnamed namespaces.
- (push_namespace): Use get_unique_name for naming unnamed namespaces.
-
-Fri Jun 16 15:07:29 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
-
- * Make-lang.in (DEMANGLER_PROG): Add LIBS.
-
-Thu Jun 15 15:00:41 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (define_function): Don't set DECL_INTERFACE_KNOWN.
-
- * parse.y: Call cplus_decl_attributes with prefix_attributes where
- appropriate.
-
-Wed Jun 14 19:24:49 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Mon Jun 12 17:50:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Mon Jun 12 12:36:59 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Mon Jun 12 10:41:40 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (can_convert): Also check for distance > 0.
- (can_convert_arg): Ditto.
- (user_harshness): Ditto.
-
-Fri Jun 9 19:17:21 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * g++.c (MATH_LIBRARY): Provide default.
- (main): Always link with the math library if we link with libstdc++.
-
- * decl.c (start_function): Complain about redefinition of a function
- even when the pending_inline version is compiled after the other
- version.
-
-Thu Jun 8 15:44:38 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * gc.c (build_dynamic_cast): Build up a reference to a parameter of
- aggregate type.
-
-Wed Jun 7 20:00:31 1995 Mike Stump <mrs@cygnus.com>
-
- * *.[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).
-
-Wed Jun 7 19:02:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Wed Jun 7 15:31:57 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * init.c (build_vec_delete): Resolve an offset ref before we try to
- use it.
-
-Wed Jun 7 14:19:32 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Tue Jun 6 09:41:27 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Mon Jun 5 18:49:38 1995 Mike Stump <mrs@cygnus.com>
-
- * method.c (build_opfncall): Use DECL_CHAIN, not TREE_CHAIN for
- results from lookup_fnfields. Always give warning/error on bad
- code.
-
-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 <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * 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.
-
- * 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.
-
- * class.c (popclass): Don't mess with current_class_decl,
- current_vtable_decl, or C_C_D.
-
-Mon May 29 12:45:10 1995 Paul Eggert <eggert@twinsun.com>
-
- * Make-lang.in (c++.mostlyclean): Remove $(DEMANGLER_PROG).
-
-Thu Jun 1 17:03:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (lookup_name_real): Don't try to look anything up in an
- erroneous object.
-
-Fri Jun 2 10:30:14 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed May 31 19:10:32 1995 Mike Stump <mrs@cygnus.com>
-
- * decl.c (grokdeclarator): Always give errors on constant overflow
- for array indices.
-
-Wed May 31 11:39:43 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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 *&.
-
-Wed May 24 15:55:18 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
-
- * decl.c (duplicate_decls): Check simple_cst_equal result against 0.
- * decl2.c (finish_anon_union): Likewise.
- * method.c (largest_union_member): Likewise.
-
-Wed May 24 14:41:11 1995 H.J. Lu (hjl@nynexst.com)
-
- * Make-lang.in (cxxmain.o): Replace single quotes with backslashes.
-
-Mon May 22 17:38:48 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
-
- * 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.
-
-Wed May 24 01:39:03 1995 Jason Merrill <jason@deneb.cygnus.com>
-
- * call.c (build_method_call): parms can be null, duh.
-
-Tue May 23 01:32:09 1995 Jason Merrill <jason@deneb.cygnus.com>
-
- * call.c (build_method_call): If convert_arguments failed, just bail.
-
-Fri May 19 10:31:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * cvt.c (convert_force): Pass LOOKUP_NORMAL to cp_convert.
-
- * tree.c (copy_to_permanent): Oops.
-
-Fri May 19 10:01:07 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * cp-tree.h (break_out_target_exprs): Add decl.
-
-Thu May 18 13:02:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (start_function): Move *all* interface handling stuff after
- the pushdecl.
-
- * 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.
-
- * typeck.c (convert_arguments): Use it.
-
- * method.c (hack_identifier): Use convert_from_reference to
- dereference a reference.
-
-Wed May 17 17:54:54 1995 Mike Stump <mrs@cygnus.com>
-
- * call.c (convert_harshness): Move reference bashing before pointer
- to member bashing.
-
-Wed May 17 16:57:53 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed May 17 01:43:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck2.c (store_init_value): Don't take the MAIN_VARIANT of the
- decl type.
-
- * 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.
-
- * expr.c (cplus_expand_expr, NEW_EXPR): If this is an explicit
- constructor call, mark slot addressable.
-
-Tue May 16 18:37:51 1995 Douglas Rupp (drupp@cs.washington.edu)
-
- * g++.c: Changed WINNT to _WIN32.
-
-Tue May 16 12:40:16 1995 Jason Merrill <jason@lisa.cygnus.com>
-
- * lex.c (handle_sysv_pragma): Don't use token_buffer.
-
-Tue May 16 12:05:26 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Tue May 16 11:55:35 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (push_overloaded_decl): Return the new decl even if it
- can't be pushed.
-
-Tue May 16 11:00:37 1995 Jason Merrill <jason@lisa.cygnus.com>
-
- * 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.
-
-Mon May 15 12:47:56 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * decl2.c (import_export_vtable): Make duplicates weak rather than
- static if supported.
- (import_export_inline): Ditto.
- * pt.c (do_pending_expansions): Ditto.
-
- * class.c (build_vbase_path): flag_assume_nonnull_objects only
- affects reference conversion.
-
- * 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/.
-
-Tue May 16 07:06:28 1995 Paul Eggert <eggert@twinsun.com>
-
- * method.c (numeric_output_need_bar): Renamed from misspelling.
-
- * typeck.c (build_ptrmemfunc): Fix misspellings in messages.
-
-Sun May 14 10:26:22 1995 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
-
- * lang-options.h, lang-specs.h: New files.
-
-Thu May 11 00:31:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (default_conversion): Don't check for BLKmode before
- pulling out the decl_constant_value.
-
- * decl.c (start_function): Clear named_labels and shadowed_labels.
-
- * typeck.c (build_function_call_real): Also synthesize methods here.
-
-Wed May 10 00:55:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl2.c (finish_file): Synthesize exported methods before the
- reconsider loop.
-
- * parse.y: Move declaration of flag_new_for_scope to file scope.
-
-Tue May 9 19:10:33 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Mon May 8 12:41:52 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (define_function): Mark function decl artificial.
-
-Sun May 7 00:51:28 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * parse.y (simple_stmt, FOR): Put back push/pop for condition scope.
-
- * decl2.c (grokclassfn): DECLs don't have cv-qualified types.
- * tree.c (build_cplus_method_type): Ditto.
-
- * cp-tree.h (SET_DECL_ARTIFICIAL): Just set DECL_ARTIFICIAL to 1.
-
- * 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.
-
-Sat May 6 02:39:41 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (duplicate_decls): Don't check DECL_NOT_REALLY_EXTERN for
- decls that don't include it.
-
-Fri May 5 14:23:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (duplicate_decls): Decls that have DECL_INTERFACE_KNOWN or
- DECL_NOT_REALLY_EXTERN set aren't extern decls.
-
- * 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.
-
- * pt.c (do_type_instantiation): Only instantiate member functions
- that actually come from templates.
-
-Fri May 5 09:46:05 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Fri May 5 00:37:14 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (convert_harshness): Handle pointers to members better.
-
-Thu May 4 16:00:26 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl2.c (delete_sanity): Do access control here.
- * init.c (build_delete): Instead of here.
-
- * Make-lang.in: Build c++filt.
-
-Wed May 3 02:59:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl2.c (cplus_decl_attributes): If we just modified a TYPE_DECL,
- update our IDENTIFIER_TYPE_VALUE.
-
-Fri Apr 28 07:58:41 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * lex.c (cons_up_default_function): Fix linkage of #pragma
- implemented functions.
-
-Thu Apr 27 16:56:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * method.c (build_overload_name): Simplify and fix repeated type
- folding.
-
- * decl.c (grokdeclarator): Prohibit pointers to void or reference
- members.
-
-Thu Apr 27 09:49:07 1995 Mike Stump <mrs@cygnus.com>
-
- * typeck2.c (process_init_constructor): Make sure initializers are
- fully digested.
-
-Thu Apr 27 01:11:55 1995 Jason Merrill <jason@python.cygnus.com>
-
- * lex.c (cons_up_default_function): Always defer synthesis.
-
-Thu Apr 27 00:20:37 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl2.c (mark_inline_for_output): Don't play with pending_inline
- stuff.
-
-Wed Apr 26 17:48:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Wed Apr 26 17:11:25 1995 Jason Merrill <jason@deneb.cygnus.com>
-
- * typeck.c (build_function_call_real): Improve error message for
- calling a non-function.
-
- * method.c (hack_identifier): Lose check for calling a data member.
-
-Wed Apr 26 16:59:13 1995 Mike Stump <mrs@cygnus.com>
-
- * typeck2.c (build_functional_cast): Remove very old cruft.
- Seems like good code is generated without it.
-
-Wed Apr 26 00:47:16 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * method.c (do_build_assign_ref): Fix handling of anonymous unions.
- (do_build_copy_constructor): Ditto.
-
- * parse.y (simple_stmt, SWITCH): Call {push,pop}_switch.
-
- * decl.c (push_switch): New function.
- (pop_switch): Ditto.
- (define_case_label): Check for jumping over initialization.
-
- * 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 (duplicate_decls): Check for a function being redeclared
- inline after its address has been taken.
-
- * typeck.c (build_conditional_expr): Handle related class lvalues.
-
-Tue Apr 25 13:20:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * pt.c (do_pending_expansions): Don't expand unused templates.
+ * pt.c (do_decl_instantiation): Lose support for instantiating
+ non-templates.
- * parse.y (component_decl): Accept a lone semicolon.
+ * call.c (build_new_function_call): Fix handling of null explicit
+ template args.
+ (build_new_method_call): Likewise.
-Tue Apr 25 00:25:56 1995 Jason Merrill <jason@rtl.cygnus.com>
+Mon Oct 6 23:44:34 1997 Mark Mitchell <mmitchell@usa.net>
- * call.c (build_method_call): Don't allow an RTL_EXPR to serve as the
- object parameter anymore.
+ * method.c (build_underscore_int): Fix typo.
- * expr.c (cplus_expand_expr): Don't create RTL_EXPRs with no insns.
+1997-10-06 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Apr 24 12:35:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * tree.c (print_lang_statistics): #if 0 call to
+ print_inline_obstack_statistics until its definition is checked in.
- * parse.y (simple_stmt, decl case): Clear prefix_attributes.
- (lang_extdef): Ditto.
+Mon Oct 6 09:27:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * decl2.c (finish_file): Move dump_tree_statistics to end.
- * pt.c (tsubst): Propagate attributes const and noreturn.
+ * pt.c (instantiate_decl): Look for the original template.
+ (tsubst): Set DECL_IMPLICIT_INSTANTIATION on partial instantiations
+ of member templates.
- * typeck.c (build_modify_expr): If warn_synth, call build_opfncall
- before doing the default thing.
+Wed Oct 1 08:41:38 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Apr 27 21:49:36 1995 Doug Evans <dje@cygnus.com>
+ * Makefile.in (g++FAQ.*): New rules.
+ (CONFLICTS): Update.
+ * g++FAQ.texi: Moved from libg++.
- * typeck.c (common_type): Call lookup_attribute instead of
- value_member.
+ * parse.y (PFUNCNAME): Only specify the type once.
-Tue Apr 25 18:07:43 1995 Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
+1997-10-01 Brendan Kehoe <brendan@lasher.cygnus.com>
- * Make-lang.in: Change "realclean" to "maintainer-clean".
+ * lex.c (real_yylex): Clean up the code to fully behave the way
+ the c-lex.c parser does for complex and real numbers.
-Sun Apr 23 12:32:38 1995 Mike Stump <mrs@cygnus.com>
+Tue Sep 30 08:51:36 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_file): Fix broken linked list handling.
+ * method.c (build_decl_overload_real): Reformat.
-Fri Apr 21 18:08:43 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Tue Sep 30 00:18:26 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_base_struct): Don't set TYPE_HAS_COMPLEX_*_REF
- as often.
- (finish_struct): Ditto.
+ * method.c (synthesize_method): If at_eof, determine our linkage.
- * various: Use TYPE_HAS_TRIVIAL_* instead of TYPE_HAS_COMPLEX_*.
+1997-09-29 Paul Eggert <eggert@twinsun.com>
- * cp-tree.h (TYPE_HAS_TRIVIAL_INIT_REF): New macro.
- (TYPE_HAS_TRIVIAL_ASSIGN_REF): New macro.
+ * lex.c (real_yylex): Treat `$' just like `_', except issue a
+ diagnostic if !dollars_in_ident or if pedantic.
-Fri Apr 21 15:52:22 1995 Jason Merrill <jason@python.cygnus.com>
+ * lang-specs.h (@c++): -ansi no longer implies -$.
- * typeck.c (c_expand_return): Only expand a returned TARGET_EXPR if
- it is of the same type as the return value.
+ * decl2.c (lang_decode_option):
+ -traditional and -ansi now do not mess with
+ dollars_in_ident.
-Fri Apr 21 03:01:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon Sep 29 19:57:51 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
- * decl2.c (finish_file): Reconsider if synthesizing a method wrote
- out its assembly.
+ * 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.
- * typeck.c (convert_for_initialization): Don't call a trivial copy
- constructor.
+ * call.c, cp-tree.h, decl.c, tree.c: Finish prototyping.
- * typeck2.c (store_init_value): Only abort if the type has a
- non-trivial copy constructor.
+ * expr.c (cplus_expand_expr): Make it static.
- * 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.
+ * decl2.c, init.c, typeck.c: Include "expr.h".
+ (expand_expr): Use proper values when calling the function.
- * tree.c (build_cplus_new): Layout the slot.
+Mon Sep 29 11:05:54 1997 Alexandre Oliva <oliva@dcc.unicamp.br>
- * expr.c (cplus_expand_expr): Use expand_call to expand the call
- under a NEW_EXPR, so the target is not discarded.
+ * 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.
-Thu Apr 20 14:59:31 1995 Mike Stump <mrs@cygnus.com>
+Mon Sep 29 09:20:53 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * gc.c (build_dynamic_cast): Tighten error checking.
+ * decl.c (cp_finish_decl): Allow expand_aggr_init to set
+ TREE_USED, reset value based on already_used.
-Thu Apr 20 11:23:54 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * decl2.c (cplus_decl_attributes): Attributes applied to a template
- really apply to the template's result.
-
- * tree.c (lvalue_p): Check IS_AGGR_TYPE instead of TREE_ADDRESSABLE
- to decide whether to consider a CALL_EXPR an lvalue.
-
- * class.c (finish_struct_bits): Only set TREE_ADDRESSABLE if the
- type has a non-trivial copy constructor.
+ * init.c (expand_member_init): Revert change.
+
+Mon Sep 29 08:57:53 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * cp-tree.h, decl.c, decl2.c, pt.c:
+ Lose DECL_C_STATIC and DECL_PUBLIC. Don't pretend statics are public.
+
+ * decl2.c (lang_decode_option): Add missing ;.
+
+Sat Sep 27 16:22:48 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * friend.c (do_friend): Disable injection for all template-derived
+ decls.
+ * 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 <mmitchell@usa.net>
+
+ * call.c (add_template_candidate): Add explicit_targs parameter.
+ (build_scoped_method_call): Use it.
+ (build_overload_call_real): Likewise.
+ (build_user_type_conversion_1): Likewise.
+ (build_new_function_call): Likewise.
+ (build_object_call): Likewise.
+ (build_new_op): Likewise.
+ (build_new_method_call): Likewise.
+ (build_new_function_call): Handle TEMPLATE_ID_EXPR.
+ (build_new_method_call): Likewise.
+
+ * 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 <schwab@issan.informatik.uni-dortmund.de>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ 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 <brendan@lisa.cygnus.com>
+
+ * decl.c (start_function): Up warning of no return type to be a
+ pedwarn.
+
+Mon Sep 22 14:15:34 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * call.c (build_over_call): Do require_complete_type before
+ build_cplus_new.
- * decl.c (start_function): If interface_known, unset
- DECL_NOT_REALLY_EXTERN on the function.
+Thu Sep 18 16:47:52 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Apr 19 16:53:13 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * search.c (lookup_field): Call complete_type in all cases.
- * pt.c (do_function_instantiation): Handle explicit instantiation of
- member functions.
- (do_type_instantiation): Handle 'inline template class foo<int>',
- meaning just spit out the vtable.
+ * decl.c (finish_function): Just warn about flowing off the end.
- * lex.c (cons_up_default_function): Set DECL_NOT_REALLY_EXTERN on
- the consed functions.
+Wed Sep 17 10:31:25 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (import_export_inline): Set DECL_INTERFACE_KNOWN.
+ * decl.c (grokparms): Don't bash a permanent list node if we're
+ in a function.
-Wed Apr 19 16:28:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+1997-09-17 Brendan Kehoe <brendan@lisa.cygnus.com>
- * call.c, class.c, decl2.c, gc.c, init.c, parse.y, pt.c, search.c,
- typeck.c: Include output.h.
+ * Makefile.in (CONFLICTS): Fix s/r conflict count to 18.
-Wed Apr 19 14:57:21 1995 Gerald Baumgartner (gb@alexander.cs.purdue.edu)
+Tue Sep 16 14:06:56 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Allow a signature member functions to
- be called from a default implementation.
+ * call.c (build_new_op): Give better error for syntactically
+ correct, but semantically invalid, use of undeclared template.
-Wed Apr 19 10:21:17 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (compare_qual): Handle pmfs.
- * repo.c (finish_repo): Remember what directory we are in.
+ * decl.c (store_parm_decls): last_parm_cleanup_insn is the insn
+ after the exception spec.
- * search.c (expand_upcast_fixups): Don't mess with abort_fndecl.
+Mon Sep 15 11:52:13 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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 (null_ptr_cst_p): Integer type, not integral type.
-Wed Apr 19 02:32:40 1995 Mike Stump <mrs@cygnus.com>
+ * call.c (joust): Disable warnings until they can be moved to the
+ right place.
- * 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.
+Fri Sep 12 16:11:13 1997 Per Bothner <bothner@cygnus.com>
-Tue Apr 18 03:57:35 1995 Michael Meissner (meissner@cygnus.com)
+ * Makefile.in, config-lang.in: Convert to autoconf.
- * Makefile.in (lex.o): Add dependency on c-pragma.h.
+Thu Sep 11 17:14:55 1997 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (handle_sysv_pragma): Use NULL_PTR and NULL_TREE as
- appropriate, instead of 0.
+ * decl.c (lookup_name_real): Add implicit 'typename' to types from
+ base classes.
-Mon Apr 17 12:28:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (most_specialized_class): Fix typo.
+ (tsubst): Move constant folding to TREE_VEC case.
- * decl.c (pushdecl): Use decls_match, not duplicate_decls, for
- comparing local and global decls.
+Thu Sep 11 10:08:45 1997 Mark Mitchell <mmitchell@usa.net>
-Fri Apr 14 01:46:52 1995 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.
- * typeck.c (convert_arguments): Only prohibit passing to ... of
- types with non-trivial copy constructors.
+ * pt.c (uses_template_parms): Check the values of an enumeration
+ type to make sure they don't depend on template parms.
- * repo.c (repo_template_used): Don't try to mess with no id.
+ * 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.
-Fri Apr 14 23:32:50 1995 Per Bothner <bothner@rtl.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.
- * decl.c (duplicate_decls): Use cp_warning_at for redundant-decls.
+Wed Sep 10 11:21:55 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Apr 13 15:37:42 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * except.c (expand_builtin_throw): #ifndef DWARF2_UNWIND_INFO.
+ * decl2.c (finish_file): Only register exception tables if we
+ need to.
- * cp-tree.h (current_tinst_level): Delete declaration, since it's
- static inside pt.c.
+ * decl.c (init_decl_processing): Add __builtin_[fs]p.
- * typeck.c (build_modify_expr): Catch incompatible array assignment.
+Tue Sep 9 19:49:38 1997 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (attribute_list, attrib): Rewrite actions to feed the
- right stuff to decl_attributes.
+ * pt.c (unify): Just return 0 for a TYPENAME_TYPE.
-Thu Apr 13 11:24:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Tue Sep 9 17:57:25 1997 Mark Mitchell <mmitchell@usa.net>
- * search.c (dfs_debug_mark): Check for magic virtual like
- import_export_vtable.
+ * 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.
- * typeck.c (build_binary_op_nodefault): Don't call cp_pedwarn with
- four args.
+1997-09-09 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Apr 12 12:02:57 1995 Jason Merrill <jason@deneb.cygnus.com>
+ * typeck.c (build_indirect_ref): Heed FLAG_VOLATILE similar to
+ c-typeck.c.
- * decl2.c (finish_file): Move prevtable pass before needs_messing_up
- decision.
+Tue Sep 9 09:36:39 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
-Tue Apr 11 11:20:27 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * except.c (expand_throw): Call build_delete for all
+ exception types, not just objects with destructors.
- * decl.c (finish_decl): If we're writing out a static data member of
- a class, we want the debug info for that class.
+Mon Sep 8 02:33:20 1997 Jody Goldberg <jodyg@idt.net>
- * gc.c (build_t_desc): Check linkage of a class properly.
+ * 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.
- * 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.
+Mon Sep 8 01:21:43 1997 Mark Mitchell <mmitchell@usa.net>
-Mon Apr 10 12:15:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- * 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.
+ * 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.
- * pt.c (do_function_instantiation): Call repo_template_instantiated.
- (do_type_instantiation): Ditto. Don't diagnose multiple
- instantiation.
+ * error.c (dump_expr): Obtain the correct declaration for a
+ TEMPLATE_CONST_PARM.
- * decl2.c (finish_file): Use DECL_NOT_REALLY_EXTERN when deciding
- whether or not to synthesize a method.
+ * call.c (add_template_conv_candidate): New function.
+ (build_object_call): Handle member templates, as done in the other
+ build_ functions.
+
+Sat Sep 6 10:20:27 1997 Mark Mitchell <mmitchell@usa.net>
- 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.
+ * 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.
-Sat Apr 8 17:45:41 1995 Mike Stump <mrs@cygnus.com>
+Fri Sep 5 17:27:38 1997 Jason Merrill <jason@yorick.cygnus.com>
- * gc.c (build_headof): Use ptrdiff_type_node instead of
- integer_type_node on pointer arithmetic.
+ * class.c (grow_method): Remove check for redeclaration.
-Sat Apr 8 11:57:04 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Fri Sep 5 01:37:17 1997 Mark Mitchell <mmitchell@usa.net>
- * typeck.c (build_modify_expr): Undo previous change.
+ * 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 <mmitchell@usa.net>
+
+ * 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.
-Thu Apr 6 01:23:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (do_pending_inlines): Set up template parameter context
+ for member templates.
+ (process_next_inline): Likewise.
- * Makefile.in (compiler): Remove ../cc1plus before rebuilding it.
+ * 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 <jason@yorick.cygnus.com>
- * repo.c (get_base_filename): Put the .rpo file in the directory
- with the object file, not the source.
+ * typeck.c (c_expand_return): Always convert_for_initialization
+ before checking for returning a pointer to local.
- * typeck.c (build_conditional_expr): Handle pmf's better.
+ * pt.c (type_unification): If strict and the function parm doesn't
+ use template parms, just compare types.
- * repo.c (finish_repo): Also use ASM_OUTPUT_LABELREF to print out
- the name of the symbol.
+Wed Sep 3 10:35:49 1997 Klaus Espenlaub <kespenla@student.informatik.uni-ulm.de>
-Wed Apr 5 15:24:12 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * method.c (build_overloaded_value): Replace direct call
+ to the floating point emulator with REAL_VALUE_TO_DECIMAL macro.
- * 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.
+Wed Sep 3 00:02:53 1997 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (cons_up_default_function): If this function belongs to a
- template class, call repo_template_used for it.
+ * typeck.c (convert_arguments): Don't arbitrarily choose the first
+ of a set of overloaded functions.
- * repo.c (repo_template_used): Using a class means using its vtable,
- if any.
- (finish_repo): Ditto.
+Tue Sep 2 12:09:13 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): Only wrap TARGET_EXPRs in RTL_EXPRs
- if the type has a complex copy constructor.
+ * lex.c (real_yylex): Don't elide __FUNCTION__.
- * decl2.c (lang_decode_option): -frepo implies
- -fno-implicit-templates.
+ * method.c (build_overload_value): Add in_template parm.
+ (build_overload_int): Likewise.
+ (build_overload_identifier): Pass it.
- * decl.c (start_function): Clear current_{base,member}_init_list.
+ * decl.c (duplicate_decls): Don't bash a previous template
+ definition with a redeclaration.
- * lex.c (init_lex): Also unset *_eq if ! flag_operator_names.
+ * pt.c (unify): float doesn't match double.
-Tue Apr 4 16:11:08 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- * 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 Sep 2 10:27:08 1997 Richard Henderson <rth@cygnus.com>
-Mon Apr 3 16:55:08 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (build_ptrmemfunc1): Clean up ptr->int cast warnings.
- * repo.c (get_base_filename): Take filename parm, fix logic bug.
+Mon Sep 1 13:19:04 1997 Eugene Mamchits <eugin@ips.ras.ru>
- * 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.
+ * call.c (add_builtin_candidate): Add missing TREE_TYPE.
+ (compare_ics): Likewise.
- * init.c (build_new): Handle initialization of arrays of builtins
- properly.
+Mon Sep 1 13:19:04 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Apr 3 15:08:04 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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.
- * repo.c: Include config.h to get definitions of bcopy and rindex
- on systems that don't have them (e.g., SVR4).
+ * call.c (build_new_op): Strip leading REF_BIND from first operand
+ to builtin operator.
-Mon Apr 3 14:41:55 1995 Mike Stump <mrs@cygnus.com>
+ * decl2.c (mark_vtable_entries): Mark abort_fndecl as used when we
+ use its RTL.
- * 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.
+Thu Aug 28 09:45:23 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Apr 3 10:45:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (null_ptr_cst_p): Remove support for (void*)0.
- * 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.
+Wed Aug 27 02:03:34 1997 Jeffrey A Law (law@cygnus.com)
- * parse.y (structsp): Add TYPENAME_KEYWORD complex_type_name.
+ * typeck.c (expand_target_expr): Make definition match declaration.
-Sun Apr 2 23:43:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * class.c (get_basefndecls): Make definition match declaration.
- * search.c (compute_access): Don't try to do access control on
- nested types.
+Mon Aug 25 14:30:02 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 31 10:14:23 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * input.c (sub_getch): Eventually give up and release the input file.
- * repo.c: New file to handle things repo.
+ * decl.c (cp_finish_decl): If #p i/i, put inline statics in the
+ right place.
- * 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.
+ * call.c (joust): Tweak message.
- * parse.y (template_instantiate_once): Call repo_template_used.
+Sat Aug 23 18:02:59 1997 Mark Mitchell <mmitchell@usa.net>
- * lex.c (lang_init): Call init_repo.
+ * error.c (type_as_string): Put const/volatile on template type
+ parameters where appropriate.
- * decl2.c: Handle flag_use_repository.
- (finish_file): Call finish_repo.
+Sat Aug 23 17:47:22 1997 Jeffrey A Law (law@cygnus.com)
- * decl.c (start_method): Call repo_template_used if this is a
- template method.
+ * call.c (strictly_better): Make arguments unsigned ints.
- * Makefile.in (CXX_OBJS): Add repo.o.
- (repo.o): Add dependencies.
+Thu Aug 21 18:48:44 1997 Jason Merrill <jason@yorick.cygnus.com>
- * Make-lang.in (CXX_SRCS): Add repo.c.
+ * lex.c (real_yylex): Refer to __complex instead of complex.
- * decl.c (start_function): If DECL_INTERFACE_KNOWN and
- DECL_NOT_REALLY_EXTERN are both set, unset DECL_EXTERNAL.
+Thu Aug 21 22:25:46 1997 J"orn Rennecke <amylaar@cygnus.co.uk>
- * typeck.c (build_binary_op_nodefault): Identify the invalid operand
- types used.
+ * lex.c (real_yylex): Don't use getc directly.
- * decl.c (duplicate_decls): Propagate DECL_NOT_REALLY_EXTERN.
+Wed Aug 20 17:25:08 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Mar 30 17:54:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (is_subseq): Don't try to be clever.
- * 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.
+Wed Aug 20 03:13:36 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
- * method.c (do_build_copy_constructor): Reverse
- current_base_init_list after we've built it up.
+ * 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.
-Thu Mar 30 14:35:18 1995 Mike Stump <mrs@cygnus.com>
+Wed Aug 20 01:34:40 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (build_throw): Never warn about the value of throw not
- being used.
+ * decl2.c (mark_vtable_entries): Instead of replacing pure
+ virtuals with a reference to __pure_virtual, copy the decl and
+ change the RTL.
-Thu Mar 30 13:16:54 1995 Mike Stump <mrs@cygnus.com>
+Tue Aug 19 02:26:07 1997 Jason Merrill <jason@yorick.cygnus.com>
- * except.c (expand_start_catch_block): Check for bad catch parameter
- declarations.
+ * pt.c (lookup_nested_type_by_name): Handle typedef wierdness.
-Thu Mar 30 13:06:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (instantiate_class_template): Call repo_template_used
+ before finish_prevtable_vardecl.
- * decl.c (finish_function): Only set DECL_NOT_REALLY_EXTERN if
- DECL_EXTERNAL is not already set.
+ * call.c (is_subseq): New fn.
+ (compare_ics): Use it.
-Thu Mar 30 11:26:24 1995 Mike Stump <mrs@cygnus.com>
+ * repo.c (finish_repo): Don't crash on no args.
- * 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.
+ * parse.y (named_complex_class_head_sans_basetype): Handle
+ explicit global scope.
+ * decl2.c (handle_class_head): New fn.
-Thu Mar 30 11:15:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * Makefile.in (BISON): Add -L flag.
- * decl2.c (import_export_inline): Don't set DECL_NOT_REALLY_EXTERN
- here.
+ * pt.c (unify): Add CONST_DECL case.
- * 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.
+Thu Aug 14 10:05:13 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Mar 29 19:35:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * rtti.c (permanent_obstack): Fix decl to not be a pointer.
- * cp-tree.h (DECL_THIS_INLINE): New macro.
- (DECL_NOT_REALLY_EXTERN): New macro.
- (DECL_THIS_STATIC): New macro.
+ * 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.
- * 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.
+Wed Aug 13 19:19:25 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Don't bother trying to handle inlines
- specially.
- * cvt.c (convert_to_aggr): Ditto.
+ * error.c (dump_decl): Don't bother processing a function with no
+ DECL_LANG_SPECIFIC.
- * pt.c (do_function_instantiation): Handle instantiation of
- public inlines, too.
+ * method.c (emit_thunk): Call init_function_start in the macro case.
-Wed Mar 29 16:04:25 1995 Mike Stump <mrs@cygnus.com>
+Wed Aug 13 10:46:19 1997 H.J. Lu (hjl@gnu.ai.mit.edu)
- * 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.
+ * decl2.c (DEFAULT_VTABLE_THUNKS): Define to be 0 if not
+ defined and used to set flag_vtable_thunks.
-Mon Mar 27 07:14:33 1995 Warner Losh <imp@village.org>
+Tue Aug 12 20:13:57 1997 Jason Merrill <jason@yorick.cygnus.com>
- * g++.c: Removed __NetBSD__ from conditional.
- Declare strerror if HAVE_STRERROR is defined; otherwise
- declare sys_errlist and sys_nerr.
- (my_strerror): New function.
+ * parse.y: Don't clear the inlines from their obstack until they've
+ all been processed.
-Tue Mar 28 14:16:35 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (duplicate_decls): Don't complain about exception
+ specification mismatch if flag_exceptions is off.
- * search.c (get_binfo): Don't try to be so clever.
+ * Makefile.in (BISON): bison, not byacc or bison -y.
+ (parse.c): Use bison flags.
- * tree.c (copy_to_permanent): Also suspend_momentary().
+Mon Aug 11 15:01:56 1997 Marc Lehmann <pcg@goof.com>
- * cvt.c (cp_convert_to_pointer): Hand off to convert_fn_pointer even
- if the types are the same.
+ * Make-lang.in (c++.distclean): Remove g++.c on make distclean.
- * decl.c (start_function): Handle extern inlines more like C++ says
- we should.
+Sun Aug 10 12:06:09 1997 Paul Eggert <eggert@twinsun.com>
- * init.c (build_member_call): Hand constructor calls off to
- build_functional_cast.
+ * cp-tree.h: Replace STDIO_PROTO with PROTO in include files.
+ * cvt.c, error.c, except.c, expr.c, friend.c, init.c, rtti.c:
+ Include <stdio.h> before include files that formerly used STDIO_PROTO.
- * typeck2.c (build_functional_cast): Use DECL_NESTED_TYPENAME to get
- the name of the type.
+ * decl.c, g++spec.c, lex.c, method.c, repo.c:
+ Include "config.h" first, as per autoconf manual.
-Tue Mar 28 13:13:56 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Fri Aug 8 11:47:48 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Check for the decl returned by
- grokfndecl to be null before using build_decl_attribute_variant.
+ * 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.
-Mon Mar 27 18:04:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl2.c (lang_decode_option): Handle -fhandle-exceptions.
+ * lang-options.h: Add -fhandle-exceptions.
- * init.c (build_new): Use build_pointer_type instead of
- TYPE_POINTER_TO.
+ * class.c (build_vtable): vtables are artificial.
+ (prepare_fresh_vtable): Likewise.
-Fri Mar 24 12:11:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Aug 6 11:02:36 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_conditional_expr): Handle pmfs.
- (convert_for_assignment): Fix pmf support.
+ * cvt.c (ocp_convert): After converting to the target type, set
+ LOOKUP_NO_CONVERSION.
- * cvt.c (convert_fn_ptr): Support !flag_vtable_thunks.
- (cp_convert_to_pointer): Handle pmfs.
- (cp_convert): Pass pmfs to cp_convert_to_pointer.
+ * 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 (common_type): Handle inheritance for pmfs.
+Tue Aug 5 15:15:07 1997 Michael Meissner <meissner@cygnus.com>
- * typeck2.c (build_m_component_ref): Do access control.
+ * exception.cc: Declare __terminate_func with noreturn attribute.
- * typeck.c (comp_target_types): Check for conversion to void *
- before checking trickier conversions.
+Fri Aug 1 03:18:15 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (duplicate_decls): Propagate DECL_ABSTRACT_VIRTUAL_P.
+ * parse.y: Break out eat_saved_input, handle errors.
+ (function_try_block): Use compstmt instead of compstmt_or_error.
- * pt.c (push_tinst_level): Complain if template instantiation depth
- is greater than max_tinst_depth.
+Thu Jul 31 17:14:04 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (common_type): Assume that we can call common_type to
- unify the target type of a pointer.
+ * tree.c (build_cplus_new): Don't set TREE_ADDRESSABLE.
-Thu Mar 23 00:48:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Fri Jul 4 01:45:16 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
- * 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.
+ * Make-lang.in (cplib2.txt, cplib2.ready): Instead of checking for
+ existence of cc1plus check whether $(LANGUAGES) contains C++.
- * cvt.c (build_type_conversion): Only give an error if for_sure.
+Wed Jul 30 13:04:21 1997 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
- * typeck.c (comp_target_types): Only support pointer conversions if
- nptrs > 0.
+ * 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.
-Wed Mar 22 19:30:15 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Tue Jul 29 21:17:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_new): Catch use of an initializer list where it
- shouldn't be.
+ * call.c (resolve_args): New fn.
+ (build_new_function_call): Use it.
+ (build_object_call): Likewise.
+ (build_new_method_call): Likewise.
-Wed Mar 22 16:21:07 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Mon Jul 28 16:02:36 1997 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_new): Wrap alloc_expr in an RTL_EXPR if nelts is
- non-constant.
+ * call.c (build_over_call): tsubst all default parms from templates.
- * decl2.c: temp_name_counter is now public.
+Wed Jul 23 13:36:25 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (struct cp_function): Add temp_name_counter field.
+ * decl.c (struct cp_function): Add static_labelno.
(push_cp_function_context): Save it.
(pop_cp_function_context): Restore it.
- * typeck.c (common_type): Handle unifying function types, and unify
- unmatched things to void* with a compiler_error, rather than
- silently like before.
-
-Wed Mar 22 15:10:34 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed Mar 22 15:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_binary_op_nodefault, comparison ops): Update type0
- and type1, since we might have changed op0 or op1.
-
-Wed Mar 22 13:33:45 1995 Jason Merrill <jason@python.cygnus.com>
-
- * typeck.c (common_type): Don't mess up templates.
-
-Wed Mar 22 04:56:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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 *.
-
- * cvt.c (cp_convert_to_pointer): Do access control when converting
- ptms, too.
-
-Tue Mar 21 17:25:06 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * parse.y (extern_lang_string): Catch use of linkage specs that
- aren't all naming the same language.
-
- * class.c (finish_struct): Delete accidental duplicate code.
-
-Tue Mar 21 14:00:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_binary_op_nodefault): Disable pedwarns about
- comparing functions and incomplete types.
+Tue Jul 22 14:43:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * typeck.c (build_component_ref_1): Convert from reference.
-Tue Mar 21 01:26:39 1995 Mike Stump <mrs@cygnus.com>
+Tue Jul 22 11:06:23 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * gc.c (build_generic_desc): Zap the DECL_SIZE so that we can lay it
- out fresh, as the new type may be larger.
+ * parse.y (current_declspecs, prefix_attributes): Initialize to
+ NULL_TREE.
-Mon Mar 20 19:01:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- * 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.
+Sun Jul 20 11:53:07 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * pt.c (uses_template_parms): Handle template first-parse codes.
- * lex.c (check_newline): If we're just changing files (not pushing
- or popping), update input_file_stack->name.
+ * decl.c (cp_finish_decl): Only warn about user-defined statics.
-Mon Mar 20 17:55:04 1995 Mike Stump <mrs@cygnus.com>
+Fri Jul 18 17:56:08 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (type_unification): Only TEMPLATE_DECLs are handled right now
- in the transitive unification code.
+ * pt.c (unify): Handle BOOLEAN_TYPE.
-Mon Mar 20 16:07:50 1995 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.
- * 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.
+Thu Jul 17 18:06:30 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Mar 18 04:03:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- * decl2.c (finish_prevtable_vardecl): Use DECL_DECLARED_STATIC
- rather than DECL_SAVED_INSNS to decide whether or not this method
- was declared inline.
+Thu Jul 17 11:20:17 1997 Benjamin Kosnik <bkoz@rhino.cygnus.com>
- * method.c (synthesize_method): Turn off DECL_INLINE if
- function_cannot_inline_p thinks we're too large.
+ * class.c (finish_struct_methods): add check of warn_ctor_dtor_privacy
+ before "all member functions in class [] are private"
- * typeck.c (build_indirect_ref): Use build_expr_type_conversion.
+Wed Jul 16 23:47:08 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 17 17:47:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (do_scoped_id): convert_from_reference.
+ * init.c (build_offset_ref): Likewise.
- * class.c (instantiate_type): Handle pmfs.
+Wed Jul 16 12:34:29 1997 Benjamin Kosnik <bkoz@lisa.cygnus.com>
- * typeck.c (convert_for_assignment): Check types when assigning one
- pmf to another.
+ * error.c (dump_expr): Check TREE_OPERAND before dump_expr_list.
- * decl.c (define_label): Fix logic for printing out the name of the
- label in an error message.
+Mon Jul 14 03:23:46 1997 Jason Merrill <jason@yorick.cygnus.com>
- * error.c (dump_expr): Support ARRAY_REF.
+ * typeck.c (get_member_function_from_ptrfunc): Promote index
+ before saving it.
-Fri Mar 17 17:43:02 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Sun Jul 13 00:11:52 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_vtable_vardecl): Call build_t_desc here.
- (finish_prevtable_vardecl): Instead of here.
+ * tree.c (layout_basetypes): Move non-virtual destructor warning.
+ * decl.c (xref_basetypes): Remove non-virtual destructor warning.
-Fri Mar 17 14:40:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Sat Jul 12 12:47:12 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * 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.
- * pt.c (unify): Fix unification of return type.
+Fri Jul 11 01:39:50 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * decl.c (build_enumerator): Global enumerators are also readonly.
-Thu Mar 16 22:05:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * rtti.c (build_dynamic_cast_1): Renamed from build_dynamic_cast.
+ (build_dynamic_cast): Call it and convert_from_reference.
- * init.c (build_offset_ref): Call assmble_external on functions.
- * typeck.c (build_component_ref): Ditto.
+ * 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.
-Thu Mar 16 20:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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.
- * 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.
+Wed Jul 9 13:44:12 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Mar 16 19:21:14 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (implicit_conversion): If nothing else works, try binding
+ an rvalue to a reference.
- * pt.c (instantiate_template): Call assemble_external.
+Wed Jul 9 13:04:38 1997 Geoffrey Noer <noer@cygnus.com>
-Thu Mar 16 18:07:54 1995 Brendan Kehoe (brendan@phydeaux.cygnus.com)
+ * decl.c (init_decl_processing): fix Jun 30 patch -- move
+ ifndef for Cygwin32 to include SIGSEGV.
- * 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.
+Thu Jul 3 01:44:05 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Mar 16 13:57:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * class.c (finish_struct_1): Only complain about pointers without
+ copy stuff if there are any constructors.
- * pt.c (unify): Fix array domain unification for 64-bit targets.
+ * rtti.c (build_dynamic_cast): Call complete_type on the types.
- * 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).
+ * decl.c (grokfndecl): If the function we chose doesn't actually
+ match, die.
- * init.c (emit_base_init): Use convert_pointer_to_real instead of
- convert_pointer_to when converting to a direct base.
+ * decl2.c (grokclassfn): Don't specify 'const int' for the
+ artificial destructor parm.
-Wed Mar 15 20:26:29 1995 Mike Stump <mrs@cygnus.com>
+ * pt.c (type_unification): If we are called recursively, nothing
+ decays.
- * pt.c (type_unification): Handle transitive unification better.
+Mon Jun 30 17:53:21 1997 Geoffrey Noer <noer@cygnus.com>
-Wed Mar 15 13:56:16 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- * decl2.c (walk_vtables): Always set prev to vars.
- (mark_vtable_entries): Call assemble_external on the vtable entries.
+Mon Jun 30 14:50:01 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Set the vtable's size to NULL_TREE before
- calling layout_decl, so that it gets updated properly.
+ * tree.c (mapcar, case CALL_EXPR): Handle all the parse node data.
- 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.
+Fri Jun 27 15:18:49 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Mar 14 19:14:19 1995 Doug Evans <dje@chestnut.cygnus.com>
+ * typeck2.c (store_init_value): Always return the value if our
+ type needs constructing.
- * parse.y (setattrs): Chain onto prefix_attributes rather than
- setting it.
+ * method.c (hack_identifier): Convert class statics from
+ reference, too.
-Wed Mar 15 13:00:00 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Jun 26 11:44:46 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushdecl): Check if the type of the VAR_DECL is an
- error_mark_node before trying to read TYPE_LANG_SPECIFIC.
+ * Make-lang.in (cplib2.ready): Add $(LANGUAGES) dependency.
-Mon Mar 13 21:00:28 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Jun 19 16:49:28 1997 Mike Stump <mrs@cygnus.com>
- * decl.c (grokdeclarator, case ARRAY_REF): Wrap the exp with fold,
- and convert the size and integer_one_node to the index type.
+ * typeck.c (c_expand_return): Make sure we clean up temporaries at
+ the end of return x;
-Mon Mar 13 08:01:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Jun 19 12:28:43 1997 Brendan Kehoe <brendan@lisa.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.
-
- * 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".
-
- * decl2.c (finish_file): Also set DECL_STATIC_FUNCTION_P on the
- global init function.
-
- * decl.c (finish_function): Only set DECL_EXTERNAL here if the
- inline function is public.
-
-Sat Mar 11 00:58:03 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * lex.c (check_for_missing_semicolon): Also check for CV_QUALIFIER.
- * init.c (is_friend): Be more careful about checking
- DECL_CLASS_CONTEXT on non-member functions.
-
- * 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.
-
-Fri Mar 10 14:42:29 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (finish_function): If we're not emitting the function yet,
- call assemble_external for it.
-
- * 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.
+Tue Jun 17 18:35:57 1997 Mike Stump <mrs@cygnus.com>
-Thu Mar 9 16:28:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * except.c (expand_builtin_throw): Add support
+ -fno-sjlj-exceptions -fPIC exception handling on the SPARC.
- * 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.
+Mon Jun 16 01:24:37 1997 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (duplicate_tag_error): Use cp_error_at to point out the
- previous definition of the tag.
+ * repo.c (extract_string): Null-terminate.
-Thu Mar 9 10:46:17 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cp-tree.h (TI_SPEC_INFO): New macro.
+ (CLASSTYPE_TI_SPEC_INFO): New macro.
+ * pt.c (push_template_decl): Correctly determine # of template parms
+ for partial specs.
- * 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.
+ * call.c (compare_ics): Really fix 'this' conversions.
-Wed Mar 8 13:31:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (do_decl_instantiation): Don't crash on explicit inst of
+ non-template fn.
- * init.c (member_init_ok_or_else): Check for initializing a static
- member here.
- (emit_base_init): Instead of here.
+ * pt.c (push_template_decl): Complain about mismatch in # of
+ template parms between a class template and a member template.
-Tue Mar 7 16:03:26 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Sun Jun 15 02:38:20 1997 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Disable synthesis as needed.
- * lex.c (cons_up_default_function): Ditto.
+ * 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.
-Tue Mar 7 10:14:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu Jun 12 17:35:28 1997 Jason Merrill <jason@yorick.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.
+ * method.c (synthesize_method): Remove July 30 change to never set
+ DECL_INLINE if at_eof.
-Mon Mar 6 15:07:02 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Jun 12 15:25:08 1997 Mike Stump <mrs@cygnus.com>
- * call.c (build_method_call): Don't synthesize methods outside of a
- function.
+ * xref.c (GNU_xref_member): Ensure that the node has a
+ decl_lang_specific part before checking DECL_FRIEND_P.
- 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.
+Thu Jun 12 12:36:05 1997 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y: Turn -ansi checks back into -pedantic checks.
+ * pt.c (instantiate_class_template): Diagnose non-class types used
+ as bases.
- * init.c (build_new): Fix -fcheck-new for array new.
+Wed Jun 11 17:33:40 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Mar 4 15:55:42 1995 Fergus Henderson <fjh@cs.mu.oz.au>
+ * typeck.c (build_conditional_expr): Use convert_for_initialization
+ instead of convert_and_check.
- * typeck.c (build_compound_expr): warn if left-hand operand of
- comma expression has no side-effects.
+Wed Jun 11 12:31:33 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Fri Mar 3 15:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * parse.y (typespec): Don't pedwarn for typeof.
- * parse.y (primary): Change 'object qualified_id *' rules to 'object
- overqualified_id *'.
+Tue Jun 10 00:22:09 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 3 12:48:17 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * repo.c (finish_repo): Only check changes if we would write a
+ repo file.
- * parse.y (unary_expr): Catch doing sizeof an overloaded function.
- Make the error look the same as the one we issue in c_sizeof.
+ * call.c (compare_ics): Fix handling of 'this' conversions.
- * typeck.c (build_binary_op_nodefault): Give an error for trying
- to compare a pointer-to-member to `void *'.
+ * pt.c (do_decl_instantiation): Support static data too. Rename
+ from do_function_instantiation.
+ * cp-tree.h: Adjust.
+ * parse.y: Adjust.
-Fri Mar 3 11:28:50 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * repo.c (extract_string): New fn.
+ (get_base_filename): Use it.
+ (init_repo): Compare old args with current args.
- * 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.
+Mon Jun 9 14:25:30 1997 Mike Stump <mrs@cygnus.com>
-Fri Mar 3 00:08:10 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * Makefile.in, Make-lang.in: Protect C-ls with a comment
+ character, idea from Paul Eggert <eggert@twinsun.com>.
- * decl.c (grokparms): Catch a PARM_DECL being used for a default
- argument as well.
+Mon Jun 9 01:52:03 1997 Jason Merrill <jason@yorick.cygnus.com>
-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 <jason@phydeaux.cygnus.com>
-
- * decl.c (finish_function): Change test for calling
- mark_inline_for_output.
-
-Wed Mar 1 11:23:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_modify_expr): Complain if
- build_default_binary_type_conversion fails.
-
- * init.c (expand_default_init): Handle arguments of unknown type
- properly.
+ * typeck.c (c_expand_return): Be more persistent in looking for
+ returned temps.
- * cvt.c (build_expr_type_conversion): Only complain about ambiguity
- if 'complain'.
- * various: Pass 'complain'.
+ * cvt.c (build_up_reference): Use NOP_EXPR for switching from
+ pointer to reference.
- * typeck.c (comptypes): Be more picky about comparing UPTs.
+ * class.c (build_vbase_path): Don't do anything if PATH has no steps.
-Wed Mar 1 11:03:41 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Sun Jun 8 03:07:05 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): If declarator is null, say that the
- type used has an incomplete type.
+ * init.c (build_member_call, build_offset_ref):
+ Use do_scoped_id instead of do_identifier.
-Wed Mar 1 10:06:20 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * cvt.c (convert): Remove bogosity.
- * 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.
+Sat Jun 7 20:50:17 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * tree.c (make_deep_copy): Support copying INTEGER_TYPEs (assuming
- they are array domain types).
+ * cvt.c (build_up_reference): Do checks of ARGTYPE and
+ TARGET_TYPE before trying to use get_binfo.
-Tue Feb 28 23:24:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Fri Jun 6 17:36:39 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * cvt.c (build_up_reference): Call get_binfo to get access control.
-Tue Feb 28 19:57:31 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl2.c (import_export_decl): If we don't support weaks, leave
+ statics undefined.
- * decl.c (grokdeclarator): Don't allow decl of an argument as `void'.
+Fri Jun 6 15:55:49 1997 Mike Stump <mrs@cygnus.com>
-Tue Feb 28 17:23:36 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * except.c (expand_builtin_throw): Add support for machines that
+ cannot access globals after throw's epilogue when
+ -fno-sjlj-exceptions is used.
- * parse.y (typed_declspecs1): Add 'typespec reserved_typespecquals
- reserved_declspecs' rule.
+Thu Jun 5 16:28:43 1997 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (expr_or_declarator): Remove notype_qualified_id rule.
- (direct_notype_declarator): Ditto.
- (complex_direct_notype_declarator): Add notype_qualified_id rule.
+ * 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.
- * lex.c (real_yylex): Handle :> digraph properly.
+Tue Jun 3 18:08:23 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Feb 28 12:26:29 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * search.c (push_class_decls): A name which ambiguously refers to
+ several instantiations of the same template just refers to the
+ template.
- * 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 Jun 3 12:30:40 1997 Benjamin Kosnik <bkoz@cirdan.cygnus.com>
-Tue Feb 28 00:08:01 1995 Jason Merrill <jason@phydeaux.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).
- * 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.
+Mon Jun 2 17:40:56 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (uses_template_parms): Handle pmfs.
+ * typeck.c (build_component_ref): Only call mark_used on a decl.
- * decl.c (grokdeclarator): Don't call variable_size for array bounds
- that only depend on template constant parameters.
+Thu May 29 15:54:17 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Feb 27 15:38:16 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * typeck.c (build_c_cast): Make the check for a ptr to function
+ more specific before possible default_conversion call.
- * error.c (dump_decl): Only look to see if it's a vtable if we
- actually have a name to check out.
+Thu May 29 13:02:06 1997 Mike Stump <mrs@cygnus.com>
-Mon Feb 27 13:37:53 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- * cvt.c (convert_to_aggr): Lose misleading shortcut.
+Wed May 28 17:08:03 1997 Mike Stump <mrs@cygnus.com>
-Sun Feb 26 17:27:32 1995 Doug Evans <dje@canuck.cygnus.com>
+ * except.c (init_exception_processing): Mark terminate as not
+ returning so that the optimizer can optimize better.
- * decl.c (set_nested_typename): Always set DECL_IGNORED_P,
- not just for dwarf.
+Tue May 27 19:49:19 1997 Mike Stump <mrs@cygnus.com>
-Sun Feb 26 00:10:18 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * cvt.c (convert): Don't do any extra work, if we can avoid it
+ easily.
- * decl.c (grokdeclarator): Don't allow a static member to be
- declared `register'.
+Tue May 27 18:21:47 1997 Mike Stump <mrs@cygnus.com>
- * init.c (make_friend_class): Move up to a pedwarn for the warning
- about a class declaring friends with itself.
+ * *.[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.
- * 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.
+Fri May 23 10:58:31 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Feb 25 22:32:03 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * lang-specs.h: Define __EXCEPTIONS if exceptions are enabled.
+ Lose -traditional support.
- * decl.c (grokdeclarator): Don't allow initialization of a
- non-virtual function.
+Thu May 22 15:41:28 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_function): Do a pedwarn if we're changing `main'
- to have an int return type.
+ * rtti.c (get_tinfo_var): Use TYPE_PRECISION (sizetype).
-Sat Feb 25 00:02:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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_modify_expr): Handle simple assignment from
- TARGET_EXPRs by building up an RTL_EXPR to force expansion. Whew.
+ * 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.
-Fri Feb 24 18:27:14 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
+Wed May 21 18:24:19 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Also don't allow virtual outside of a
- class decl for a scope method definition performed at global binding.
+ * pt.c (instantiate_class_template): TYPE_VALUES for an enum
+ doesn't refer to the CONST_DECLs.
- * init.c (build_offset_ref): Don't allow creation of an OFFSET_REF
- of a bitfield.
+Tue May 20 21:09:32 1997 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (grokdeclarator): Don't allow a const to be declared mutable.
+ * rtti.c (get_tinfo_var): Either INT_TYPE_SIZE or 32, whichever
+ is bigger.
+ (expand_class_desc): Convert the last argument to a sizetype.
- * 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.
-
- * typeck.c (build_unary_op): Forbid using postfix -- on a bool.
-
- * decl.c (grokdeclarator): Allow `signed' and `unsigned' to be
- used on `__wchar_t'.
-
-Fri Feb 24 13:59:53 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c (end_protect_partials): Do it the right way.
-
-Wed Feb 22 15:42:56 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_binary_op_nodefault): Upgrade warning about
- comparing distinct pointer types to pedwarn.
-
- * typeck2.c (digest_init): Cope with extra braces.
-
- * typeck.c (build_binary_op_nodefault): Use tree_int_cst_sgn instead
- of INT_CST_LT (..., interger_zero_node).
-
-Wed Feb 22 14:45:52 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * except.c [!TRY_NEW_EH] (end_protect_partials): Define dummy
- function for systems that don't have EH.
-
-Tue Feb 21 19:18:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (can_convert_arg): Like can_convert, but takes an arg as
- well.
-
- * pt.c (type_unification): Allow implicit conversions for parameters
- that do not depend on template parameters.
-
-Tue Feb 21 18:43:48 1995 Douglas Rupp (drupp@cs.washington.edu)
-
- * 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.
-
-Tue Feb 21 18:36:55 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
+Tue May 20 13:55:57 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Feb 21 16:05:59 1995 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * 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.
-
-Tue Feb 21 01:53:18 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (duplicate_decls): Always lay out the merged decl.
-
- * decl2.c (finish_vtable_vardecl): Don't do vtable hack on templates.
- (finish_prevtable_vardecl): Ditto.
-
- * method.c (synthesize_method): Set interface_{unknown,only}
- according to the settings for our class, not the file where it comes
- from.
-
-Sat Feb 18 12:26:48 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c: Handle systems that define __i386__ but not __i386.
-
-Fri Feb 17 15:31:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl2.c (reparse_decl_as_expr): Support being called without a
- type argument.
-
- * parse.y (primary): Add '(' expr_or_declarator ')'. Adds 4 r/r
- conflicts. Sigh.
-
-Fri Feb 17 12:02:06 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Fri Feb 17 01:54:46 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * init.c (build_new): Set TREE_NO_UNUSED_WARNING on COMPOUND_EXPRs
- built for news of scalar types.
-
-Thu Feb 16 17:48:28 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * typeck.c (build_unary_op, ADDR_EXPR): Lose bogus special case for
- PRE*CREMENT_EXPR.
-
- * 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.
-
- * decl2.c (import_export_vtable): Use and set DECL_INTERFACE_KNOWN.
-
- * cp-tree.h (DECL_INTERFACE_KNOWN): Use DECL_LANG_FLAG_5.
-
- * init.c (expand_virtual_init): Always call assemble_external.
-
- * 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.
-
-Thu Feb 16 03:28:49 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * class.c (finish_struct): Use TYPE_{MIN,MAX}_VALUE to determine
- whether an enumerated type fits in a bitfield.
-
-Wed Feb 15 15:38:12 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * class.c (grow_method): Update method_vec after growing the class
- obstack.
-
-Wed Feb 15 13:42:59 1995 Mike Stump <mrs@cygnus.com>
-
- * parse.y (handler_seq): Push a level for the catch parameters.
-
-Wed Feb 15 12:42:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * init.c (emit_base_init): Update BINFO_INHERITANCE_CHAIN on my
- bases, in case they've been clobbered.
-
-Wed Feb 15 12:07:29 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
- * cp-tree.h (copy_binfo): Removed, unused.
- * tree.c (copy_binfo): Ditto.
-
-Wed Feb 15 00:05:30 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * init.c (build_new): Save the allocation before calling
- expand_vec_init on it.
-
- * 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.
-
-Tue Feb 14 15:31:25 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Tue Feb 14 02:15:43 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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?
-
- * decl.c (grokparms): Fine, just don't call
- convert_for_initialization at all. OK? Happy now?
-
-Mon Feb 13 02:23:44 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * cp-tree.h (CLASSTYPE_FIRST_CONVERSION): Make sure that the class
- method vector has a second element before returning it.
-
- * decl.c (grokparms): Don't strip REFERENCE_TYPE before calling
- convert_for_initialization.
-
-Sun Feb 12 03:57:06 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_modify_expr): Compare function name to
- constructor_name (current_class_type) instead of current_class_name.
-
- * decl.c (grokparms): Don't do anything with the return value of
- convert_for_initialization.
-
- * error.c (dump_decl): Also dump_readonly_or_volatile on the decl.
-
- * decl.c (duplicate_decls): Tweak error message.
-
- * typeck.c (build_const_cast): Implement checking.
- (build_reinterpret_cast): Implement some checking.
-
- * 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.
-
-Fri Feb 10 16:18:52 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (build_c_cast): Use non_lvalue to tack something on
- where necessary.
-
- * decl.c (auto_function): Now a function.
- * except.c (init_exception_processing): terminate, unexpected,
- set_terminate, and set_unexpected have C++ linkage.
-
- * 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.
-
- * except.c (expand_throw): Don't call convert_to_reference.
- Pass the correct parameters to build_new.
-
- * method.c (do_build_assign_ref): Don't use access control when
- converting to a base reference here.
- (do_build_copy_constructor): Or here.
-
- * init.c (build_new): Unset TREE_READONLY on the dereferenced
- pointer before assigning to it.
-
- * decl.c (maybe_build_cleanup): Don't bother stripping const here.
-
- * decl2.c (delete_sanity): You can now delete pointer to const.
-
-Fri Feb 10 13:28:38 1995 Jason Merrill <jason@python.cygnus.com>
-
- * decl.c (finish_function): Don't rely on actual parameters being
- evaluated left-to-right.
- * except.c (expand_end_catch_block): Ditto.
-
-Fri Feb 10 00:52:04 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * cvt.c (build_type_conversion_1): Don't call convert on aggregate
+ * 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.
- (convert_to_reference): Fix erroneous text substitution.
-
- * typeck2.c (initializer_constant_valid_p): Update from C frontend.
- Add new argument to all callers.
-
- * typeck.c (convert_arguments): Check for error_mark_node before
- trying to do anything with the actual parameter.
-
- * 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.
-
- * parse.y (conditions): Call condition_conversion rather than
- building up a CLEANUP_POINT_EXPR.
-
- * pt.c (end_template_decl): Don't warn_if_unknown_interface here
- under -falt-external-templates.
-
-Thu Feb 9 05:24:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * init.c (build_new): Complain about new of const type without
- initializer. Other cleanup.
-
- * 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.
-
- * cvt.c (build_type_conversion_1): There will never be any need to
- dereference references here now.
-
-Thu Feb 9 00:37:47 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c (expand_builtin_throw): Make sure we only `use' the
- value of return_val_rtx.
-
-Wed Feb 8 15:45:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * parse.y (structsp): Don't complain about declaring a type being
- defined to be a friend.
-
- * 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.
-
- * decl.c (set_nested_typename): Set IDENTIFIER_TYPE_VALUE on the
- nested name again, to make local classes work a bit better.
-
- * typeck.c (build_function_call_real): Dereference reference after
- checking for incomplete type.
-
- * init.c (build_new): Accept new of const and volatile types.
-
-Wed Feb 8 14:04:16 1995 Jason Merrill <jason@deneb.cygnus.com>
-
- * decl.c (grokdeclarator): Fix error message.
-
-Wed Feb 8 03:16:15 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (convert_for_initialization): Do bash arrays when
- converting to a reference to non-array.
-
-Tue Feb 7 15:50:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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 (build_method_call): Don't build up a reference to the
- parameter here; let build_overload_call handle that.
-
- * 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.
-
- * call.c (build_method_call): Dereference a returned reference.
- * typeck.c (build_function_call_real): Ditto.
-
- * decl.c (xref_basetypes): Check for unions with basetypes here.
- (xref_tag): Instead of here.
-
- * pt.c (process_template_parm): Template type parm decls are
- artificial.
-
-Mon Feb 6 04:32:09 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * decl2.c (grokfield): Call pushdecl_class_level after setting the
- TYPE_NAME, not before.
-
-Sun Feb 5 02:50:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (convert_harshness): Don't call sorry here. Don't allow
- conversions between function pointer types if pedantic.
-
- * pt.c (overload_template_name): Pass globalize=1 to xref_tag.
-
- * lex.c (cons_up_default_function): Use the full name for the return
- type of op=.
-
- * 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.
-
- * cp-tree.h (TYPE_INCOMPLETE): New macro; TEMPLATE_TYPE_PARMs are
- not considered incomplete even though their definition is unknown.
-
- * 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.
-
- * 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.
-
- * pt.c (push_template_decls): Template parm decls are artificial.
-
- * decl.c (duplicate_decls): Restore check for qualifier
- disagreement for non-functions.
- (decls_match): Remove check for qualifier disagreement.
-
-Fri Feb 3 14:58:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (grok_reference_init): Convert initializer from
- reference.
- * typeck.c (convert_for_initialization): Ditto.
-
- * decl.c (duplicate_decls): Propagate DECL_NESTED_TYPENAME.
-
- * 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.
-
-Thu Feb 2 15:07:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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_c_cast): Don't strip NOPs if we're converting to a
- reference type.
-
- * parse.y (structsp): Put back error for 'struct B: public A;'.
-
-Wed Feb 1 23:02:06 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c: Add support for mips systems that don't define __mips
- but do define mips, like Ultrix.
-
-Wed Feb 1 22:39:07 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c: Add support for exception handling on the Alpha.
-
-Wed Feb 1 10:12:14 1995 Mike Stump <mrs@cygnus.com>
-
- * decl2.c (finish_file): Fix bug in Jan 31st change.
-
-Tue Jan 31 16:59:15 1995 Gerald Baumgartner (gb@lorenzo.cs.purdue.edu)
-
- * 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 <mrs@cygnus.com>
-
- * 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 <typeinfo.h>.
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * call.c (build_method_call): Fix -fthis-is-variable for 32-bit
- targets, too.
-
-Tue Jan 31 00:11:04 1995 Mike Stump <mrs@cygnus.com>
-
- * 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 <jason@phydeaux.cygnus.com>
-
- * 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.
-
- * init.c (build_new): Fix -fthis-is-variable support.
- * call.c (build_method_call): Ditto.
-
- * call.c (convert_harshness): Make conversion from a pointer to bool
- worse than conversion to another pointer.
-
-Sat Jan 28 16:46:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * init.c (build_new): Check new return value if -fcheck-new.
-
- * lex.c (check_newline): Clear end_of_file when we're done, too.
-
-Sat Jan 28 10:38:39 1995 Mike Stump <mrs@cygnus.com>
-
- * decl2.c (finish_vtable_vardecl): Make rtti TD tables follow
- vtables whereever they go.
-
- * gc.c (build_t_desc): Remove old way of setting it up, as it wasn't
- right.
-
-Sat Jan 28 09:10:44 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Sat Jan 28 04:57:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (grokdeclarator): Discard the template parameters in a
- template constructor declaration so that the function is always
- named constructor_name (ctype).
-
- * lex.c (check_newline): Use ungetc to put back the character before
- calling HANDLE_PRAGMA.
-
-Fri Jan 27 17:23:47 1995 Mike Stump <mrs@cygnus.com>
-
- * decl2.c (check_classfn): If the cname is T<int> and fn_name is T,
- make sure we still match them.
-
-Fri Jan 27 16:32:10 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * parse.y: Add END_OF_LINE token.
-
- * 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.
-
- * 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.
-
-Thu Jan 26 19:26:34 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Thu Jan 26 19:20:00 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c (init_exception_processing): Don't use r12 on the rs6000.
-
-Tue Jan 24 16:36:31 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (grokparms): Don't try to build up a reference at this point.
-
- * typeck2.c (build_functional_cast): Don't assume that a NOP_EXPR
- will suffice to convert from integer_zero_node.
-
-Wed Jan 25 15:02:09 1995 David S. Miller (davem@nadzieja.rutgers.edu)
-
- * class.c (instantiate_type): Change error message text.
- * typeck2.c (store_init_value): Likewise.
-
-Mon Jan 23 21:57:14 1995 Mike Stump <mrs@cygnus.com>
-
- * pt.c (tsubst): When we copy a node, don't forget to copy
- TREE_CHAIN, we use it later.
-
-Mon Jan 23 03:33:47 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck.c (convert_for_assignment): Initialize variable before use.
-
-Fri Jan 20 01:17:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Thu Jan 19 15:43:11 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (build_method_call): Don't mess with 'this' before calling
- compute_conversion_costs.
-
-Wed Jan 18 15:40:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * search.c (get_matching_virtual): Give line number for previous
- declaration.
-
- * call.c (convert_harshness): Handle conversions to references
- better.
-
- * cvt.c (build_up_reference): OK, handle {MIN,MAX}_EXPR *properly*.
-
-Wed Jan 18 15:21:38 1995 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed Jan 18 14:26:59 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * tree.c (lvalue_p): Handle {MIN,MAX}_EXPR.
-
- * decl2.c (lang_decode_option): -Wall implies -Wparentheses.
- warn_parentheses defaults to 0.
-
- * decl.c (grokparms): Put back call to require_instantiated_type.
-
-Tue Jan 17 19:56:15 1995 Mike Stump <mrs@cygnus.com>
-
- * except.c (exception_section): Use the data section on the rs6000.
- Change calling convention for named_section.
-
-Wed Jan 17 18:20:57 1994 Fergus Henderson <fjh@munta.cs.mu.oz.au>
-
- * cp-tree.h : Make if (x=0) warn with wall
- * parse.y : Make if (x=0) warn with wall
-
-Tue Jan 17 14:12:00 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (BOOL_TYPE_SIZE): BITS_PER_WORD if SLOW_BYTE_ACCESS,
- BITS_PER_UNIT otherwise.
-
- * search.c (get_matching_virtual): Don't check the binfo if the
- types are the same.
-
- * cvt.c (cp_convert): Just call truthvalue_conversion to convert to
- bool.
-
-Mon Jan 16 13:28:48 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * various: Use boolean_type_node, boolean_true_node,
- boolean_false_node.
-
- * search.c (get_matching_virtual): Allow covariant returns that
- don't require pointer adjustment.
-
- * typeck.c (build_conditional_expr): Don't call default_conversion
- on ifexp.
-
- * cvt.c (build_up_reference): Handle MIN_EXPR and MAX_EXPR.
-
- * decl.c (grokdeclarator): Upgrade warning about &const to pedwarn.
-
-Sun Jan 15 22:17:32 1995 dcb@lovat.fmrco.COM (David Binderman)
-
- * pt.c (do_function_instantiation): Free targs once we're done.
-
-Sun Jan 15 22:17:32 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (BOOL_TYPE_SIZE): Defaults to BITS_PER_WORD.
- (init_decl_processing): Use BOOL_TYPE_SIZE instead of CHAR_TYPE_SIZE
- for bool.
-
-Sat Jan 14 05:33:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Fri Jan 13 14:42:55 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (duplicate_decls): Propagate DECL_STATIC_{CON,DE}STRUCTOR.
- (finish_function): Handle DECL_STATIC_{CON,DE}STRUCTOR.
- (finish_function): Trust rest_of_compilation.
-
- * decl2.c (finish_file): Also call functions designated as static
- constructors/destructors.
-
- * 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.
-
- * lex.c (real_yylex): Downgrade complaint about the escape sequence
- being too large from pedwarn to warning.
-
- * decl.c (grokdeclarator): Don't complain about long long in system
- headers.
-
- * lex.c (real_yylex): Handle digraphs.
-
-Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * decl.c (init_decl_processing): -f{no-,}strict-prototype only
- affects C linkage declarations now.
-
- * typeck.c (comp_target_types): Grok simple contravariant conversions.
- (common_type): t1 and t2 are interchangeable.
-
- * 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).
-
- (common_type): Prefer long double to double even when
- they have the same precision.
-
- * decl.c (grokparms): Call convert_for_initialization to check
- default arguments.
-
- * init.c (build_new): void_type_node has a size (of 0).
-
- * 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.
-
- * search.c (dfs_pushdecls): Ditto.
-
- * decl2.c (finish_file): Don't second-guess self-initialization.
+ (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 <jason@yorick.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * pt.c (instantiate_class_template): Oops.
+
+Fri May 16 14:23:57 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
- * cvt.c (convert_to_reference): Work with expr directly, rather than
- a copy.
+ * pt.c (tsubst_copy): Handle BIT_NOT_EXPR.
- * decl.c (push_overloaded_decl): Only shadow artificial TYPE_DECLs.
+Wed May 7 11:17:59 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * init.c (add_friend): Downgrade duplicate friend message from
- pedwarn to warning.
+ * method.c (emit_thunk) [ASM_OUTPUT_MI_THUNK]: Build up the RTL
+ for THUNK_FNDECL before we switch to temporary allocation.
- * decl.c (duplicate_decls): Push obstacks before calling common_type.
+Mon May 5 14:46:53 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jan 12 17:15:21 1995 Michael Ben-Gershon <mybg@cs.huji.ac.il>
+ * call.c (build_new_op): Handle null arg2 for ?:.
- * 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 May 1 18:26:37 1997 Mike Stump <mrs@cygnus.com>
-Thu Jan 12 12:17:24 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * 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.
- (complete_array_type): Copy code from C frontend.
+Tue Apr 29 15:38:54 1997 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (real_yylex): Don't multiply the length of a wide string
- literal by WCHAR_BYTES.
+ * init.c (build_new): Fix nothrow handling.
- * 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.
+Tue Apr 29 14:29:50 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (unary_complex_lvalue): Also wrap prefix -- and ++ in
- COMPOUND_EXPRs.
- (build_unary_op): Wrap unary plus in a NON_LVALUE_EXPR.
+ * init.c (emit_base_init): Don't warn about the initialization
+ list for an artificial member.
- * lex.c (real_yylex): Don't skip whitespace when reading the next
- character after ->.
+Fri Apr 25 17:47:59 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Jan 11 16:32:49 1995 Mike Stump <mrs@cygnus.com>
+ * expr.c (do_case): Handle !START case for the error msg.
- * 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.
+Fri Apr 25 11:55:23 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jan 11 01:05:42 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl2.c, lang-options.h: New option -Weffc++.
+ * class.c, decl.c, init.c, typeck.c: Move Effective C++ warnings
+ to -Weffc++.
- * decl.c (pushtag): Only look for a previous decl in the current
- binding level. Use explicit global scope in DECL_NESTED_TYPENAME.
+ * decl2.c (finish_prevtable_vardecl): Change NO_LINKAGE_HEURISTICS
+ to MULTIPLE_SYMBOL_SPACES.
- * gxx.gperf: Add __signature__ and __sigof__ keywords.
+Wed Apr 23 18:06:50 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (lang_decode_option): -ansi does not set flag_no_asm. It
- does set flag_no_gnu_keywords and flag_operator_names.
+ * method.c (emit_thunk, generic case): Set current_function_is_thunk.
- * 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'.
+ * method.c (emit_thunk, macro case): Set up DECL_RESULT.
- * decl.c (lookup_name_real): The got_object special lookup only
- applies to types.
+ * 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.
-Tue Jan 10 18:07:51 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Apr 23 14:43:06 1997 Mike Stump <mrs@cygnus.com>
- * spew.c (yylex): Also use DECL_NESTED_TYPENAME if got_object is set.
+ * 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.
- * parse.y (primary): Unset got_object after all rules that use the
- 'object' nonterminal.
- (object): Set got_object.
+ * 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.
- * lex.h: Declare got_object.
+ * decl.c (maybe_build_cleanup_1): We no longer have to unsave, as
+ we know it will be done later by the backend.
- * decl.c (lookup_name_real): Also lookup names in the context of an
- object specified.
+ * decl2.c (lang_f_options): Remove support for short temps.
+ * lang-options.h: Likewise.
+
+Wed Apr 23 04:12:06 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Jan 10 14:30:30 1995 Mike Stump <mrs@cygnus.com>
+ * tree.c (varargs_function_p): New fn.
+ * method.c (emit_thunk): Replace broken generic code with code to
+ generate a heavyweight thunk function.
- * 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.
+Tue Apr 22 02:45:18 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Jan 10 01:49:25 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (process_template_parm): pedwarn about floating-point parms.
- * decl.c (pushtag): Stick the new decl in TYPE_NAME before pushing
- it.
+ * decl.c (grokdeclarator): inline no longer implies static.
- * 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.
+ * spew.c (yylex): Always return the TYPE_DECL if we got a scope.
- * 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'.
+Mon Apr 21 15:42:27 1997 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (lookup_field): Don't return a TYPE_DECL if there is a
- function alternative and want_type is not set.
+ * class.c (check_for_override): The signature of an overriding
+ function is not changed.
-Mon Jan 9 18:16:23 1995 Jason Merrill <jason@phydeaux.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.
- * 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.
+Sun Apr 20 16:24:29 1997 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (lookup_field): Handle want_type properly in the presence
- of fields with the same name.
+ * call.c (build_user_type_conversion_1): Really ignore rvalue
+ conversions when looking for a REFERENCE_TYPE.
- * 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.
+ * 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.
-Mon Jan 9 16:48:16 1995 Steve Chamberlain (sac@jonny.cygnus.com)
+Fri Apr 18 12:11:33 1997 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (pointer_int_sum): Use offset size when calculating
- index expression.
+ * 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.
-Mon Jan 9 03:44:33 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Thu Apr 17 14:37:22 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * inc/typeinfo (type_info::before): Add cv-qualifier-seq.
+ * tinfo2.cc (type_info::before): Likewise.
- * spew.c (yylex): Decrement looking_for_typename after we see a
- _DEFN.
+Mon Apr 14 12:38:17 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushdecl): Don't install an artificial TYPE_DECL in
- IDENTIFIER_LOCAL_VALUE if we already have a decl with that name.
+ * call.c (implicit_conversion): Oops.
- * typeck.c (convert_for_assignment): Converting pointers to bool
- does not need a cast.
+Fri Apr 11 02:18:30 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sun Jan 8 18:16:45 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * call.c (implicit_conversion): Try to find a reference conversion
+ before binding a const reference to a temporary.
- * class.c (instantiate_type): Initialize nsubsts parm.
+Wed Apr 2 12:51:36 1997 Mike Stump <mrs@cygnus.com>
- * pt.c (do_function_instantiation): Ditto.
+ * exception.cc (__default_unexpected): Call terminate by default,
+ so that if the user overrides terminate, the correct function will
+ be called.
+
+Wed Mar 19 14:14:45 1997 Mike Stump <mrs@cygnus.com>
-Sat Jan 7 14:37:05 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * parse.y (left_curly): Avoid trying to use any fields of
+ error_mark_node, as there aren't any.
- * 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.
+Thu Mar 13 16:33:22 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * lex.c (do_identifier): Avoid breaking on overloaded methods
+ as default arguments.
-Fri Jan 6 14:10:57 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Mar 12 13:55:10 1997 Hans-Peter Nilsson <Hans-Peter.Nilsson@axis.se>
- * 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.
+ * call.c (add_template_candidate): Initialize the variable "dummy".
- * class.c (finish_struct_methods): Still set
- TYPE_HAS_{INT,REAL}_CONVERSION.
+Mon Mar 10 15:13:14 1997 Brendan Kehoe <brendan@canuck.cygnus.com>
- * call.c (can_convert): Don't use aggregate initialization.
+ * 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.
- * cp-tree.h: Declare lookup_conversions.
+Fri Mar 7 13:19:36 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Jan 5 21:08:00 1995 Mike Stump <mrs@cygnus.com>
+ * cp-tree.h (comp_ptr_ttypes, more_specialized): Add decl.
+ (debug_binfo): Delete decl, not needed.
- * parse.y (simple_stmt): Fix duplicate case value error messages to
- be more readable.
+ * 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 Jan 4 16:44:19 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (pending_invalid_xref{,_file,_line}): Delete unused vars.
- * cvt.c (build_type_conversion): Total rewrite to use
- convert_harshness instead of reproducing conversion logic here. Now
- much shorter.
+ * friend.c (is_friend_type): Delete fn.
+ * cp-tree.h (is_friend_type): Delete decl.
- * call.c (convert_harshness): Support conversions to bool.
- (can_convert): Checks whether a conversion is less harsh
- than USER_CODE, for build_type_conversion.
+ * 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.
- * 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.
+ * decl.c (push_overloaded_decl{,_top_level}): Make static, adding
+ fwd decls.
+ * cp-tree.h (push_overloaded_decl{,_top_level}): Delete decls.
- * cp-tree.h: Lose CLASSTYPE_CONVERSIONS hackery.
- (CLASSTYPE_FIRST_CONVERSION): Points to elt 1 of CLASSTYPE_METHOD_VEC.
+ * decl.c (pushdecl_nonclass_level): #if 0, unused.
+ * cp-tree.h (pushdecl_nonclass_level): #if 0 decl.
- * 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?
+ * lex.c (reinit_lang_specific): #if 0, unused.
+ * cp-tree.h (reinit_lang_specific): #if 0 decl.
-Mon Jan 2 14:42:58 1995 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (revert_static_member_fn): Make static, adding fwd decl.
+ * cp-tree.h (revert_static_member_fn): Delete decl.
- * call.c (build_method_call): Lose another misleading shortcut.
+ * class.c (root_lang_context_p): Delete fn.
+ * cp-tree.h (root_lang_context_p): Delete decl.
-Fri Dec 30 17:57:30 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (set_current_level_tags_transparency): #if 0, unused.
+ * cp-tree.h (set_current_level_tags_transparency): #if 0 decl.
- * gc.c (build_bltn_desc): Handle bool as a built-in type.
+ * lex.c (set_vardecl_interface_info): Make static.
+ * cp-tree.h (set_vardecl_interface_info): Delete decl.
-Fri Dec 30 14:20:21 1994 Mike Stump <mrs@cygnus.com>
+ * call.c (find_scoped_type): Make static.
+ * cp-tree.h (find_scoped_type): Delete decl.
- * tree.c (layout_vbasetypes): Ensure that we don't loose alignment
- on the complete type because of small virtual bases.
+ * search.c (convert_pointer_to_vbase): Make static.
+ * cp-tree.h (convert_pointer_to_vbase): Delete decl.
-Fri Dec 30 12:22:29 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (const_ptr_type_node): Likewise.
+ * cp-tree.h (const_ptr_type_node): Delete decl.
- * 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.
+ * typeck.c (common_base_type): Make static.
+ * cp-tree.h (common_base_types): Delete erroneous decl.
-Thu Dec 29 18:20:57 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (classtype_mangled_name): Make static.
+ * cp-tree.h (classtype_mangled_name): Delete decl.
- * pt.c (tsubst): Fix problem with defining constructors in templated
- classes with virtual bases.
+ * lex.c (check_newline): Make static.
+ * cp-tree.h (check_newline): Delete decl.
-Wed Dec 28 08:31:00 1994 Mike Stump <mrs@cygnus.com>
+ * typeck.c (build_x_array_ref): Delete fn, same idea as
+ grok_array_decl.
+ * cp-tree.h (build_x_array_ref): Delete decl.
- * parse.y (TYPEID): Strip top-level cv-qualifiers on typeid
- expressions.
- * gc.c (build_typeid): Ditto.
+ * 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 Dec 22 17:26:33 1994 Mike Stump <mrs@cygnus.com>
+ * class.c (build_vtable_entry): Make static.
+ * cp-tree.h (build_vtable_entry): Delete decl.
- * cvt.c (build_up_reference): Fix breakage introduced on Nov 29,
- don't assert on complex AGGR inits.
+ * class.c (build_vbase_pointer): Make static.
+ * cp-tree.h (build_vbase_pointer): Delete decl.
-Thu Dec 22 14:32:31 1994 Mike Stump <mrs@cygnus.com>
+ * sig.c (build_sptr_ref): Add forward decl and make static.
+ * cp-tree.h (build_sptr_ref): Delete decl.
- * method.c (build_overload_value): Handle pointer to members as
- template arguments.
+ * call.c (build_new_method_call): Add forward decl and make static.
+ * cp-tree.h (build_new_method_call): Delete decl.
-Thu Dec 22 13:09:07 1994 Mike Stump <mrs@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.
- * 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.
+ * init.c (build_builtin_call): Make static.
+ * cp-tree.h (build_builtin_call): Delete decl.
-Thu Dec 22 10:04:19 1994 Mike Stump <mrs@cygnus.com>
+ * typeck.c (binary_op_error): Delete decl.
+ * cp-tree.h (binary_op_error): Likewise.
- * decl.c (grokdeclarator): Use the typedef name for linkage if the
- type doesn't otherwise have a name.
+Thu Mar 6 16:13:52 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl2.c (grokfield): 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.
- * 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.
+ * typeck.c (build_c_cast): Don't decl TYPE as register tree.
-Wed Dec 21 11:07:05 1994 Mike Stump <mrs@cygnus.com>
+Sun Mar 2 02:54:36 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * decl2.c (check_classfn): Ignore this parameter on static functions
- when checking to see if we match.
+ * pt.c (unify): Strip NOP_EXPR wrappers before unifying integer values.
-Tue Dec 20 17:47:02 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (coerce_template_parms): Add new error message.
- * typeck.c (unary_complex_lvalue): Handle address of non-left most
- pointers to members by calling get_delta_difference.
+ * method.c (build_overload_value): Implement name mangling for
+ floating-point template arguments.
-Mon Dec 19 22:40:53 1994 Mike Stump <mrs@cygnus.com>
+ * method.c (build_overload_int, icat, dicat): Fix mangling of template
+ arguments whose absolute value doesn't fit in a signed word.
- * decl2.c (check_classfn): Don't use decls_match yet, as it modifies
- static functions to early.
+Mon Mar 3 12:14:54 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Dec 19 22:37:48 1994 Mike Stump <mrs@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.
- * method.c (make_thunk): Handle encoding of positive thunk offsets.
+Sun Mar 2 11:04:43 1997 Jason Merrill <jason@yorick.cygnus.com>
-Sat Dec 17 13:29:50 1994 Doug Evans <dje@canuck.cygnus.com>
+ * call.c (build_scoped_method_call): Complain if the scope isn't a
+ base.
- * Make-lang.in (.PHONY): Tell GNU make C++ and c++ are phony targets.
+Wed Feb 26 11:31:06 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Dec 15 16:32:12 1994 Mike Stump <mrs@cygnus.com>
+ * parse.y (left_curly): Don't crash on erroneous type.
- * 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.
+ * init.c (build_delete): Fix type of ref.
-Thu Dec 15 15:17:55 1994 Mike Stump <mrs@cygnus.com>
+Tue Feb 25 12:41:48 1997 Jason Merrill <jason@yorick.cygnus.com>
- * *.[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.
+ * search.c (get_vbase_1): Renamed from get_vbase.
+ (get_vbase): Wrapper, now non-static.
+ (convert_pointer_to_vbase): Now static.
-Tue Dec 13 19:16:05 1994 Mike Stump <mrs@cygnus.com>
+ * 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.
- Fix some random `explicit' bugs.
+Mon Feb 24 15:00:12 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * call.c (build_over_call): Only synthesize non-trivial copy ctors.
-Tue Dec 13 16:18:57 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (build_c_cast): Lose other reference to flag.
- * Make-lang.in (cc1plus): Depends on c-pragma.o.
+ * 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.
- * Makefile.in (OBJ{DEP,}S): Add ../c-pragma.o.
+Thu Feb 20 15:12:15 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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_over_call): Call mark_used before trying to elide
+ the call.
-Mon Dec 12 23:53:06 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (implicitly_declare): Don't set DECL_ARTIFICIAL.
- * except.c (expand_throw): Fix Dec 6th change, build_new likes a
- reference better.
+Wed Feb 19 11:18:53 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Dec 12 18:01:00 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * typeck.c (build_modify_expr): Always pedwarn for a cast to
+ non-reference used as an lvalue.
- * 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 Feb 19 10:35:37 1997 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (do_pending_expansions): Don't clear TREE_PUBLIC on
- instantiations controlled by -fexternal-templates.
+ * cvt.c (cp_convert_to_pointer): Convert from 0 to a pmf properly.
- * decl.c (duplicate_decls): Don't complain about different values of
- __attribute__ ((const)) and ((noreturn)).
+Tue Feb 18 15:40:57 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Dec 9 18:17:37 1994 Doug Evans <dje@cygnus.com>
+ * parse.y (handler): Fix template typo.
- * Makefile.in (BISONFLAGS): Delete --yacc.
- (PARSE_H): Depend on $(PARSE_C), for parallel makes.
- (PARSE_C): Undo last patch.
+Sun Feb 16 02:12:28 1997 Jason Merrill <jason@yorick.cygnus.com>
-Fri Dec 2 10:44:36 1994 Mike Stump (mrs@wombat.gnu.ai.mit.edu)
+ * error.c (lang_decl_name): New fn.
+ * tree.c (lang_printable_name): Use it.
- * Makefile.in (BISONFLAGS): Add --yacc so that output winds up in
- y.tab.c.
+Fri Feb 14 16:57:05 1997 Mike Stump <mrs@cygnus.com>
-Thu Dec 8 17:39:46 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * g++spec.c: Include config.h so that we can catch bzero #defines
+ from the config file.
- * decl.c (finish_decl): Don't call obscure_complex_init for decls
- of indeterminate size.
+Tue Feb 11 13:50:48 1997 Mike Stump <mrs@cygnus.com>
-Wed Dec 7 16:49:22 1994 Jason Merrill <jason@phydeaux.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 (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.
+Mon Feb 10 22:51:13 1997 Bruno Haible <bruno@linuix.mathematik.uni-karlsruhe.de>
- * parse.y (bad_parm): Stop trying to support parms without types.
+ * 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.
-Wed Dec 7 12:06:56 1994 Mike Stump <mrs@cygnus.com>
+Fri Feb 7 15:43:34 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokfield): Make asm specs on static member functions
- work.
+ * decl.c (xref_basetypes): Allow a base class that depends on
+ template parms to be incomplete.
-Tue Dec 6 15:43:20 1994 Mike Stump <mrs@cygnus.com>
+ * 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.
- * except.c (expand_throw): Make a copy of the thrown object.
+Tue Feb 4 11:28:24 1997 Jason Merrill <jason@yorick.cygnus.com>
-Tue Dec 6 14:16:34 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * pt.c (unify, case TEMPLATE_CONST_PARM): Use cp_tree_equal.
- * parse.y: : has lower precedence than =.
+ * pt.c (tsubst): Put it back for -fno-ansi-overloading.
-Tue Dec 6 12:46:17 1994 Mike Stump <mrs@cygnus.com>
+Mon Feb 3 18:41:12 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushdecl): Use DECL_NAME of VAR_DECLs to avoid namespace
- manglings.
- (grokvardecl): Add namespace into variable name.
+ * pt.c (tsubst, case FUNCTION_DECL): Lose obsolete code that
+ smashes together template and non-template decls of the same
+ signature.
-Tue Dec 6 11:26:55 1994 Mike Stump <mrs@cygnus.com>
+Thu Jan 30 19:18:00 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * pt.c (tsubst): Don't recurse for the type of a TYPENAME_TYPE.
-Mon Dec 5 17:11:51 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+Wed Jan 29 11:40:35 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * decl.c (duplicate_decls): Next route, pedwarn about different
+ exceptions if -pedantic *or* olddecl !DECL_IN_SYSTEM_HEADER.
- * decl2.c (push_namespace): Dummy function.
- (pop_namespace): Ditto.
- (do_namespace_alias): Ditto.
- (do_using_decl): Ditto.
- (do_using_directive): Ditto.
+Tue Jan 28 20:43:29 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * 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.
- * typeck.c (convert_for_assignment): Handle conversions between
- enums and bool.
+ * 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.
- * decl.c (duplicate_decls): Only propagate DECL_MAIN_VARIANT on
- FUNCTION_DECLs.
+Tue Jan 28 16:40:40 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Dec 5 13:03:16 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (push_template_decl): Handle getting a typedef.
- * 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.
+ * call.c (build_new_function_call): Complain about void arg.
-Mon Dec 5 11:41:50 1994 Mike Stump <mrs@cygnus.com>
+Tue Jan 28 15:25:09 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (convert_for_assignment): Use cp_convert instead of
- convert so that we don't get static casts.
+ * decl.c (duplicate_decls): Give pedwarn of different exceptions
+ if -pedantic, instead of olddecl !DECL_IN_SYSTEM_HEADER.
-Sun Dec 4 11:59:01 1994 Mike Stump <mrs@cygnus.com>
+Mon Jan 27 19:21:29 1997 Mike Stump <mrs@cygnus.com>
- * cvt.c (cp_convert): Don't complain about int->enum conversion if
- we are doing static casts.
+ * 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.
-Fri Dec 2 18:32:41 1994 Mike Stump <mrs@cygnus.com>
+Mon Jan 27 16:24:35 1997 Sean McNeil <sean@mcneil.com>
- * error.c (dump_expr): Do something more intelligent with SAVE_EXPRs
- when dumping expressions in error messages.
+ * Make-lang.in: Add $(exeext) as necessary.
-Fri Dec 2 17:04:27 1994 Mike Stump <mrs@cygnus.com>
+Mon Jan 27 13:20:39 1997 Mike Stump <mrs@cygnus.com>
- * gc.c (build_dynamic_cast): Change interface to libg++, ensure that
- the return type is the right type, and make references work.
+ * parse.y (handler_seq): Must have at least one catch clause.
-Fri Dec 2 16:36:43 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+Sat Jan 25 12:00:05 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * call.c (add_builtin_candidate): Restore ?: hack.
- * decl2.c (mark_inline_for_output): Deal with the DECL_MAIN_VARIANT
- of this decl, in case this is a function-scope declaration.
+ * decl.c (grok_op_properties): More warnings.
- * decl.c (finish_enum): Make sure that the type has the right
- precision when we call fixup_*_type.
+Sat Jan 25 08:50:03 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Nov 29 19:12:07 1994 Jason Merrill <jason@phydeaux.cygnus.com>
+ * decl.c (duplicate_decls): On second thought, do it as a pedwarn
+ still but only if !DECL_IN_SYSTEM_HEADER (olddecl).
- * 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.
+ * decl.c (duplicate_decls): Scale back to a warning, and only do
+ 'em if -pedantic.
-Tue Nov 29 11:28:59 1994 Mike Stump <mrs@cygnus.com>
+Fri Jan 24 17:52:54 1997 Mike Stump <mrs@cygnus.com>
- * parse.y (maybe_raises): Handle throw ().
- * parse.y (ansi_raise_identifier): grok type-ids in exception
+ * decl.c (duplicate_decls): pedwarn mismatched 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.
-
-Tue Nov 29 09:50:39 1994 Mike Stump <mrs@cygnus.com>
-
- * except.c: Add support for m68k and mips exception handling
- support.
-
-Tue Nov 29 08:48:33 1994 Mike Stump <mrs@cygnus.com>
-
- * except.c (expand_end_all_catch): Throw into outer context, if we
- fall off end of catch handlers.
-
-Mon Nov 28 16:44:41 1994 Mike Stump <mrs@cygnus.com>
-
- * Makefile.in: Make is easier to decide where parse.[ch] will be
- built.
-
-Thu Nov 17 20:11:24 1994 Doug Evans <dje@cygnus.com>
-
- * 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.
-
-Thu Nov 3 18:48:19 1994 Paul Eggert <eggert@twinsun.com>
-
- * Makefile.in (spew.o, lex.o, pt.o):
- Depend on $(srcdir)/parse.h, not parse.h.
-
-Mon Nov 28 13:53:03 1994 Mike Stump <mrs@cygnus.com>
-
- * parse.y (THROW): Fix precedence of throw expressions.
-
-Mon Nov 28 13:15:16 1994 Mike Stump <mrs@cygnus.com>
-
- * typeck.c (build_unary_op): Allow promotions from bool to int on
- unary ~.
-
-Sun Nov 27 00:16:21 1994 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * 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.
-
-Wed Nov 23 17:59:42 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed Nov 23 14:46:56 1994 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * call.c (build_method_call): Don't try to synthesize methods yet.
-
-Tue Nov 22 12:45:21 1994 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * pt.c (push_template_decls): Create CONST_DECLs for template
- constant parameters, not VAR_DECLs.
-
-Sat Nov 19 15:28:31 1994 Jim Wilson (wilson@chestnut.cygnus.com)
-
- * typeck.c (build_binary_op_nodefault): Can shorten shift only if
- shift count is less than size in bits of arg0.
-
-Thu Nov 17 15:30:50 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Thu Nov 17 10:56:50 1994 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * typeck2.c (build_m_component_ref): Check the basetype of the
- member pointer against the main variant of the object type.
-
-Mon Nov 14 14:21:52 1994 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * cvt.c (convert_to_reference): Make sure that the original expr
- gets its type back when converting a reference.
-
- * method.c (build_overload_name): Clear numeric_outputed_need_bar here.
- (build_decl_overload): Instead of here.
-
-Tue Nov 8 17:11:24 1994 Jason Merrill <jason@phydeaux.cygnus.com>
-
- * cvt.c (cp_convert): Don't build a TARGET_EXPR if we're not in a
- function.
-
- * typeck.c (convert_for_initialization): Handle initialization from
- a TARGET_EXPR.
-
-Sun Nov 6 01:34:24 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * 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.
-
-Sat Nov 5 22:42:15 1994 Greg McGary (gkm@magilla.cichlid.com)
-
- * pt.c (do_type_instantiation): Check to see if there's a
- IDENTIFIER_TEMPLATE on a class before calling
- instantiate_member_templates().
-
-Fri Nov 4 19:04:18 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Fri Nov 4 11:12:00 1994 Mike Stump <mrs@cygnus.com>
-
- * except.c: Add hppa support.
-
-Fri Nov 4 10:50:50 1994 Mike Stump <mrs@cygnus.com>
-
- * except.c: Add rs6000 support.
-
-Thu Nov 3 14:24:23 1994 Mike Stump <mrs@cygnus.com>
-
- * except.c (do_unwind): Add i[34]86 support.
-
-Thu Nov 3 00:10:46 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * pt.c (do_pending_expansions): Unset TREE_PUBLIC on implicit
- instantiations.
-
-Wed Nov 2 15:08:24 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * decl.c (finish_function): emit types used in method parameters
- into symbol table.
-
-Wed Nov 2 15:05:47 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * pt.c (process_template_parm): Allow pointer to member function
- template parameter types.
- (uses_template_parms): Handle pointer to member function
- CONSTRUCTORs.
-
- * g++.c (main): Cast first argument of bzero to (char *).
- Pass -lstdc++ instead of -lg++ unless we are invoked as 'g++'.
-
-Mon Oct 31 14:50:48 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * 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.
-
-Tue Oct 25 17:13:09 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * 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 25 13:37:41 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * call.c (convert_harshness): Check for TREE_UNSIGNED differences
- after checking for integral conversions.
-
-Sun Oct 23 13:19:55 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * 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.
-
-Fri Oct 21 00:32:54 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * lex.c (cons_up_default_function): Don't try to defer method
- synthesis now.
-
- * 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.
-
- * tree.c (array_type_nelts_total): Use sizetype, not
- integer_type_node.
- (array_type_nelts_top): Ditto.
-
-Thu Oct 20 15:48:27 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Thu Oct 20 12:55:24 1994 Jim Wilson (wilson@cygnus.com)
-
- * method.c (emit_thunk): Call instantiate_virtual_regs.
-
-Wed Oct 19 14:15:33 1994 Mike Stump <mrs@cygnus.com>
- * except.c (expand_exception_blocks): Make sure throw code doesn't
- get put in function that won't be output.
+Thu Jan 23 18:18:54 1997 Mike Stump <mrs@cygnus.com>
-Mon Oct 17 18:03:15 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * call.c (build_new_method_call): Don't display the invisible
+ argument for controlling virtual bases.
- * decl.c (init_decl_processing): Make alloca a builtin.
+Thu Jan 23 16:48:10 1997 Mike Stump <mrs@cygnus.com>
-Thu Oct 27 21:10:25 1994 Craig Burley (craig@burley)
+ * 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}.
- * g++.c (main): Only decrement "added" and set "library" to
- NULL when "library" != NULL (just like 940829 fix).
+Thu Jan 23 16:39:06 1997 Jason Merrill <jason@yorick.cygnus.com>
-Mon Oct 17 15:56:11 1994 Mike Stump <mrs@cygnus.com>
+ * lex.c (cons_up_default_function): Fix return type of synth op=.
- * except.c (expand_start_catch_block): Make sure the false label
- gets onto the permanent obstack, as it is used for the exception
- table.
+ * init.c (emit_base_init): Add warnings for uninitialized members
+ and bases.
-Fri Oct 14 18:54:48 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (xref_basetypes): Add warning for non-polymorphic type
+ with destructor used as base type.
- * class.c (modify_one_vtable): Since the DECL_CONTEXT of fndecl can
- be set just below, use current_fndecl instead.
+ * 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.
-Fri Oct 14 15:12:22 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * class.c (finish_struct_1): Add warning for class with pointers
+ but not copy ctor or copy op=.
- * 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.
+ * 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.
- * typeck.c (build_modify_expr): Don't just build a MODIFY_EXPR if
- the rhs is a TARGET_EXPR.
+ * decl2.c (copy_assignment_arg_p): Disable old hack to support
+ Booch components.
- * parse.y (left_curly): Anonymous types are not affected by #pragma
- interface/implementation.
+Tue Jan 21 18:32:04 1997 Mike Stump <mrs@cygnus.com>
- * method.c (synthesize_method): Don't call setup_vtbl_ptr for the
- default constructor if it isn't needed.
+ * cvt.c (cp_convert): Pedwarn enum to pointer conversions.
- * lex.c (cons_up_default_function): Do synthesize methods for
- anonymous types if necessary.
+Mon Jan 20 17:59:51 1997 Jason Merrill <jason@yorick.cygnus.com>
-Thu Oct 13 17:44:55 1994 Jason Merrill (jason@phydeaux.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.
- * method.c (build_decl_overload): Set numeric_outputed_need_bar to 0.
+Mon Jan 20 14:53:13 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Oct 12 13:27:57 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * 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.
- * typeck.c (build_modify_expr): Understand how to copy an aggregate.
+Mon Jan 20 14:43:49 1997 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_default_init): Ditto. Also remove some of the
- crufty code that assumes methods will not be synthesized properly.
+ * decl.c (finish_function): Also zero out DECL_INCOMING_RTL for
+ the arguments.
- * 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.
+ * error.c (dump_expr, TEMPLATE_CONST_PARM): Don't require
+ current_template_parms.
- * lex.c (real_yylex): Use HOST_BITS_PER_WIDE_INT to determine the
- bitmask for lexing character constants.
+Fri Jan 17 10:25:42 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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): Don't return a function, check want_type.
-Wed Oct 12 16:14:01 1994 Benoit Belley <belley@cae.ca>
+Thu Jan 16 18:14:35 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * init.c (build_new): Make sure PLACEMENT has a type.
-Wed Oct 12 13:24:03 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Thu Jan 16 17:40:28 1997 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (type_promotes_to): Also promote enums to long if
- appropriate.
+ * init.c (build_new): Support new (nothrow).
- * typeck.c (default_conversion): Don't expect type_promotes_to to
- return a main variant.
+Wed Jan 15 12:38:14 1997 Jason Merrill <jason@yorick.cygnus.com>
-Wed Oct 12 12:19:45 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * pt.c (instantiate_decl): Also do push_to_top_level before setting
+ up DECL_INITIAL.
- * call.c (build_scoped_method_call): Don't lose side effects in the
- object expression when calling a non-existent destructor.
+ * cp-tree.h (PARM_DEFAULT_FROM_TEMPLATE): New macro.
+ * pt.c (tsubst): Defer instantiation of default args.
+ * call.c (build_over_call): Until here.
-Fri Sep 2 19:05:21 1994 Rohan Lenard (rjl@iassf.easams.com.au)
+Wed Jan 15 10:08:10 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * call.c (build_scoped_method_call): Remove erroneous error message
- when destructor call is written as a scoped call.
+ * search.c (lookup_field): Make sure we have an
+ IDENTIFIER_CLASS_VALUE before we try to return it.
-Tue Oct 11 23:48:31 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Thu Jan 9 07:19:01 1997 Brendan Kehoe <brendan@lisa.cygnus.com>
- * various: Cast pointer arguments to bzero and bcopy to char *.
+ * 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.
-Tue Oct 11 19:34:32 1994 Mike Stump <mrs@cygnus.com>
+Wed Jan 8 13:09:54 1997 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * 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.
-Tue Oct 11 16:10:52 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * 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.
- * pt.c (do_function_instantiation): Set DECL_EXTERNAL and
- TREE_STATIC when setting DECL_INTERFACE_KNOWN.
- (do_type_instantiation): Ditto.
+ * method.c (build_overload_value): Handle getting a
+ TEMPLATE_CONST_PARM for a pointer.
- * lex.c (cons_up_default_function): Set DECL_INTERFACE_KNOWN,
- DECL_EXTERNAL and TREE_STATIC as appropriate.
+Tue Jan 7 14:00:58 1997 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_file): Also synthesize methods that don't have
- DECL_EXTERNAL set. Set interface_unknown before doing so.
-
- * decl.c (start_function): If DECL_INTERFACE_KNOWN is set on the
- function decl, don't muck with TREE_PUBLIC and DECL_EXTERNAL.
-
-Mon Oct 10 00:56:53 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * 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.
-
- * 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.
-
-Sun Oct 9 02:42:29 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * method.c (do_build_copy_constructor): Handle anonymous unions.
- (do_build_assign_ref): Ditto.
- (largest_union_member): Move from lex.c.
-
-Sat Oct 8 14:59:43 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- 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.
-
- 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.
-
-Wed Oct 5 13:44:41 1994 Jason Merrill (jason@phydeaux.cygnus.com)
-
- * call.c (build_overload_call_real): Don't immediately do
- array->pointer conversion.
-
- * pt.c (type_unification): If not passing to a reference, strip
- cv-quals. Also handle array->pointer conversion.
+ * init.c (expand_member_init): Don't give 'not a base' error for
+ templates.
-Tue Oct 4 17:45:37 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+ * pt.c (instantiate_decl): Call import_export_decl later.
- * decl.c (grokdeclarator): Don't warn about applying const to a
- const typedef or template type parameter.
+ * pt.c (instantiate_class_template): Return a value.
- * decl2.c (finish_file): Also synthesize methods after walking the
- vtables. Ugly ugly ugly.
+ * parse.y (extension): New rule for __extension__.
+ (extdef, unary_expr, decl, component_decl): Use it.
-Mon Oct 3 15:02:41 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Tue Jan 7 09:20:28 1997 Mike Stump <mrs@cygnus.com>
- * various: Remove lingering remnants of old exception handling code.
+ * class.c (base_binfo): Remove unused base_has_virtual member.
+ (finish_base_struct): Likewise.
+ (finish_struct_1): Likewise.
- * decl2.c (finish_file): Synthesize methods before walking the
- vtables, so that the vtables get emitted as needed.
+Tue Dec 31 20:25:50 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (shadow_tag): Remove obsolete code for pushing tags and
- dealing with exceptions.
+ * 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 Oct 3 13:05:27 1994 Ian Lance Taylor <ian@sanguine.cygnus.com>
+Tue Dec 31 15:16:56 1996 Mike Stump <mrs@cygnus.com>
- * Make-lang.in (g++-cross): Depend upon version.o and $(LIBDEPS).
+ * init.c (perform_member_init): Make sure the partial EH cleanups
+ live on the function_obstack.
-Mon Oct 3 02:59:28 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Fri Dec 27 10:31:40 1996 Paul Eggert <eggert@twinsun.com>
- * decl2.c (finish_file): Fix inline handling.
+ * 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).
-Sun Oct 2 00:21:56 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Tue Dec 24 10:24:03 1996 Jeffrey A Law (law@cygnus.com)
- * decl.c (grokdeclarator): Handle redundant scope even better.
- ({push,pop}_cp_function_context): Take toplev parameter.
+ * decl.c (grokvardecl): Avoid ANSI style initialization.
- * method.c (synthesize_method): Pass toplev parameter to
- {push,pop}_cp_function_context depending on decl_function_context
- (fndecl).
+Sun Dec 22 04:22:06 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_x_unary_op): Unary & on OFFSET_REFs is always the
- built-in version.
+ * pt.c (tsubst): Tweak arg types for a FUNCTION_TYPE.
- * method.c (synthesize_method): Don't be confused by __in_chrg
- parameter.
+Fri Dec 20 17:09:25 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (popclass): Set C_C_D like start_function does.
+ * pt.c (instantiate_class_template): Call grok_{ctor,op}_properties.
- * decl.c (grokdeclarator): Handle redundant scope better.
+Fri Dec 20 12:17:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * parse.y (expr_or_declarator): Add '(' expr_or_declarator ')' rule.
- (direct_notype_declarator): Ditto.
- (complex_direct_notype_declarator): Remove it here.
+ * 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.
-Sat Oct 1 21:42:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Dec 19 11:53:57 1996 Stan Shebs <shebs@andros.cygnus.com>
- * init.c (resolve_offset_ref): Fix types used in resolving .*
- expressions.
+ * lang-specs.h: Accept .cp as an C++ extension.
-Sat Oct 1 15:18:49 1994 Jason Merrill (jason@phydeaux.cygnus.com)
+Mon Dec 16 22:43:31 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- 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.
+ * cp-tree.h (ptr_reasonably_similar): Add decl.
-Thu Sep 29 16:58:52 1994 Mike Stump <mrs@cygnus.com>
+Thu Dec 12 15:00:35 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (c_expand_return): Use magic so the backend can fixup the
- assignment into the return register, so cleanups won't clobber it.
+ * decl.c (grokvardecl): Change SPECBITS parm to be the SPECBITS_IN
+ pointer. New local SPECBITS with the parm's value.
+ (grokdeclarator): Pass &specbits down.
-Thu Sep 29 13:08:50 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * method.c (hack_identifier): Don't call assemble_external for
- template decls.
+ * search.c (envelope_add_decl): Check that the CLASSTYPE_CID of
+ CONTEXT is not 0 before we try to use TYPE_DERIVES_FROM.
- * decl.c (finish_decl): Also end temporary allocation if the decl in
- question has a type of error_mark_node.
+ * decl.c (cplus_expand_expr_stmt): Only expand the expr if EXP is
+ not an error_mark_node.
-Wed Sep 28 21:45:00 1994 Mike Stump <mrs@cygnus.com>
+Sat Dec 7 17:20:22 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): When optimizing ?: on lhs, make sure
- that if the ?: was a reference type, that the subparts will be also.
+ * cp-tree.h (TYPE_MAIN_DECL): Use TYPE_STUB_DECL.
+ * *.c: Use TYPE_MAIN_DECL instead of TYPE_NAME where appropriate.
+
+Fri Dec 6 14:40:09 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Sep 28 16:14:04 1994 Brendan Kehoe (brendan@lisa.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).
- * except.c (register_exception_table): Use Pmode, not PTRmode.
+ * typeck2.c (build_m_component_ref): If component is a pointer
+ to data member, resolve the OFFSET_REF now.
-Fri Sep 23 13:54:27 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (convert_like): Don't go into infinite recursion.
- * lex.c (do_pending_inlines): Do method synthesis after the
- pending_inlines have been reversed.
+ * pt.c (coerce_template_parms): Use tsubst_expr for non-type args.
-Thu Sep 22 12:53:03 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * class.c (finish_struct_1): Set DECL_ARTIFICIAL on the vptr.
+ * tree.c (layout_basetypes): And on the vbase ptr.
- * decl2.c (finish_file): Fix Brendan's fix: Only call
- register_exception_table if there is a non-empty exception table.
+Thu Dec 5 02:11:28 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Sep 22 12:03:46 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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.
- * decl2.c (finish_file): Only do register_exception_table if
- -fhandle-exceptions is being used.
+ * decl.c (pushtag): Set DECL_IGNORED_P for DWARF, too.
-Wed Sep 21 19:01:51 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Tue Dec 3 23:18:37 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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 (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.
-Wed Sep 21 13:20:42 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Fri Nov 29 21:54:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (break_out_calls): Don't try to duplicate the DECL_INITIAL.
+ * decl2.c (finish_file): Emit DWARF debugging info for static data
+ members.
- * decl2.c (delete_sanity): Give an error at trying to delete a
- function.
+ * pt.c (tsubst): If t is a stub decl, return the stub decl for type.
-Wed Sep 21 11:47:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Nov 27 14:47:15 1996 Bob Manson <manson@charmed.cygnus.com>
- * lex.c (cons_up_default_function): Mark synthesized destructors
- inline.
+ * typeck.c (build_component_ref): Don't die if COMPONENT isn't a
+ IDENTIFIER_NODE.
- * decl.c (duplicate_decls): Ignore redeclarations of wchar_t as
- something other than __wchar_t, complaining if -pedantic and not in
- a system header.
+Wed Nov 27 16:05:19 1996 Michael Meissner <meissner@tiktok.cygnus.com>
-Tue Sep 20 09:43:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (g++-cross$(exeext)): Fix typo.
- * decl.c (xref_tag): Set up BINFO_INHERITANCE_CHAIN on base binfos
- here.
+Wed Nov 27 08:14:00 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (build_modify_expr): Require complete type after checking
- for error_mark_node.
+ 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.
- * call.c (build_method_call): Print parmtypes when complaining of
- ambiguous call.
+Tue Nov 26 19:01:09 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (build_modify_expr): Handle assignment to array from
- non-array.
+ * cvt.c (build_up_reference): Arrange for any temporary values
+ that have been keep in registers until now to be put into memory.
- * decl.c (lookup_name_real): Deal with got_scope == error_mark_node.
+Mon Nov 25 15:16:41 1996 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
- * call.c (build_method_call): Don't bother with the exact match.
+ * Make-lang.in (c++.stage[1234]): Depend upon stage[1-4]-start, so
+ that make -j3 bootstrap works better.
-Mon Sep 19 00:51:39 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sun Nov 24 02:09:39 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_aggr_init): If we munge the type of the variable,
- also munge the type of the initializer.
+ * decl.c (pushtag): Do pushdecl for anon tags.
- * 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 Nov 21 16:30:24 1996 Jason Merrill <jason@yorick.cygnus.com>
- * error.c (cp_line_of): return lineno in lieu of 0.
+ * typeck.c (c_expand_return): Fix logic.
+ (unary_complex_lvalue): Avoid unused warning on address of INIT_EXPR.
- * 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 Nov 20 18:47:31 1996 Bob Manson <manson@charmed.cygnus.com>
- * typeck2.c (store_init_value): Don't pedwarn about non-constant
- bracketed initializers for automatic variables.
+ * 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.
-Sun Sep 18 10:12:12 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Nov 19 16:12:44 1996 Jason Merrill <jason@yorick.cygnus.com>
- * error.c (dump_decl): Don't say `typedef enum foo foo'.
+ * decl.c (implicitly_declare): Set DECL_ARTIFICIAL.
- * 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.
+Tue Nov 19 15:48:19 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (build_unary_op): Clean up cruft in ADDR_EXPR case.
+ * init.c (resolve_offset_ref): Handle obj.vfn better.
+ * typeck.c (build_component_ref): Set TREE_TYPE on result from
+ build_vfn_ref.
- * class.c (instantiate_type): Set TREE_CONSTANT on instantiated
- ADDR_EXPRs if appropriate.
+Tue Nov 19 13:14:33 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (build_ptrmemfunc_type): Unset IS_AGGR_TYPE on pmf types.
+ * typeck.c (convert_for_assignment): Also handle anachronistic
+ implicit conversions from (::*)() to cv void*.
+ * cvt.c (cp_convert_to_pointer): Likewise.
- * typeck.c (build_ptrmemfunc): Handle &overloaded_method as an
- initializer properly.
- * typeck2.c (digest_init): Ditto.
+Mon Nov 18 17:05:26 1996 Jason Merrill <jason@yorick.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.
+ * lex.c (handle_cp_pragma): Fix bogus warning.
- * pt.c (do_type_instantiation): Don't try to instantiate nested
- enums.
+Mon Nov 18 16:10:43 1996 Mike Stump <mrs@cygnus.com>
-Tue Sep 13 10:56:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (cp_convert_to_pointer): Avoid thinking a POINTER_TYPE
+ (METHOD_TYPE) is a TYPE_PTRMEMFUNC_P.
- * cvt.c (build_up_reference): Handle preincrement and predecrement
- properly.
+Thu Nov 14 23:18:17 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Sep 13 09:51:59 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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.
- * decl.c (finish_decl): Only lay out the rtl for DECL if it is, in
- fact, static.
+Thu Nov 14 15:21:46 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Mon Sep 12 14:40:30 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * Make-lang.in (cplib2.ready): Add else clause to avoid problems
+ on some picky hosts.
- * decl.c (finish_decl): Lay out the rtl for DECL before doing
- grok_reference_init, in case it's static.
+Wed Nov 13 12:32:07 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Sep 12 12:45:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (finish_struct_1): A class has a non-trivial copy
+ constructor if it has virtual functions.
- * 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.
+ * cvt.c (cp_convert): Always call a constructor.
- * decl.c (grokdeclarator): Don't treat a function pointer field
- with the same name as the class as a constructor.
+ * call.c (reference_binding): Still tack on a REF_BIND
+ for bad conversions.
+ (build_user_type_conversion_1): Propagate ICS_BAD_FLAG.
-Fri Sep 9 13:17:00 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * typeck.c (build_c_cast): Pull constant values out of their
- variables here.
+Wed Nov 13 11:51:20 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (duplicate_decls): Only propagate DECL_CHAIN in
- FUNCTION_DECLs and TEMPLATE_DECLs.
+ * g++.c (main): Also set PEXECUTE_SEARCH, to make the invocation
+ of GCC be path-relative.
-Thu Sep 8 10:07:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Nov 13 11:27:16 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * decl.c (duplicate_decls): Propagate DECL_CHAIN in all DECLs that
- have it.
+ * Make-lang.in (g++-cross): G++-cross doesn't need version.o, but
+ it does need choose-temp.o and pexecute.o.
- * 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.
+Wed Nov 13 07:53:38 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Sep 7 13:17:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * 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.
+Wed Nov 13 02:00:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * init.c (expand_default_init): Avoid calling constructors to
+ initialize reference temps.
-Mon Sep 5 12:49:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (convert_to_reference): Fix.
- * 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.
+Tue Nov 12 19:10:07 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Sep 2 15:11:59 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.
- * decl.c (finish_enum): Overhaul to fix several bugs.
- (start_enum): Disable useless code.
+Tue Nov 12 16:29:04 1996 Brendan Kehoe <brendan@canuck.cygnus.com>
-Thu Sep 1 16:04:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst_expr): Reverse args to expand_start_catch_block.
- * typeck.c (c_expand_return): Warn about returning a reference to a
- temporary.
- (convert_arguments): Increment argument counter when using default
- arguments, too.
+Tue Nov 12 15:26:17 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Aug 31 14:29:22 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (expand_aggr_init_1): Don't crash on non-constructor
+ TARGET_EXPR.
- * decl.c (finish_decl): If the type of decl is error_mark_node,
- don't bother trying to do anything.
+Tue Nov 12 14:00:50 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (convert_for_initialization): If the rhs contains a
- constructor call, pretend the lhs type needs to be constructed.
+ * 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.
- * init.c (expand_default_init): If we stick the object inside the
- initializer, mark the initializer used.
+ * 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.
-Tue Aug 30 13:50:18 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.
- * method.c (build_assign_ref): return *this;
- (build_assign_ref): Fix base assignment order.
- (build_copy_constructor): Fix member init order.
+Tue Nov 12 12:16:20 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Aug 29 13:54:39 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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.
- * g++.c (main): Remember to clear out SAW_SPECLANG after we see
- its argument.
+Mon Nov 11 13:57:31 1996 Jason Merrill <jason@yorick.cygnus.com>
-Sat Aug 27 09:36:03 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * method.c (build_copy_constructor): Also copy virtual bases.
+ * pt.c (current_template_args): New fn.
+ (push_template_decl): Use it.
+ * decl.c (grokdeclarator): Use it.
-Fri Aug 26 17:05:15 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (build_expr_from_tree): Dereference ref vars.
- * lex.c (do_pending_inlines): Clear out pending_inlines before doing
- any synthesis. Also first set deja_vu on all pending_inlines.
+ * decl.c (grokdeclarator): Generalize handling of TYPENAME_TYPEs in
+ the decl-specifier-seq.
- * 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.
+ * 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.
- * decl2.c (grokfield): Don't complain about undefined local class
+ * decl2.c (finish_file): Don't call instantiate_decl on synthesized
methods.
- * 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.
-
-Fri Aug 26 12:24:14 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * 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.
-
- * cp-tree.h (cons_up_default_function): Note change of prototype.
-
-Thu Aug 25 23:05:30 1994 Gerald Baumgartner (gb@cs.purdue.edu)
-
- * 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.
-
-Thu Aug 25 00:36:31 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- 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().
-
- * error.c (cp_line_of): If we're dealing with an artificial
- TYPE_DECL, look at the type instead.
-
-Wed Aug 24 11:11:50 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * init.c (sort_member_init): Check warn_reorder.
- * decl2.c (lang_decode_option): Handle -W{no-,}reorder.
-
- * 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.
-
-Tue Aug 23 09:28:35 1994 Mike Stump <mrs@cygnus.com>
-
- * error.c (dump_decl): Improve wording, so that error messages
- dont't read template<, class foo>...
-
-Mon Aug 22 15:30:51 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * 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.
-
- * pt.c (coerce_template_parms): Call cp_error, not cp_error_at,
- for the message so they know at what point it was instantiated.
-
-Sun Aug 21 23:07:35 1994 Gerald Baumgartner (gb@cs.purdue.edu)
-
- * 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): Don't test for function/field name
- conflicts in signatures, since all the fields are compiler-constructed.
-
-Fri Aug 19 14:04:47 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * 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.
-
-Thu Aug 18 16:24:43 1994 Mike Stump <mrs@cygnus.com>
-
- * error.c (dump_decl): Handle NULL args.
-
-Thu Sep 29 16:15:36 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
-
- * g++.c: Rework last change so it's done like collect.c (and
- gcc.c).
-
-Wed Sep 14 10:17:27 1994 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
-
- * g++.c: Include <sys/errno.h> in case `errno' is a macro
- as permitted by ANSI C.
-
-Thu Aug 18 12:48:09 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Thu Aug 11 11:32:42 1994 H.J. Lu (hjl@nynexst.com)
-
- * g++.c (main): Only decrement "added" and set "library" to
- NULL when "library" != NULL.
-
-Sat Aug 13 00:14:52 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * 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.
-
- * lex.c (cons_up_default_function): Don't play with TREE_PUBLIC and
- DECL_EXTERNAL here.
-
-Fri Aug 12 01:55:15 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (pushtag): SET_DECL_ARTIFICIAL on gratuitous typedefs.
- (xref_defn_tag): Ditto.
- (pushdecl): Only allow artificial typedefs to be shadowed.
-
- * init.c (emit_base_init): Pass the right binfos to
- expand_aggr_init_1.
-
- * class.c (delete_duplicate_fields_1): Make it work right.
- (finish_struct): Catch function/field name conflict.
-
- * decl2.c (check_classfn): Pass the function to cp_error, not just
- the name.
-
- * 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.
-
- * error.c (dump_expr): Handle lists of functions.
-
- * 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.
-
- * 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.
-
- * class.c (instantiate_type): Handle template instantiation better.
-
- * 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.
-
- * lex.c (check_for_missing_semicolon): Also give error at end of
- file.
-
- * call.c (build_method_call): Don't promote arrays to pointers here.
-
- * typeck.c (convert_arguments): Don't require the actual parameter
- to be of a complete type if the formal parameter is a reference.
-
-Thu Aug 11 15:21:40 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (grokdeclarator): Soften 'static' on member function error
- to pedwarn.
-
- * init.c (build_new): Don't automatically save rval.
- (build_offset_ref): Do field lookup with proper basetype_path.
+Mon Nov 11 13:20:34 1996 Bob Manson <manson@charmed.cygnus.com>
-Thu Aug 11 12:46:54 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * typeck.c (get_delta_difference): Remove previous bogusness.
+ Don't give errors if force is set.
- * 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.
+Fri Nov 8 17:38:44 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Aug 11 00:02:54 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl2.c (grok_array_decl): Try computing *(A+B) if neither
- argument is obviously an array.
-
-Wed Aug 10 15:32:04 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (c_expand_start_case): Do cleanups here.
-
- * parse.y (xcond): Do bool conversion here, too.
- (simple_stmt, SWITCH case): Don't do cleanups here.
-
- * decl.c (duplicate_decls): Don't treat builtins that have been
- explicitly declared specially.
-
-Tue Aug 9 01:16:09 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * tree.c (make_deep_copy): Support copying pointer, reference,
- function, array, offset and method types.
-
- * 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.
-
- * parse.y (paren_cond_or_null): Do cleanup and bool conversion here.
- (condition): Instead of here.
- (simple_stmt, SWITCH case): Also do cleanup here.
-
- * decl2.c (finish_anon_union): Only break out FIELD_DECLs.
-
- * 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.
-
- * method.c (build_decl_overload): Oop.
-
- * decl2.c (lang_decode_option): Deal with flag_no_nonansi_builtin,
- warn about uselessness of specifying -fansi-overloading.
-
- * method.c (build_decl_overload): Treat any non-member new with one
- parameter as __builtin_new.
-
- * decl.c (init_decl_processing): Setup built-in meanings of exit,
- _exit and abort.
-
-Mon Aug 8 15:03:30 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * error.c (dump_readonly_or_volatile): Put a space between const and
- volatile if both apply.
-
- * 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.
-
-Sun Aug 7 14:55:05 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * call.c (build_method_call): Deal with destroying references.
-
- * parse.y (condition): Do bool_truthvalue_conversion here.
- (paren_expr_or_null): And here.
- (simple_if): Not here.
- (simple_stmt): Or here.
-
-Sat Aug 6 22:29:45 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * parse.y (paren_expr_or_null): Wrap the expression in a
- CLEANUP_POINT_EXPR.
- (condition): Ditto.
-
-Sat Aug 6 19:46:37 1994 Rohan Lenard (rjl@easams.com.au)
+ * 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.
- * call.c (build_scoped_method_call): Fix error message when
- destructor call refers to a nonexistent type.
+Fri Nov 8 11:52:28 1996 Bob Manson <manson@charmed.cygnus.com>
-Sat Apr 16 22:43:30 1993 Gerald Baumgartner (gb@cs.purdue.edu)
+ * 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.
- * 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.
+Thu Nov 7 11:16:24 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (grokdeclarator): Use RID_LAST_MODIFIER instead of
- RID_MAX as loop limit for finding declaration specifiers.
+ * error.c (dump_expr): Improve the wording on error messages that
+ involve pointer to member functions.
-Sat Apr 3 21:59:07 1993 Gerald Baumgartner (gb@cs.purdue.edu)
+Tue Nov 5 17:12:05 1996 Mike Stump <mrs@cygnus.com>
- * lex.c (debug_yytranslate): Moved to parse.y since it needs to
- access `yytname,' which is static in parse.c.
+ * 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 Apr 2 23:36:57 1993 Gerald Baumgarnter (gb@cs.purdue.edu)
+Tue Nov 5 14:54:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (GNU_xref_ref): Fixed typo in extern declaration, it
- was `GNU_xref_def' instead of `GNU_xref_ref.'
+ * 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.
-Fri Aug 5 14:20:16 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Nov 4 17:43:12 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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.
- * decl2.c (import_export_inline): Decides at EOF what an inline's
- linkage should be.
- (finish_file): Call it.
+Sun Nov 3 09:43:00 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * typeck.c (c_expand_return): Fix for returning overloaded fn.
-Fri Aug 5 01:12:20 1994 Mike Stump <mrs@cygnus.com>
+Fri Nov 1 08:53:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * 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.
-Tue Aug 2 12:44:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Oct 31 17:08:49 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Put back unary_complex_lvalue call
- that I thought was redundant.
+ * typeck.c (mark_addressable): Support TARGET_EXPR, unify with
+ similar code in build_up_ref.
+ * cvt.c (build_up_reference): Drastically simplify.
- * typeck.c (c_expand_return): Fix a case I missed before.
+Mon Oct 28 12:45:05 1996 Jeffrey A Law (law@cygnus.com)
-Sun Jul 31 17:54:02 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (signed_or_unsigned_type): If the given type already
+ as the correct signedness, then just return it.
- * 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').
+ * typeck.c ({un,}signed_type): If can't do anything, call
+ signed_or_unsigned_type.
-Fri Jul 29 01:03:06 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Oct 24 14:21:59 1996 Bob Manson <manson@charmed.cygnus.com>
- * pt.c (do_type_instantiation): Instantiate nested TAGS, not
- typedefs. Third time's the charm?
+ * decl2.c (copy_assignment_arg_p): Don't buy the farm if
+ current_class_type is NULL.
- * 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.
+Wed Oct 23 00:43:10 1996 Jason Merrill <jason@gerbil.cygnus.com>
-Wed Jul 27 17:47:00 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * class.c (finish_struct_1): Avoid empty structs by adding a field
+ so layout_type gets the mode right.
- * pt.c (do_type_instantiation): Only instantiate nested *classes*.
+ * typeck.c (c_expand_return): Drastically simplify.
-Tue Jul 26 13:22:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Oct 21 22:34:02 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (note_debug_info_needed): Also emit debugging information
- for the types of fields.
+ * typeck.c (decay_conversion): Handle overloaded methods.
-Mon Jul 25 00:34:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Oct 18 16:03:48 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (lookup_template_class): Pass 'template' to
- coerce_template_parms instead of 'in_decl', since it's a more
- meaningful context.
+ * call.c (build_over_call): A TARGET_EXPR has side-effects.
- * 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.
+Thu Oct 17 11:31:59 1996 Mike Stump <mrs@cygnus.com>
- * pt.c (do_type_instantiation): Also instantiate nested types.
+ * 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.
- * typeck.c (convert_for_assignment): Don't die when comparing
- pointers with different levels of indirection.
+Mon Oct 14 00:28:51 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): The sub-call to grokdeclarator for
- class-local typedefs sets DECL_ARGUMENTS, so we need to clear it
- out.
+ * Make-lang.in (cplib2.ready): Fix logic.
- * decl2.c (finish_anon_union): Don't die if the union has no
+ * decl.c (shadow_tag): Only complain about non-artificial function
members.
- * decl.c (grokdeclarator): Undo changes to declspecs when we're done
- so that 'typedef int foo, bar;' will work.
-
- * decl2.c (finish_file): Don't call expand_aggr_init for
- non-aggregates.
-
-Mon Jul 25 00:03:10 1994 Teemu Torma (tot@trema.fi)
-
- * decl.c (finish_function): We can't inline constructors and
- destructors under some conditions with -fpic, but don't unset
- DECL_INLINE.
-
-Mon Jul 25 00:03:10 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (build_object_ref): Make sure 'datum' is a valid object.
-
-Sun Jul 24 14:19:31 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct): Don't set DECL_FIELD_BITPOS on
- non-fields.
- (finish_struct_methods): Use copy_assignment_arg_p.
-
- * cvt.c (cp_convert): If expr is an OFFSET_REF, resolve it instead
- of giving an error.
-
- * typeck.c (build_binary_op_nodefault): Don't set result_type if we
- don't know how to compare the operands.
-
- * decl.c (grokdeclarator): Avoid seg fault when someone uses '__op'
- as a declarator-id in their program. Like the Linux headers do.
- Arrgh.
-
- * tree.c (lvalue_p): Treat calls to functions returning objects by
- value as lvalues again.
+ * class.c (finish_struct_1): Add synthesized methods to TYPE_METHODS.
- * typeck.c (build_component_addr): Use convert_force to convert the
- pointer in case the component type is also a private base class.
+Fri Oct 11 16:12:40 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (get_matching_virtual): Fix bogus warning of overloaded
- virtual.
+ * expr.c (cplus_expand_expr): Pre-tweak call_target like
+ expand_inline_function would.
- * pt.c (overload_template_name): Set DECL_ARTIFICIAL on the created
- TYPE_DECL to fix bogus shadowing warnings.
-
-Fri Jul 22 01:15:32 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * init.c (expand_aggr_init_1): const and volatile mismatches do not
- prevent a TARGET_EXPR from initializing an object directly.
-
-Tue Jul 19 17:55:37 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cvt.c (build_up_reference): Allow building up references to
- `this', don't warn about making references to artificial variables
- (like `this').
-
- * tree.c (lvalue_p): `this' is not an lvalue.
-
- * call.c (build_method_call): Accept using a typedef name (or
- template type parameter) for explicit destructor calls.
-
-Wed Jul 13 03:57:54 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * method.c (hack_identifier): Put back old code so lists of
- non-functions will be handled properly.
-
- * cp-tree.h (TYPE_NEEDS_CONSTRUCTING): #if 0 out; this macro is now
- defined in the language-independent tree.h.
-
- * tree.c (count_functions): Avoid bogus warning when compiling this
- function.
-
-Mon Jul 11 18:37:20 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (grok_reference_init): Always save the initializer of a
- reference.
-
-Fri Jul 8 17:41:46 1994 Mike Stump <mrs@cygnus.com>
-
- * decl.c (cplus_expand_expr_stmt): Wrap statement expressions inside
- CLEANUP_POINT_EXPRs so that the stack slots can be reused.
- (disabled for now)
-
-Fri Jul 8 12:59:38 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * method.c (hack_identifier): Fix for new overloading.
-
- * typeck.c (build_binary_op_nodefault): Don't mess with division by
- zero.
-
-Fri Jul 8 13:20:28 1994 Gerald Baumgartner (gb@cs.purdue.edu)
-
- * decl2.c (finish_file): Only call walk_sigtables, if
- flag_handle_signatures is turned on, don't waste time otherwise.
-
-Fri Jul 8 02:27:41 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * 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.
-
- * 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.
-
-Thu Jul 7 22:20:46 1994 Gerald Baumgartner (gb@andros.cygnus.com)
-
- * 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.
-
- * sig.c (build_signature_table_constructor): Mark class member
- function pointed to from signature table entry as addressable.
-
-Thu Jul 7 13:39:37 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (start_decl): Check new decl of static member variable
- against the declaration in the class here.
- (grokvardecl): Instead of here.
-
- * class.c (prepare_fresh_vtable): Call import_export_vtable if not
- -fvtable-thunks.
- (build_vtable): Ditto.
-
- * 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.
-
-Wed Jul 6 20:25:48 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed Jul 6 17:55:32 1994 Per Bothner (bothner@kalessin.cygnus.com)
-
- * decl2.c (mark_vtable_entries): If -ftable-thunks, set the
- vtable entry properly to abort.
-
-Tue Jul 5 14:07:54 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (build_binary_op_nodefault): Downgrade division by zero
- errors to warnings.
-
- * 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.
+ * pt.c (mark_decl_instantiated): If extern_p, call
+ mark_inline_for_output.
- * 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.
+Thu Oct 10 15:58:08 1996 Mike Stump <mrs@cygnus.com>
-Fri Jul 1 09:35:51 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (unary_complex_lvalue): Add code to handle intermediate
+ pmd conversions.
- * parse.y (init): ANSI C++ does not forbid { }.
+ * typeck.c (get_delta_difference): Fix wording, as we can be used
+ for pointer to data members.
-Thu Jun 30 00:35:22 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Oct 8 12:43:51 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl2.c (lang_decode_option): Set warn_nonvdtor along with -Wall.
- warn_nonvdtor defaults to off.
+ * 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.
- * class.c (instantiate_type): Use comptypes rather than relying on
- types to satisfy ==.
+Thu Oct 3 16:24:28 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_function): Set DECL_DEFER_OUTPUT on all inlines that
- might be static.
+ * 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.
- * tree.c (build_cplus_new): Never build WITH_CLEANUP_EXPRs.
+Wed Oct 2 21:58:01 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (grok_reference_init): Deal with ADDR_EXPRs of TARGET_EXPRs.
+ * decl.c (duplicate_decls): Make sure the old DECL_LANG_SPECIFIC
+ isn't the same as the new one before we whack it.
- * cvt.c (cp_convert): Pass 0 to with_cleanup_p arg of
- build_cplus_new.
+Mon Sep 30 13:38:24 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jun 29 22:31:09 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * decl2.c (finish_file): Maybe consider static inlines multiple
- times, in case they reference each other.
+Mon Sep 30 12:58:40 1996 Mike Stump <mrs@cygnus.com>
-Tue Jun 28 11:58:38 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+ * input.c (sub_getch): Handle 8-bit characters in string literals.
- * class.c (finish_struct): Don't `cons_up_default_function's
- for signatures.
- (finish_struct): Handle an empty method_vec correctly.
+Sun Sep 29 03:12:01 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * tree.c (mapcar): Handle CONSTRUCTORs.
+ (copy_to_permanent): Handle expression_obstack properly.
- * 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.
+ * Make-lang.in (cplib2.txt): Also depend on the headers.
- * sig.c (build_signature_pointer_constructor): Complain if we
- try to assign to/initialize a signature pointer/reference of
- an undefined signature.
+ * 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 Jun 27 14:05:16 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+ * method.c (build_overload_int): TYPE_PRECISION should be applied
+ to types.
- * typeck2.c (store_init_value): Don't be pedantic about
- non-constant initializers of signature tables/pointers/references.
+Sat Sep 28 14:44:50 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Jun 24 16:49:41 1994 Gerald Baumgartner (gb@cs.purdue.edu)
+ * call.c (build_new_op): A COND_EXPR involving void must be a
+ builtin.
- * decl.c (grokdeclarator): If we are grokking an opaque typedef
- in a signature, don't complain about it begin static.
+Fri Sep 27 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
-Wed Jun 29 16:44:45 1994 Mike Stump <mrs@cygnus.com>
+ * 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.
- Fixes a problem of the this pointer being wrong in virtual calls to
- methods that are not overridden in more derived classes.
+ * decl.c (start_decl): variable-sized arrays cannot be initialized.
+ * error.c (dump_type_suffix): Handle variable arrays.
- * 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.
+Fri Sep 27 13:14:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Jun 28 23:49:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (exception.o): Put back compiling it with -fPIC.
- * typeck.c (build_binary_op): Use the types before default
- conversions in the error message.
+Fri Sep 27 03:00:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- * *.c: Use c_build_type_variant instead of build_type_variant where
- the type might be an array.
+ * decl.c (lookup_name_real): Don't try to look up anything in a
+ TYPENAME_TYPE.
- * call.c (build_method_call): Call build_type_variant and
- build_reference_type in the right order.
- * decl.c (record_builtin_type): Ditto.
+ * tinfo2.cc (__throw_type_match_rtti): Oops.
-Wed Jun 29 16:58:53 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Sep 26 22:11:05 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * call.c (build_method_call): Call build_type_variant and
- build_reference_type in the right order.
- * decl.c (record_builtin_type): Ditto.
+ * Make-lang.in (exception.o): Use -fno-PIC for now.
-Tue Jun 28 23:49:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Sep 26 10:59:00 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_binary_op): Use the types before default
- conversions in the error message.
+ * 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.
+
+ * rtti.c (build_typeid): Use resolves_to_fixed_type_p.
+ (build_x_typeid): Likewise.
- * *.c: Use c_build_type_variant instead of build_type_variant where
- the type might be an array.
+ * 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.
-Sat Jun 25 11:50:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Sep 25 17:26:16 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (convert_to_reference): Try UDC's before doing the
- reinterpret_cast thang, though.
+ * call.c (convert_like): Pull out constant values.
-Fri Jun 24 01:24:01 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * tree.c (mapcar): Use build_cplus_array_type, not build_array_type.
- * typeck.c (c_expand_return): Don't USE the return value location
- after we've expanded the jump.
+Wed Sep 25 17:28:53 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * decl2.c (finish_file): Make sure DECL_SAVED_INSNS is not 0 before
- trying to write out an inline.
+ * 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.
- * 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.
+Tue Sep 24 18:18:44 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jun 23 00:22:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (exception.o): Turn off pic.
- * decl2.c (finish_file): Use TREE_SYMBOL_REFERENCED to decide
- whether to emit inlines.
+ * tinfo2.cc (__throw_type_match_rtti): Fix cv-variants of the same
+ type, multi-level ptr conversions.
- * decl.c (grokdeclarator): Set explicit_int for decls that just
- specify, say, 'long'.
+ * 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.
- * init.c (do_friend): Do overload C functions (or call pushdecl,
- anyaway).
+ * Remove .h from standard C++ headers, add new.h, move into inc
+ subdirectory.
-Wed Jun 22 13:40:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * exception*: Remove pointer from object, constructors. Add
+ default exception::what that uses type_info::name. Add
+ __throw_bad_typeid.
- * 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_new): Don't add a cookie to new (void *) T[2].
- * tree.c (lvalue_p): Random CALL_EXPRs are not lvalues.
+Mon Sep 23 15:21:53 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * Make-lang.in: Building C++ code depends on cc1plus.
- * typeck2.c (build_functional_cast): Ditto.
+Mon Sep 23 12:38:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Jun 21 17:38:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (struct saved_scope): Declare PROCESSING_TEMPLATE_DECL as
+ a HOST_WIDE_INT, not a tree.
- * decl.c (grokdeclarator): signed, unsigned, long and short all
- imply 'int'.
+Mon Sep 23 12:36:02 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Allow "this is a type" syntax.
- (grok_reference_init): Simplify and fix.
+ * exception.cc: Don't include <stdlib.h>.
-Sun Jun 19 17:08:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * Make-lang.in (c++.clean): Remove cplib2.*.
- * decl.c (grokdeclarator): pedwarn about a typedef that specifies no
- type.
+Mon Sep 23 09:42:19 1996 Doug Evans <dje@canuck.cygnus.com>
-Sat Jun 18 04:16:50 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y (component_decl_1, component_costructor_declarator case):
+ Pass attributes/prefix_attributes in tree list.
- * decl.c (start_function): Move TREE_PUBLIC and DECL_EXTERNAL
- tinkering to after call to pushdecl.
+Mon Sep 23 01:18:50 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Jun 17 14:48:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * tinfo{,2}.cc: #include <stddef.h> instead of <stdlib.h>.
- * call.c (build_method_call): Handle destructors for non-aggregate
- types properly.
+Sun Sep 22 05:31:22 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Jun 16 16:48:05 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c (do_identifier): Don't do deferred lookup in a template
+ header.
- * call.c (build_method_call): Make sure that the name given for the
- destructor matches the constructor_name of the instance.
+ * typeck2.c (store_init_value): Oops.
- * pt.c (do_function_instantiation): A non-extern instantiation
- overrides a later extern one.
- (do_type_instantiation): Ditto.
+ * 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.
-Wed Jun 15 19:34:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sat Sep 21 19:17:28 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (expand_aggr_init): Use TYPE_MAIN_VARIANT to get the
- unqualified array type.
+ * 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.
- * cp-tree.h (EMPTY_CONSTRUCTOR_P): Tests whether NODE is a
- CONSTRUCTOR with no elements.
+Thu Sep 19 16:41:07 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * 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.
- * typeck2.c (process_init_constructor): Don't treat empty_init_node
- specially.
+ * 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.
-Wed Jun 15 19:05:25 1994 Mike Stump <mrs@cygnus.com>
+Wed Sep 18 13:30:20 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * class.c (override_one_vtable): Don't forget to merge in an old
- overrider when we wanted to reuse a vtable, but couldn't.
+ * lex.c (enum tree_node_kind) [GATHER_STATISTICS]: Put the enum back.
-Wed Jun 15 15:03:16 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Sep 18 04:24:07 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_decl): Put statics in common again.
+ * method.c (make_thunk): Call comdat_linkage before setting the
+ TREE_CODE.
- * decl.c (grokdeclarator): Return NULL_TREE for an error rather than
- setting the type to error_mark_node.
+ * 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.
- * typeck.c (build_modify_expr): Build up a COMPOUND_EXPR for enum
- bitfield assignments.
+Sat Sep 14 08:34:41 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Jun 14 12:23:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (grokfield): Tighten checking for access decls.
- * decl.c (grok_op_properties): Const objects can be passed by value.
+ * 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.
-Mon Jun 13 03:10:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * decl2.c (import_export_vtable): Force implicit instantiations to
- be interface_only when -fno-implicit-templates.
+Fri Sep 13 17:31:40 1996 Stan Shebs <shebs@andros.cygnus.com>
- * decl.c (duplicate_decls): Redeclaring a class template name is an
- error.
+ * mpw-make.sed: Fix include paths, add @DASH_C_FLAG@ to compile.
- * pt.c (end_template_decl): Call GNU_xref_decl for class templates.
- * xref.c (GNU_xref_decl): Support templates.
+Wed Sep 11 22:38:13 1996 Gerald Baumgartner <gb@cs.purdue.edu>
-Sat Jun 11 17:09:05 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_method_call): When calling a signature
+ default implementation, as in other cases, let instance_ptr simply
+ be instance.
- * 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.
+Wed Sep 11 22:14:44 1996 Mike Stump <mrs@cygnus.com>
- * search.c (dfs_debug_mark): Lose checks for DWARF_DEBUG and
- TREE_ASM_WRITTEN, as they are redundant.
+ * parse.y (simple_stmt): Cleanup and use do_poplevel ().
- * 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.
+Wed Sep 11 22:10:48 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * except.c (expand_start_catch_block): Add a pushlevel so that -g
+ works on hppa and SPARC.
-Fri Jun 10 00:41:19 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Sep 11 10:18:06 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (grokdeclarator): Set DECL_CONTEXT on static data members.
+ * typeck.c (build_indirect_ref): Catch PTR being an error_mark_node.
- * g++.c (main): Use -xc++-cpp-output for .i files.
+Mon Sep 9 19:51:14 1996 Gerald Baumgartner <gb@cs.purdue.edu>
- * 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.
+ * call.c (build_over_call): Check first whether DECL_CONTEXT exists
+ before testing whether it's a signature.
-Thu Jun 9 19:04:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sun Sep 8 16:06:57 1996 Gerald Baumgartner <gb@cs.purdue.edu>
- 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.
+ * 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.
- * 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.
+Thu Sep 5 16:51:28 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * 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 <brendan@lisa.cygnus.com>
+
+ * cvt.c (convert_to_reference): Use %#T, not %#D, for error.
+
+Wed Sep 4 17:16:09 1996 Bob Manson <manson@charmed.cygnus.com>
+
+ * 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 <mrs@cygnus.com>
-Wed Jun 8 20:48:02 1994 Mike Stump <mrs@cygnus.com>
+ * except.c (expand_exception_blocks): Always make sure USE and
+ CLOBBER insns that came at the end still do, the backend relies
+ upon this.
- * 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.
+Wed Sep 4 07:44:48 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * decl.c (grokdeclarator): Don't core dump when void() is given.
+
+Tue Sep 3 02:38:56 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * decl.c (copy_args_p): Don't crash.
+
+Fri Aug 30 14:26:57 1996 Mike Stump <mrs@cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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 <manson@charmed.cygnus.com>
+
+ * rtti.c (build_dynamic_cast): Don't try to dereference exprtype
+ too early. Make sure we explode if exprtype turns out to be a
+ NULL_TREE when it shouldn't be.
+
+Tue Aug 27 10:56:21 1996 Mike Stump <mrs@cygnus.com>
+
+ * 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 <mrs@cygnus.com>
-Wed Jun 8 16:18:14 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (groktypefield): Remove unused code.
- * 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.
+Mon Aug 26 17:00:33 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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 <jason@yorick.cygnus.com>
- * search.c (get_base_distance): Use IS_AGGR_TYPE_CODE to check for
- class type, not == RECORD_TYPE.
+ * decl.c (start_function): Only check interface_* for templates
+ with flag_alt_external_templates.
- * decl.c (grokdeclarator): Cope with grokfndecl returning NULL_TREE.
+ * call.c (build_new_op): Check for comparison of different enum types.
+ (build_over_call): Fix arg # output.
- * typeck2.c (report_case_error): #if 0 out.
- * lex.c (real_yylex): Lose RANGE.
- * parse.y: Ditto.
+ * typeck.c (build_component_ref): Handle pre-found TYPE_DECL.
-Tue Jun 7 18:17:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Aug 21 00:13:15 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (simple_stmt, case ranges): Use ELLIPSIS instead of RANGE.
+ * call.c (build_new_op): Check for erroneous args.
-Mon Jun 6 19:39:57 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_new_method_call): Add missing args to cp_error.
- * 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.
+ * tree.c (error_type): Dont print reference-to-array.
- * 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.
+ * typeck.c (convert_for_assignment): Don't say contravariance for
+ removing const.
-Fri Jun 3 02:10:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Aug 20 13:23:00 1996 Jason Merrill <jason@yorick.cygnus.com>
- Implement 'extern template class A<int>;' 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<int>;' syntax.
- * decl.c (start_function): Don't modify the settings of TREE_PUBLIC
- and DECL_EXTERNAL on explicit instantiations.
+ * call.c (build_over_call): Diagnose bad convs for `this'.
- * cvt.c (cp_convert): Replace constants with their values before
- converting.
- (cp_convert): Consistently use 'e' instead of 'expr'.
+ * lex.c (cons_up_default_function): Set DECL_ARTIFICIAL
+ on _ctor_arg.
-Thu Jun 2 03:53:30 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (convert_like): Handle bad convs.
+ (build_over_call): Handle bad convs better.
- * typeck2.c (build_x_arrow): Resolve OFFSET_REFs first.
+ * decl2.c: -fansi-overloading is now the default.
-Wed Jun 1 18:57:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_new_method_call): Check for erroneous args.
- * typeck2.c (digest_init): Handle initializing a pmf with an
- overloaded method.
- * typeck.c (build_ptrmemfunc): Handle overloaded methods.
+ * pt.c (instantiate_class_template): Propagate
+ TYPE_USES_MULTIPLE_INHERITANCE.
- * 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.
+Tue Aug 20 13:09:57 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (convert_arguments): Make sure type is not NULL before
- checking its TREE_CODE.
+ * call.c (enforce_access): Add static to routine.
-Wed Jun 1 17:40:39 1994 Mike Stump <mrs@cygnus.com>
+Sun Aug 18 14:35:54 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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 (build_user_type_conversion_1): Fix bad handling.
+ (compare_ics): Likewise.
- * 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)
+Sat Aug 17 21:54:11 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Make sure we have a DNAME set before we
- try to use it in an error.
+ * call.c (standard_conversion): Oops.
-Wed Jun 1 09:48:49 1994 Mike Stump <mrs@cygnus.com>
+Sat Aug 17 16:28:11 1996 Geoffrey Noer <noer@cygnus.com>
- * typeck.c (convert_arguments, convert_for_initialization): Don't
- strip NOP_EXPRs, when we are converting to a reference.
+ * g++.c: Update test for win32 (&& ! cygwin32).
-Wed Jun 1 01:11:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sat Aug 17 03:45:31 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): Don't dereference references when
- initializing them.
+ * 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.
- * decl2.c (grokfield): Don't check for grokdeclarator returning
- error_mark_node any more.
+Fri Aug 16 15:02:19 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (grokfndecl): Return NULL_TREE instead of error_mark_node.
- (start_method): Return void_type_node instead of error_mark_node.
+ * init.c (expand_vec_init): Use ptrdiff_type_node instead of
+ integer_type_node when computing pointer offsets.
- * typeck.c (build_modify_expr): Resolve offset refs earlier.
+Fri Aug 16 01:28:32 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue May 31 16:06:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * call.c (build_method_call): Resolve OFFSET_REFs in the object.
+Thu Aug 15 17:27:13 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * pt.c (instantiate_decl): Evaluate DECL_INITIAL of a VAR_DECL here.
+ (tsubst): Not here.
-Mon May 30 23:38:55 1994 Jason Merrill (jason@deneb.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.
- * decl.c (start_function): Set DECL_DEFER_OUTPUT on implicit
- instantiations and inline members.
+Thu Aug 15 17:09:54 1996 Mike Stump <mrs@cygnus.com>
- * spew.c (yylex): Set looking_for_template if the next token is a '<'.
+ * except.c (do_unwind): Mark %i7 as used on the SPARC so we can
+ optimize.
- * lex.h: Declare looking_for_template.
+Thu Aug 15 01:36:49 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (lookup_name_real): Use looking_for_template to arbitrate
- between type and template interpretations of an identifier.
+ * decl2.c (import_export_decl): Ignore #pragma interface for tinfo
+ fns of classes without virtual functions.
-Sat May 28 04:07:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (add_function_candidate): Handle `this' specially.
+ (compare_ics): Likewise.
- * pt.c (instantiate_template): Zero out p if we found a
- specialization.
+Tue Aug 13 12:16:10 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grokdeclarator): Elucidate warning.
- (grokdeclarator): If pedantic AND -ansi, complain about long long.
+ * typeck.c (build_conditional_expr): Fix handling of __null.
- 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.
+ * decl2.c (comdat_linkage): New fn.
+ (import_export_vtable): Use it.
+ (import_export_decl): Use it.
+ * method.c (make_thunk): Use it.
-Fri May 27 13:57:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Aug 12 00:09:18 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_binary_op_nodefault): Division by constant zero is
- an error.
+ * pt.c (end_template_decl): If we don't actually have parms, return.
+ * parse.y (template_header): Accept 'template <>'.
-Fri May 27 13:50:15 1994 Mike Stump <mrs@cygnus.com>
+ * errfn.c: Allow 5 args.
- * class.c (override_one_vtable): Don't modify things we don't own.
+Sun Aug 11 15:20:58 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri May 27 01:42:58 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.
- * 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.
-
- * call.c (convert_harshness): Dereference reference on rhs before
- proceeding, properly grok passing const things to non-const
- references.
+Fri Aug 9 14:36:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_unary_op): Soften error about taking the address
- of main() to a pedwarn.
+ * decl2.c (lang_decode_option): Allow -fansi-overloading.
- * lex.c (default_copy_constructor_body): Unambiguously specify base
- classes (i.e. A((const class ::A&)_ctor_arg) ).
- (default_assign_ref_body): Ditto.
+Thu Aug 8 17:04:18 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu May 26 13:13:55 1994 Gerald Baumgartner (gb@mexican.cygnus.com)
+ * 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.
- * decl2.c (grokfield): Don't complain about local signature
- method declaration without definition.
+ * 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.
- * 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.
+Thu Aug 8 17:48:16 1996 Michael Meissner <meissner@tiktok.cygnus.com>
- * call.c (build_method_call): Distinguish calling the default copy
- constructor of a signature pointer/reference from a signature
- member function call.
+ * decl2.c (import_export_vtable): Delete code that disabled vtable
+ heuristic on systems with ASM_OUTPUT_EXTERNAL.
-Thu May 26 12:56:25 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Aug 7 12:44:11 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokfield): Don't set TREE_PUBLIC on member function
- declarations.
+ * typeck.c (build_x_function_call): Handle static call context
+ better.
- * 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.
+ * decl.c (finish_function): Set the DECL_CONTEXT of the result to
+ the function, not its outer block.
-Wed May 25 14:36:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * decl.c (grokdeclarator): Handle initialization of static const
- members.
- (finish_decl): Ditto.
+ * 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.
- * decl2.c (grokfield): Allow initialization of static const members
- even when pedantic.
+Tue Aug 6 12:58:46 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokfield): Deal with grokdeclarator returning
- error_mark_node.
+ * 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.
- * decl.c (grok_ctor_properties): Return 0 for A(A) constructor.
- (grokfndecl): Check the return value of grok_ctor_properties.
- (start_method): Ditto.
+ * decl.c (grokparms): Don't check default args in templates.
- * parse.y (absdcl): Expand type_quals inline.
+Mon Aug 5 17:17:06 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue May 24 19:10:32 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (build_new_op): Fix args to build_unary_op.
+ (add_builtin_candidates): Don't call type_promotes_to on float.
- * decl.c (pushtag): Use IS_AGGR_TYPE rather than checking for a
- RECORD_TYPE.
+ * decl.c (grokparms): Check the type of the default arg.
-Tue May 24 18:09:16 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * cvt.c (build_new_op): Pass non-overloaded cases on rather than
+ returning NULL_TREE.
- * 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.
+ * 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.
-Tue May 24 00:22:04 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Aug 5 17:07:47 1996 Mike Stump <mrs@cygnus.com>
- * pt.c (tsubst): Use lookup_name_nonclass to find guiding decls, not
- lookup_name.
+ * 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.
- * call.c (build_overload_call_real): Don't immediately pick a
- function which matches perfectly.
+Mon Aug 5 13:46:28 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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').
+ * cvt.c (convert_like): Don't call build_cplus_new twice.
- * typeck.c (convert_arguments): Don't mess with i for methods.
- * call.c (build_method_call): Pass the function decl to
- convert_arguments.
+ * call.c, cp-tree.h, cvt.c, decl2.c, init.c, method.c, pt.c, typeck.c:
+ Control new overloading code with -fansi-overloading.
- * 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.
+Sun Aug 4 15:29:11 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon May 23 14:11:24 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * error.c (dump_char): Use TARGET_* for character constants.
+ * cvt.c (build_up_reference): Propagate INDIRECT_BIND to
+ recursive calls.
+ * typeck.c (complete_type): Propagate
+ TYPE_NEEDS_{CONSTRUCTING,DESTRUCTOR}.
-Mon May 23 13:03:03 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Sat Aug 3 14:05:07 1996 Jason Merrill <jason@yorick.cygnus.com>
- * tree.c (debug_no_list_hash): Make static.
+ * cvt.c (joust): More ?: kludging. Sigh.
+ (build_over_call): Don't try to synthesize global fns.
- * 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.
+ * search.c (lookup_conversions): Use binfo marking.
-Fri May 20 14:04:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sat Aug 3 12:33:42 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (grokdeclarator): Make warning about duplicate short, etc.
- a pedwarn.
+ * search.c (build_mi_matrix): Use the correct value of cid
+ when determining the new mi_size.
- * typeck.c (build_c_cast): Casting to function or method type is an
- error.
+Sat Aug 3 01:27:41 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Make warning for anonymous class with no
- instances a pedwarn.
+ * 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.
- * Makefile.in (stamp-parse): Expect a s/r conflict.
+Fri Aug 2 01:26:59 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): pedwarn about using a non-lvalue
- cast as an lvalue.
+ * 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.
-Thu May 19 12:08:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (build_new_function_call): Check for error args.
- * cvt.c (type_promotes_to): Make sure bool promotes to int rather
- than unsigned on platforms where sizeof(char)==sizeof(int).
+ * typeck.c (comptypes): Just check DERIVED_FROM_P, not UNIQUELY.
-Wed May 18 14:27:06 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * 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.
+ * 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.
- * 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.
+ * 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.
- * typeck.c (convert_for_assignment): Complain about changing
- the signedness of a pointer's target type.
+Thu Aug 1 16:45:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * 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.
- * typeck.c (convert_for_assignment): Don't complain about assigning
- a negative value to bool.
+Thu Aug 1 16:06:14 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (init_decl_processing): Make bool unsigned.
+ * lex.c (do_identifier): Don't use %O on IDENTIFIER_OPNAME_Ps, use
+ %D instead.
- * class.c (finish_struct): Allow bool bitfields.
+Thu Aug 1 15:24:02 1996 Mike Stump <mrs@cygnus.com>
-Wed May 18 12:35:27 1994 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
+ * except.c (expand_throw): Use maybe_build_cleanup_and_delete
+ instead of just maybe_build_cleanup so that we deallocate the
+ thrown object.
- * Make-lang.in (c++.install-man): Get g++.1 from $(srcdir)/cp.
+Thu Aug 1 15:18:00 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed May 18 03:28:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (finish_prevtable_vardecl): Make non-static for pt.c's use.
+ * cp-tree.h (finish_prevtable_vardecl): Add decl.
- * cvt.c (build_type_conversion): Lose special handling of
- truthvalues.
+Thu Aug 1 11:53:51 1996 Bob Manson <manson@charmed.cygnus.com>
- * search.c (dfs_pushdecls): Improve shadowing warning.
+ * 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.
-Tue May 17 13:34:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * init.c (build_delete): Throw away const and volatile on `this'.
+ * 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.
- * decl.c (finish_enum): Put the constants in TYPE_VALUES again,
- rather than the enumerators.
- (pushtag): s/cdecl/c_decl/g
+Wed Jul 31 09:57:05 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon May 16 23:04:01 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de)
+ * 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.
- * cp/typeck.c (common_type): Attribute merging.
- (comp_types): Utilise COMP_TYPE_ATTRIBUTES macro.
+ * 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.
- * cp/parse.y: Revamp attribute parsing.
+Tue Jul 30 13:06:13 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon May 16 01:40:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * decl.c (shadow_tag): Also check for inappropriate use of auto and
- register.
+ * decl.c (start_function): Statics are static even in a #pragma
+ interface file.
- * method.c (build_overload_name): Clarify that the illegal case is a
- pointer or reference to array of unknown bound.
+ * decl2.c (import_export_vtable): Disable vtable heuristic on
+ systems with ASM_OUTPUT_EXTERNAL.
- * error.c (dump_type_prefix): Print references to arrays properly.
+ * cvt.c (compare_ics): Fix comparison of PMEM_CONV and BASE_CONV.
+ (standard_conversion): No std conv to enum type.
- * typeck.c (various): Be more helpful in pointer
- comparison diagnostics.
+ * cvt.c (standard_conversion): Fix order of args to DERIVED_FROM_P
+ for ptm's.
- * tree.c (lvalue_p): MODIFY_EXPRs are lvalues again. Isn't this
- fun?
+ * cvt.c (reference_binding): Bind directly to a base subobject of
+ a class rvalue.
- * parse.y: Also catch an error after valid stmts.
+ * cvt.c (build_new_op): Enforce access control.
- * search.c (dfs_init_vbase_pointers): Don't abort because `this' is
- const.
+Tue Jul 30 09:22:53 1996 Bob Manson <manson@charmed.cygnus.com>
- * typeck.c (convert_for_initialization): If call to
- convert_to_reference generated a diagnostic, print out the parm
- number and function decl if any.
+ * typeck2.c (process_init_constructor): When scanning the
+ union for a named field, skip things that aren't FIELD_DECLs.
- * errfn.c (cp_thing): Check atarg1 to determine whether or not we're
- specifying a line, not atarg.
+ * 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.
- * tree.c (build_cplus_method_type): Always make `this' const.
+Mon Jul 29 15:48:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grokclassfn): If -fthis-is-variable and this function is
- a constructor or destructor, make `this' non-const.
+ * cvt.c (build_builtin_candidate): Stick a dummy conversion in if
+ it failed.
- * typeck.c (build_modify_expr): Don't warn specially about
- assignment to `this' here anymore, since it will be caught by the
- usual machinery.
+ * cvt.c (build_user_type_conversion_1): Handle overloaded
+ conversion ops.
- * 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.
+ * cvt.c (add_builtin_candidates): Don't consider type conversion
+ operators for the first parameter of operator=.
- * typeck2.c (build_functional_cast): Call build_method_call with
- LOOKUP_PROTECT.
- (process_init_constructor): Only process FIELD_DECLs.
+Mon Jul 29 15:33:55 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (finish_decl): Also force static consts with no explicit
- initializer that need constructing into the data segment.
+ * typeck.c (complete_type): Only call layout_type if we're not
+ expanding a template.
- * init.c (build_delete): Undo last patch, as it interferes with
- automatic cleanups.
+Mon Jul 29 14:40:38 1996 Jason Merrill <jason@yorick.cygnus.com>
-Sat May 14 01:59:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (compare_ics): Oops.
- * call.c, class.h, cp-tree.h, cvt.c, decl2.c: Lose old overloading
- code.
-
- * init.c (build_delete): pedwarn about using plain delete to delete
- an array.
-
-Fri May 13 16:45:07 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (op_error): Oops.
- * typeck.c (comp_target_types): Be more helpful in contravariance
- warnings, and make them pedwarns.
+ * 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 (grokdeclarator): Use decl_context to decide whether or not
- this is an access declaration.
+Mon Jul 29 12:05:40 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (finish_struct_bits): Set TYPE_HAS_INT_CONVERSION if it
- has a conversion to enum or bool, too.
+ * 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.
-Fri May 13 16:31:27 1994 Mike Stump <mrs@cygnus.com>
+Mon Jul 29 11:25:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * method.c (emit_thunk): Make declaration for
- current_call_is_indirect local (needed for hppa).
+ * 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.
-Fri May 13 16:16:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sat Jul 27 11:27:47 1996 Stan Shebs <shebs@andros.cygnus.com>
- * pt.c (uses_template_parms): Grok BOOLEAN_TYPE.
- (tsubst): Ditto.
+ * cvt.c (build_builtin_candidate): Init local var in an ANSI way.
-Fri May 13 16:23:32 1994 Mike Stump <mrs@cygnus.com>
+Fri Jul 26 01:07:22 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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 <mrs@cygnus.com>
-
- * 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 <mrs@cygnus.com>
-
- 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 <mrs@cygnus.com>
-
- * 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 (joust): If the candidates are the same, arbitrarily pick one.
- * call.c (build_method_call): Complain about calling an abstract
- virtual from a constructor.
+ * cvt.c (build_builtin_candidate): Oops.
+ (build_new_op): Oops.
- * typeck.c (pointer_int_sum): Check for the integer operand being 0
- after checking the validity of the pointer operand.
+ * 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.
- * typeck2.c (digest_init): Pedwarn about string initializer being
- too long.
+Thu Jul 25 09:33:33 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue May 10 12:10:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (complete_type): Call layout_type rather than building
+ a new array type.
- * decl.c (push_overloaded_decl): Only throw away a builtin if the
- decl in question is the artificial one.
+ * cvt.c (add_builtin_candidate): Pointer arithmetic candidates
+ only use ptrdiff_t.
- * parse.y (simple_stmt, switch): Use implicitly_scoped_stmt because
- expand_{start,end}_case cannot happen in the middle of a block.
+Wed Jul 24 12:45:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cvt.c (build_type_conversion_1): Use convert again.
+ * 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.
-Tue May 10 11:52:04 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Tue Jul 23 12:46:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck2.c (digest_init): Make sure we check for signed and
- unsigned chars as well when warning about string initializers.
+ * cvt.c (build_new_op): Support {MAX,MIN}_EXPR.
+ (add_builtin_candidate): Likewise.
- * init.c (emit_base_init): Check if there's a DECL_NAME on the
- member before trying to do an initialization for it.
+ 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.
-Tue May 10 11:34:37 1994 Mike Stump <mrs@cygnus.com>
+Mon Jul 22 16:21:55 1996 Bob Manson <manson@charmed.cygnus.com>
- * except.c: Don't do anything useful when cross compiling.
+ * pt.c (tsubst_expr): Handle CONTINUE_STMT.
-Tue May 10 03:04:13 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Jul 22 15:38:58 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (duplicate_decls): Fix up handling of builtins yet again.
- (push_overloaded_decl): Ditto.
+ * typeck.c (build_component_ref_1): Use build_component_ref
+ instead of open coding it here.
- * cvt.c (convert): Don't look for void type conversion.
+Mon Jul 22 12:18:54 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon May 9 18:05:41 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * g++.c (main): Don't link with -lg++.
- * init.c (do_friend): Only do a pushdecl for friends, not
- pushdecl_top_level.
+ 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.
-Mon May 9 13:36:34 1994 Jim Wilson (wilson@sphagnum.cygnus.com)
+Fri Jul 19 17:59:29 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * decl.c (lookup_name_current_level): Put empty statement after
- the label OUT to make the code valid C.
+ * error.c (dump_expr, case CONSTRUCTOR, case CAST_EXPR): Take out
+ invalid second argument to dump_expr_list.
-Mon May 9 12:20:57 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Jul 19 14:04:05 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (build_binary_op_nodefault): Only complain about
- comparing void * and a function pointer if void * is smaller.
+ * decl.c (lookup_name_real): Make sure we do obj->X::i correctly.
-Sun May 8 01:29:13 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Jul 18 14:48:23 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (lookup_name_current_level): Move through temporary binding
- levels.
+ * decl2.c (import_export_vtable): ASM_OUTPUT_EXTERNAL, not
+ ASSEMBLE_EXTERNAL.
- * parse.y (already_scoped_stmt): Revive.
- (simple_stmt): Use it again.
+Mon Jul 15 17:48:43 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (poplevel): Always call poplevel recursively if we're
- dealing with a temporary binding level.
+ * 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.
-Sat May 7 10:52:28 1994 Mike Stump <mrs@cygnus.com>
+Mon Jul 15 15:42:03 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * typeck.c (build_ptrmemfunc1): New function to hide details of
+ pointer to member functions better.
-Sat May 7 03:57:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Jul 15 14:23:02 1996 Mike Stump <mrs@cygnus.com>
- * typeck.c (commonparms): Don't complain about redefining default
- args.
+ * 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): Don't complain twice about conflicting
- function decls.
- (decls_match): Don't look at default args.
- (redeclaration_error_message): Complain about redefining default
- args.
+Mon Jul 15 13:08:29 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * call.c (build_overload_call_real): Also deal with guiding
- declarations coming BEFORE the template decl.
+ * parse.y (maybecomma_warn): Only emit the pedwarn if we're not
+ inside a system header.
- * pt.c (unify): Allow different parms to have different
- cv-qualifiers.
- (unify): Allow trivial conversions on non-template parms.
+Fri Jul 12 16:30:05 1996 Bob Manson <manson@charmed.cygnus.com>
-Fri May 6 03:53:23 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * call.c (build_method_call): Call complete_type on the
+ instance type.
- * pt.c (tsubst): Support OFFSET_TYPEs.
- (unify): Ditto.
+Thu Jul 11 17:16:40 1996 Mike Stump <mrs@cygnus.com>
- * decl2.c (finish_decl_parsing): Call push_nested_class with a type.
+ * 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.
- * init.c (build_offset_ref): Fix error message.
- * search.c (lookup_field): Ditto.
+Wed Jul 10 19:36:37 1996 Mike Stump <mrs@cygnus.com>
- * call.c (build_scoped_method_call): Pass binfo to
- build_method_call.
- * typeck.c (build_object_ref): Ditto.
+ * typeck.c (build_ptrmemfunc): Remove sorry, now we can cast
+ around things. Also improve maintainability.
- * typeck2.c (binfo_or_else): Don't return a _TYPE.
+Wed Jul 10 18:20:11 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (finish_struct): Don't complain about re-use of inherited
- names or shadowing of type decls.
- * decl.c (pushdecl_class_level): Ditto.
+ * decl.c (grokdeclarator): Check for overflow when evaluating an
+ array dimension.
- * decl.c (finish_enum): Set the type of all the enums.
+Wed Jul 10 17:26:19 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_struct): Don't get confused by access decls.
+ * cvt.c (cp_convert): Don't check for ambiguity with constructor
+ if NEW_OVER.
- * 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 (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 <mrs@cygnus.com>
+
+ * 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 <manson@charmed.cygnus.com>
+
+ * search.c (get_base_distance): Call complete_type.
- * 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'.
+Tue Jul 9 12:46:34 1996 Mike Stump <mrs@cygnus.com>
+
+ * decl.c (store_bindings): Make static.
- * 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.
+Mon Jul 8 16:42:31 1996 Jason Merrill <jason@yorick.cygnus.com>
- Fri May 6 07:18:54 1994 Chip Salzenberg (chip@fin)
+ * init.c (expand_aggr_init_1): Don't check type conversions if
+ NEW_OVER.
- [ 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 (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.
-Fri May 6 01:25:38 1994 Mike Stump <mrs@cygnus.com>
+ * decl.c (duplicate_decls): Propagate DECL_ONE_ONLY.
- Add alpha exception handling support to the compiler.
- Quick and dirty backend in except.c.
+Mon Jul 8 16:18:56 1996 Bob Manson <manson@charmed.cygnus.com>
- * 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.
+ * call.c (compute_conversion_costs): Call complete_type.
-Thu May 5 17:35:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * tree.c (vec_binfo_member): Use comptypes instead of comparing
+ pointers, so we can handle template parameters.
- * parse.y (simple_stmt, for loops): Use implicitly_scoped_stmt.
- (various): Lose .kindof_pushlevel and partially_scoped_stmt.
+Fri Jul 5 16:51:53 1996 Bob Manson <manson@charmed.cygnus.com>
-Thu May 5 16:17:27 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * 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.
- * parse.y (already_scoped_stmt): move expand_end_binding() to
- fix the unmatched LBB/LBE in stabs.
+Wed Jul 3 16:29:51 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu May 5 14:36:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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 (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).
+Mon Jul 1 22:58:18 1996 Bob Manson <manson@charmed.cygnus.com>
- 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.
+ * 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.
-Thu May 5 09:35:35 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Mon Jul 1 17:56:19 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * typeck.c (build_modify_expr): Warn about assignment to `this'.
+ 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.
-Wed May 4 15:55:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sat Jun 29 14:05:46 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_delete): Use the global operator delete when
- requested.
+ * 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 (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.
+ * init.c (expand_vec_init): Don't crash if decl is NULL.
- * class.c (finish_struct): Remove a couple of dependencies on
- language linkage.
+Fri Jun 28 11:52:51 1996 Stan Shebs <shebs@andros.cygnus.com>
- * 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.
+ * mpw-config.in: New file, configury for Mac MPW.
+ * mpw-make.sed: New file, makefile editing for MPW.
- * lex.c (cons_up_default_function): Don't set DECL_CLASS_CONTEXT to
- a const-qualified type.
+Thu Jun 27 15:18:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (push_overloaded_decl): Throw away built-in decls here.
- (duplicate_decls): Instead of here.
+ * pt.c (instantiate_class_template): Call repo_template_used.
-Wed May 4 15:27:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * search.c (lookup_conversions): Only lookup conversions in
+ complete types.
- * typeck.c (get_member_function_from_ptrfunc): Do The Right
- Thing (I hope) if we're using thunks.
+Thu Jun 27 12:59:53 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed May 4 13:52:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * parse.y (specialization): aggr template_type_name ';'.
- (named_class_head_sans_basetype): Use it.
- (explicit_instantiation): Ditto.
- (tmpl.2): Revert.
+Wed Jun 26 18:29:47 1996 Bob Manson <manson@charmed.cygnus.com>
- * cvt.c (build_type_conversion_1): Use convert_for_initialization,
- rather than convert, to do conversions after the UDC.
+ * init.c (build_vec_delete_1): Call complete_type.
- * cp-tree.h (SHARED_MEMBER_P): This member is shared between all
- instances of the class.
+Mon Jun 24 17:17:32 1996 Mike Stump <mrs@cygnus.com>
- * search.c (lookup_field): If the entity found by two routes is the
- same, it's not ambiguous.
+ * except.c (start_anon_func): Make sure anonymous functions are
+ never external.
-Wed May 4 12:10:00 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Fri Jun 21 15:10:58 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (lookup_name_real): Check for a NULL TREE_VALUE,
- to prevent the compiler from crashing ...
+ * decl.c (finish_function): If function_depth > 1, set nested.
-Wed May 4 11:19:45 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (grokbitfield): Revert Bob's change.
+ * class.c (finish_struct_1): Fix handling of named bitfield widths.
- * call.c (build_method_call): If we don't have an object, check
- basetype_path to figure out where to look up the function.
+Thu Jun 20 23:35:38 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (convert_for_initialization): Pass TYPE_BINFO (type) to
- build_method_call in case exp is NULL_TREE.
+ * 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.
-Tue May 3 16:02:53 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Thu Jun 20 14:08:40 1996 Bob Manson <manson@charmed.cygnus.com>
- 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.
+ * decl2.c (grokbitfield): Handle constant decls appropriately.
+ Give an appropriate error message now instead of spewing core
+ later.
-Tue May 3 09:20:44 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Jun 20 13:01:51 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * decl2.c: Don't turn on thunks by default for now.
-Mon May 2 23:17:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Jun 19 11:37:04 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (lookup_nested_tag): Lose.
+ * typeck.c (complete_type): Handle error_mark_node.
+ (common_type, OFFSET_TYPE): Handle template_type_parms.
- * decl2.c (grokfield): Set DECL_CONTEXT on TYPE_DECLs.
- (lookup_name_nonclass): Lose.
+Tue Jun 18 10:02:15 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * pt.c (instantiate_decl): If at_eof, call import_export_decl
+ regardless of DECL_INLINE.
- * 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.
+ * typeck.c (mark_addressable): Set TREE_ADDRESSABLE on CONSTRUCTORs.
-Mon May 2 19:06:21 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * class.c (finish_struct_bits): Copy TYPE_SIZE.
- * 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.
+ * 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.
-Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Jun 17 15:23:36 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (named_class_head_sans_basetype): Add "aggr
- template_type_name ';'" rule for forward declaration of
- specializations.
+ * 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.
-Mon May 2 15:02:11 1994 Jason Merrill (jason@deneb.cygnus.com)
+Sun Jun 16 12:33:57 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (instantiate_type): Deal with pmf's.
+ * decl2.c (finish_vtable_vardecl): Don't trust
+ TREE_SYMBOL_REFERENCED for vtables of local classes.
- * Make-lang.in (cc1plus): Don't depend on OBJS or BC_OBJS, since
- stamp-objlist does.
+Fri Jun 14 18:13:36 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (../cc1plus): Depend on OBJDEPS.
- (OBJDEPS): Dependency version of OBJS.
+ * pt.c (tsubst_copy): Handle operator T.
-Mon May 2 12:51:31 1994 Kung Hsu (kung@mexican.cygnus.com)
+Wed Jun 12 17:52:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * search.c (dfs_debug_mark): unmark TYPE_DECL_SUPPRESS_DEBUG, not
- DECL_IGNORED_P.
+ * init.c (build_delete): Move creation of PARMS inside test of
+ TYPE_HAS_DESTRUCTOR, since it's never used outside of that block.
-Fri Apr 29 12:29:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Jun 11 15:09:18 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (finish_struct): Clear out memory of local tags. And
- typedefs.
+ * typeck.c (build_conditional_expr): Don't assume that
+ the arguments to ?: are always pointers or records.
- * decl2.c (grokclassfn): Don't set DECL_CONTEXT to a cv-qualified
- type.
- * search.c (get_matching_virtual): Be more helpful in error message.
+Tue Jun 11 13:56:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * *: Use DECL_ARTIFICIAL (renamed from DECL_SYNTHESIZED).
+ * decl2.c (import_export_decl): Still emit static/weak/comdat
+ copies of inline template functions with -fno-implicit-templates.
- * lex.c (default_assign_ref_body): Expect TYPE_NESTED_NAME to work.
- (default_copy_constructor_body): Ditto.
+Tue Jun 11 11:42:13 1996 Bob Manson <manson@charmed.cygnus.com>
- * class.c (finish_struct): Don't gratuitously create multiple decls
- for nested classes.
+ * init.c (build_delete): Determine the complete basetype
+ path to the destructor we're calling.
-Thu Apr 28 23:39:38 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Jun 7 15:30:10 1996 Bob Manson <manson@charmed.cygnus.com>
- 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 (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.
-Thu Apr 28 16:29:11 1994 Doug Evans (dje@canuck.cygnus.com)
+Fri Jun 7 11:11:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * decl.c (finish_function): Do access control on base destructors.
-Thu Apr 28 02:12:08 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.
- * search.c (compute_access): No really, deal with static members
- properly. Would I lie to you?
+Fri Jun 7 10:37:33 1996 Mike Stump <mrs@cygnus.com>
- 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.
+ * 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.
- * decl.c (pushdecl): Back out Chip's last change.
-
- * decl.c (grok_op_properties): operators cannot be static members.
-
- * 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.
-
- * method.c (do_inline_function_hair): Don't put friends of local
- classes into global scope, either.
-
- * typeck2.c (build_functional_cast): Don't look for a function call
- interpretation.
-
-Thu Apr 28 15:19:46 1994 Mike Stump <mrs@cygnus.com>
-
- * cp-tree.h: disable use of backend EH.
-
-Wed Apr 27 21:01:24 1994 Doug Evans (dje@canuck.cygnus.com)
-
- * 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.
-
-Wed Apr 27 19:10:04 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * decl.c (xref_tag): not to use strstr(), it's not available on
- all platforms.
-
-Wed Apr 27 18:10:12 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct): Resolve yet another class/pmf confusion.
-
- * call.c (build_overload_call_real): Don't take the single-function
- shortcut if we're dealing with an overloaded operator.
-
-Wed Apr 27 17:35:37 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed Apr 27 15:36:49 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cvt.c (convert_to_reference): Don't complain about casting away
- const and volatile.
-
- * typeck.c (build_unary_op): References are too lvalues.
-
-Wed Apr 27 13:58:05 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Wed Apr 27 01:17:08 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * parse.y (unary_expr): Expand new_placement[opt] and
- new_initializer[opt] inline.
-
- * search.c (lookup_fnfields): Don't throw away the inheritance
- information here, either.
- (compute_access): Handle static members properly.
-
- * init.c (build_member_call): Always set basetype_path, and pass it
- to lookup_fnfields.
-
- * 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.
-
- * init.c (resolve_offset_ref): Don't cast `this' to the base type
- until we've got our basetype_path.
-
- * cp-tree.h (IS_OVERLOAD_TYPE): aggregate or enum.
-
- * cvt.c (build_up_reference): Use build_pointer_type rather than
- TYPE_POINTER_TO.
-
- * call.c (convert_harshness_ansi): Call type_promotes_to for reals
- as well.
-
- * 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.
-
-Tue Apr 26 23:44:36 1994 Mike Stump <mrs@cygnus.com>
-
- Finish off Apr 19th work.
-
- * 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.
-
-Tue Apr 26 12:45:53 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (build_function_call): Call build_function_call_real with
- LOOKUP_NORMAL.
-
- * *: Don't deal with TYPE_EXPRs.
-
- * tree.c (lvalue_p): If the type of the expression is a reference,
- it's an lvalue.
-
- * 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.
-
- * parse.y: Simplify and fix rules for `new'.
+Tue Jun 4 15:41:45 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (grok_op_properties): operator void is illegal.
+ * pt.c (tsubst_expr, case DECL_STMT): Don't pass
+ LOOKUP_ONLYCONVERTING at all for now.
-Mon Apr 25 02:36:28 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * parse.y (components): Anonymous bitfields can still have declspecs.
+Mon Jun 3 15:30:52 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushdecl): Postpone handling of function templates like we
- do C functions.
+ * method.c (emit_thunk): Pretend this is a FUNCTION_DECL for the
+ backend's benefit.
- * search.c (expand_indirect_vtbls_init): Fix infinite loop when
- convert_pointer_to fails.
+Mon Jun 10 18:58:19 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * except.c (expand_start_catch_block): Add a dummy region, if we
+ get an error, so that we can avoid core dumping later.
- * cp-tree.h: Declare flag_ansi.
+Fri May 31 14:56:13 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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.
- * tree.c (lvalue_p): A comma expression is an lvalue if its second
- operand is.
+Fri May 31 14:22:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * typeck.c (build_modify_expr): Don't use TREE_VALUE on a
+ TARGET_EXPR.
-Sun Apr 24 16:52:51 1994 Doug Evans (dje@canuck.cygnus.com)
+Wed May 29 17:04:33 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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.
-Sun Apr 24 16:52:51 1994 Doug Evans (dje@canuck.cygnus.com)
+Wed May 29 16:02:08 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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.
-Sun Apr 24 00:47:49 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 23 16:40:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushdecl): Avoid redundant warning on redeclaring function
- with different return type.
- (decls_match): Compare return types strictly.
+ * error.c (dump_expr, case CAST_EXPR): Handle T() properly.
-Fri Apr 22 12:55:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * cvt.c (build_type_conversion): Do try to convert through other
- pointers. This will fail if the class defines multiple pointer
- conversions.
+ * method.c (do_build_assign_ref): Remove obsolete check of
+ TYPE_HAS_ASSIGN_REF (basetype).
- * error.c (dump_type_prefix): Print out pointers to arrays properly.
- (dump_type_suffix): Ditto. (was 'int *[]', now 'int (*)[]')
+ * decl.c (grokfndecl): Diagnose user definition of
+ implicitly-declared methods.
- * typeck.c (build_unary_op): Disallow ++/-- on pointers to
- incomplete type.
+Thu May 23 12:13:08 1996 Bob Manson <manson@charmed.cygnus.com>
- * 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.
+ * 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.
- * cvt.c (convert_to_reference): Don't force arrays to decay here.
+ * 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.
- * tree.c (lvalue_p): A MODIFY_EXPR is an lvalue.
+Wed May 22 11:45:19 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (duplicate_decls): Don't assume that the decls will have
- types.
-
- Mon Apr 18 11:35:32 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ 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.
-
- Fri Apr 22 06:38:56 1994 Chip Salzenberg (chip@fin.uucp)
-
- * cp/typeck2.c (signature_error): Use cp_error for "%T".
-
- Mon Apr 18 11:59:59 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ 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.
-
- Mon Apr 18 11:55:18 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ 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.
-
- Mon Apr 18 11:48:49 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ 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.
-
- Mon Apr 18 11:24:00 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ 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.
-
- Sun Mar 6 19:43:39 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ cp/* changes propagated from c-* changes in 940304 snapshot ]
- * cp/decl.c (finish_decl): Issue warning for large objects,
- if requested.
-
- Sat Feb 19 22:20:32 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ 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.
-
- Tue Feb 8 09:49:17 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ 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.
+ * lex.c (real_yylex): Remove old-n-crufty #if 0 code for
+ determining types for constant values.
- Mon Dec 6 13:35:31 1993 Norbert Kiesel (norbert@i3.INformatik.rwth-aachen.DE)
-
- * cp/decl.c (finish_enum): Start from 0 when determining precision
- for short enums.
-
- Fri Dec 3 17:07:58 1993 Ralph Campbell (ralphc@pyramid.COM)
-
- * cp/parse.y (unary_expr): Look at $1 for tree_code rather than
- casting $$.
-
- Wed Nov 17 19:22:09 1993 Chip Salzenberg (chip@fin.uucp)
-
- * 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".
+ * 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.
- Wed Nov 17 19:17:18 1993 Chip Salzenberg (chip@fin.uucp)
+Wed May 22 09:33:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp/call.c (convert_harshness_ansi): Given an (e.g.) char
- constant, prefer 'const char &' to 'int'.
+ * cvt.c (build_expr_type_conversion): Adjust.
- Wed Feb 3 13:11:48 1993 Chip Salzenberg (chip@fin.uucp)
+Tue May 21 11:21:56 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp/class.c (finish_struct_methods): Handle multiple
- constructors in fn_fields list.
+ * call.c (build_method_call): Always convert 'this' to the
+ appropriate type.
-Fri Apr 22 12:48:10 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * 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.
- * 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.
+ * method.c (emit_thunk): Call temporary_allocation and
+ permanent_allocation around the ASM_OUTPUT_MI_THUNK case, too.
-Fri Apr 22 03:27:26 1994 Doug Evans (dje@cygnus.com)
+ * tree.c (build_cplus_array_type): Handle tweaking of
+ TYPE_MAIN_VARIANT here.
+ * typeck.c (common_type): Not here.
- * Language directory reorganization.
- See parent makefile.
+ * typeck.c (complete_type): Only try to complete an array type if
+ it has a domain.
-Thu Apr 21 18:27:57 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Mon May 20 14:55:59 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * decl.c (grokvardecl): Call complete_type.
+ (grokdeclarator): Call complete_type for PARM_DECLs.
-Thu Apr 21 00:09:02 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri May 17 16:41:17 1996 Jason Merrill <jason@yorick.cygnus.com>
- * lex.c (check_newline): Force interface_unknown on main input file.
+ * pt.c (instantiate_class_template): Re-set
+ CLASSTYPE_GOT_SEMICOLON after calling finish_struct_1.
- * 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 <mrs@cygnus.com>
-
- 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.
+Fri May 17 14:56:55 1996 Mike Stump <mrs@cygnus.com>
-Fri Apr 15 13:49:33 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * typeck.c (build_conditional_expr): Pedwarn on pointer/integer
- mismatch, and don't pedwarn on 0/function pointer mismatch.
+Fri May 17 13:13:51 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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.
- * decl2.c (grokfield): Complain about local class method declaration
- without definition.
+Fri May 17 11:02:41 1996 Mike Stump <mrs@cygnus.com>
-Fri Apr 15 13:19:40 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * init.c (emit_base_init): Make sure the partial EH cleanups live
+ on the function_obstack.
- * method.c (emit_thunk): Add extern declaration for
- current_call_is_indirect (needed for hppa).
+Thu May 16 15:29:33 1996 Bob Manson <manson@charmed.cygnus.com>
-Thu Apr 14 16:12:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * expr.c (do_case): Don't try to dereference null TREE_TYPEs
+ when checking for pointer types.
- 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.
-
- * class.c (finish_struct): It is legal for a class with no
- constructors to have nonstatic const and reference members.
-
-Thu Apr 14 07:15:11 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
-
- * decl.c (push_overloaded_decl): Avoid giving errors about
- built-ins, since duplicate_decls will have given warnings/errors
- for them.
-
-Thu Apr 14 03:45:12 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cvt.c (convert_to_reference): Warn about casting pointer type to
- reference type when this is probably not what they wanted.
-
-Wed Apr 13 13:12:35 1994 Per Bothner (bothner@kalessin.cygnus.com)
-
- * 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 Apr 13 00:22:35 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (grok_op_properties): If op new/delete get here with
- METHOD_TYPEs, do a revert_static_member_fn.
-
- * 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.
-
- * parse.y (component_decl_1, fn.def2): Revert rules for
- constructors.
- (component_decl_1, fn.def2): Use $1 instead of $$, since $$ is being
- clobbered.
-
- * decl.c (start_function): Only warn about `void main()' if pedantic
- || warn_return_type.
-
-Tue Apr 12 02:14:17 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- 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.
-
- * method.c (build_opfncall): Only pass one argument to global op
- delete.
-
- * call.c (build_method_call): Use TYPE_VEC_DELETE_TAKES_SIZE to
- decide how many arguments to use for vec delete.
-
- * 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 (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.
-
- * parse.y (nested_name_specifier_1): Lose rules for dealing with
- syntax errors nicely, since they break parsing of 'const i;'.
-
- * decl.c (lookup_name): if (got_scope == current_class_type)
- val = IDENTIFIER_CLASS_VALUE (name).
-
- * search.c (lookup_nested_tag): Look in enclosing classes, too.
-
- * spew.c (yylex): Only look one character ahead when checking for a
- SCOPE.
-
- * lex.c (check_newline): Read first nonwhite char before
- incrementing lineno.
-
- * decl.c (grokdeclarator): Don't claim that typedefs are variables
- in warning.
-
- * 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.
-
- * class.c (push_nested_class): Don't push into non-class scope.
-
- * decl.c (grokdeclarator): If an identifier could be a type
- conversion operator, but has no associated type, it's not a type
- conversion operator.
+Thu May 16 13:38:58 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (unify): Check for equality of constants better.
+ * pt.c (instantiate_class_template): Remove obsolete check for
+ access declarations.
- * decl.c (grokdeclarator): Don't complain about access decls.
+Thu May 16 13:34:15 1996 Mike Stump <mrs@cygnus.com>
-Sun Apr 10 02:39:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * decl.c (grokdeclarator): pedwarn about data definitions without
- types here.
+Thu May 16 13:15:43 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * call.c (default_parm_conversions): Factor out common code.
+ (build_method_call): Use it.
+ (build_overload_call_real): Use it.
- * search.c (lookup_field): Use cp_error.
+Wed May 15 14:46:14 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (nested_name_specifier_1): Don't check aggr/non-aggr type
- here; it breaks destructors for non-aggr types.
+ * 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.
- * 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.
+ * typeck.c (get_delta_difference): Handle virtual bases better.
- * 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.
+Tue May 14 16:37:37 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y: Stop calling see_typename so much.
+ * 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.
- * decl.c (lookup_name): Deal with TTPs and UPTs.
+Tue May 14 16:27:25 1996 Mike Stump <mrs@cygnus.com>
- * lex.c (real_yylex): Don't set looking_for_typename just because we
- saw a 'new'.
- (dont_see_typename): #if 0 out.
+ * 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.
- * 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.
+Tue May 14 12:47:47 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (nested_name_specifier_1): Accept TEMPLATE_TYPE_PARMs,
- too.
- (named_class_head_sans_basetype): Accept template types, too. Oops.
+ * cp-tree.h (LOOKUP_AGGR): Remove, unused.
+ * parse.y: Remove uses of LOOKUP_AGGR.
-Fri Apr 8 16:39:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue May 14 12:07:51 1996 Mike Stump <mrs@cygnus.com>
- * decl2.c (reparse_decl_as_expr1): Handle SCOPE_REFs.
+ * *.[chy]: Rename current_class_decl to current_class_ptr, and
+ C_C_D to current_class_ref.
- * parse.y: Lose START_DECLARATOR.
+Mon May 13 16:55:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (lookup_nested_tag): New function to scan CLASSTYPE_TAGS
- for a class.
+ * call.c (convert_harshness): Tighten up pointer conversions.
- * parse.y: Simplify fn.def2 and component_decl. Support 'enum
- A::foo' syntax. Catch invalid scopes better.
+Sat May 11 04:33:50 1996 Doug Evans <dje@canuck.cygnus.com>
- * parse.y, lex.c: lose TYPENAME_COLON.
+ * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
+ (finish_file): Likewise.
- * decl2.c (groktypefield): #if 0 out.
+Fri May 10 11:09:57 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (lookup_name): If the type denoted by got_scope is
- currently being defined, look in CLASSTYPE_TAGS rather than FIELDS.
+ * cvt.c (convert_fn_ptr): We don't use thunks for pmfs.
- * class.c (push_nested_class): Don't try to push into
- error_mark_node.
+ * method.c (emit_thunk): Set flag_omit_frame_pointer in default
+ code.
-Fri Apr 8 07:26:36 1994 Brendan Kehoe (brendan@lisa.cygnus.com)
+Thu May 9 18:18:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (stamp-parse): Update count of conflicts to 33.
+ * decl2.c: Turn on thunks by default where supported.
-Thu Apr 7 17:47:53 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue May 7 20:39:57 1996 Mike Stump <mrs@cygnus.com>
- 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.
+ * 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.
- * 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.
+Mon May 6 01:23:32 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * decl2.c (finish_file): Don't try to emit functions that haven't
+ been compiled.
- * gxxint.texi (Parser): Update.
+Fri May 3 09:30:13 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-tree.h (IS_AGGR_TYPE_CODE): Add UNINSTANTIATED_P_TYPE.
+ * decl2.c (finish_vtable_vardecl): Oops.
- * lex.h: Add decl for got_scope.
+ * 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.
- * lex.c (see_typename): Claim to be the lexer when calling
- lookup_name.
+Thu May 2 21:56:49 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (lookup_name): When called from the lexer, look at
- got_scope and looking_at_typename; otherwise don't.
+ * 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.
-Thu Apr 7 22:05:47 1994 Mike Stump <mrs@cygnus.com>
+Thu May 2 17:20:02 1996 Mike Stump <mrs@cygnus.com>
- 31th Cygnus<->FSF merge.
+ * except.c (init_exception_processing): Setup saved_in_catch.
+ (push_eh_cleanup): Reset __eh_in_catch.
+ (expand_start_catch_block): Set __eh_in_catch.
-Thu Apr 7 17:47:53 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu May 2 16:21:17 1996 Mike Stump <mrs@cygnus.com>
- * decl2.c (mark_vtable_entries): Call this to mark all the
- entries in the vtable addressable.
- (finish_decl_parsing): Handle SCOPE_REFs.
+ * 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.
- * 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.
+Thu May 2 11:26:41 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (compparms): Also allow t1 to be ... if strict == 0.
+ * decl.c (maybe_push_to_top_level): Clear out class-level bindings
+ cache.
-Thu Apr 7 16:17:50 1994 Mike Stump <mrs@cygnus.com>
+Wed May 1 11:26:52 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (build_vtable_entry): Fix breakage introduced Apr 5
- 17:48:41.
+ * decl2.c (finish_file): Also use sentries for vars with
+ DECL_ONE_ONLY or DECL_WEAK set (should any such happen to be
+ created).
-Wed Apr 6 16:05:10 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * lex.c (handle_cp_pragma): Disable #pragma
+ interface/implementation if SUPPORTS_ONE_ONLY > 1.
- * 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.
+Tue Apr 30 11:25:46 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (finish_file): Check TREE_PUBLIC||TREE_ADDRESSABLE
- rather than DECL_SAVED_INSNS before emitting inlines.
+ * method.c (emit_thunk): Wrap default case in
+ temporary/permanent_allocation.
-Wed Apr 6 13:06:39 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (make_thunk): Use DECL_ONE_ONLY.
+ (emit_thunk): Call assemble_end_function.
- * spew.c (init_spew): #if 0 out stuff used by arbitrate_lookup.
+Mon Apr 29 15:38:29 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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).
+ * decl2.c (import_export_vtable): Use DECL_ONE_ONLY.
+ (import_export_decl): Likewise.
+ (finish_prevtable_vardecl): Disable vtable hack if
+ SUPPORTS_ONE_ONLY > 1.
- * typeck.c (compparms): ... is only equivalent to non-promoting
- parms if we're not being strict.
+Mon Apr 29 14:32:47 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (empty_parms): Don't check flag_ansi || pedantic here.
+ * typeck.c (build_modify_expr): PREINCREMENT_EXPR and
+ PREDECREMENT_EXPRs take two arguments, not one.
- * decl.c (init_decl_processing): if (flag_ansi || pedantic)
- strict_prototypes_lang_c = strict_prototypes_lang_cplusplus;
+Mon Apr 29 00:27:53 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl2.c (grok_function_init): Don't set DECL_INITIAL on pure
+ * class.c (build_vtable_entry): Don't build thunks for abstract
virtuals.
-Tue Apr 5 17:48:41 1994 Per Bothner (bothner@kalessin.cygnus.com)
-
- 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.
-
- * 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,
-
- 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.
-
- * 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.)
-
-Wed Apr 6 10:53:56 1994 Mike Stump <mrs@cygnus.com>
-
- * class.c (modify_vtable_entries): Never reset the DECL_CONTEXT
- of a fndecl, as we might not be from that vfield.
+ * lex.c (real_yylex): Fix handling of __PRETTY_FUNCTION__ like C
+ frontend.
-Tue Apr 5 17:43:35 1994 Kung Hsu (kung@mexican.cygnus.com)
+Sat Apr 27 16:45:35 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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)
+ * class.c (set_rtti_entry): Use size_zero_node.
+ (build_vtable): Likewise.
-Tue Apr 5 17:23:45 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Sat Apr 27 14:48:57 1996 Jason Merrill <jason@phydeaux.cygnus.com>
- * 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.)
+ * class.c (finish_struct_1): Pass size_zero_node to set_rtti_entry.
+ (prepare_fresh_vtable): Likewise.
-Tue Apr 5 13:26:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Apr 26 13:14:14 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (YYDEBUG): Always define.
- * lex.c (YYDEBUG): Ditto.
+ * method.c (emit_thunk): Call mark_used on the target function.
-Mon Apr 4 11:28:17 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * call.c (build_method_call): Don't warn about pending templates.
- * class.c (finish_struct): backup out the change below, put the
- new change for the same purpose. The change below breaks code.
+Thu Apr 25 14:55:44 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * decl2.c (finish_file): Fix list walking logic.
-Sat Apr 2 03:12:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck2.c (check_for_new_type): Only warn if -pedantic.
- * 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)
-
- * 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.
-
-Thu Mar 31 19:50:35 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * call.c (build_method_call): Constructors can be called for
- const objects.
-
-Thu Mar 31 16:20:16 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * decl2.c (grok_func_init): do not abort as rtl for pur virtual
- fucntions. They can be defined somewhere else.
-
-Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de)
-
- * decl.c (init_decl_processing): Declare __builtin_return_address
- and __builtin_frame_address for C++ as well.
-
-Thu Mar 31 12:35:49 1994 Mike Stump <mrs@cygnus.com>
-
- * typeck2.c (store_init_value): Integral constant variables are
- always constant, even when doing -fpic.
-
-Sat Jan 23 23:23:26 1994 Stephen R. van den Berg (berg@pool.informatik.rwth-aachen.de)
-
- * decl.c (redeclaration_error_message): Pass the types to
- comptypes.
-
-Wed Mar 30 21:29:25 1994 Mike Stump <mrs@cygnus.com>
-
- Cures incorrect errors about pure virtuals in a class, when they
- have been overridden in a derived class.
-
- * search.c (get_abstract_virtuals): Reimplement.
- * search.c (get_abstract_virtuals_1): New routine.
-
-Wed Mar 30 14:10:04 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Apr 24 15:41:15 1996 Bob Manson <manson@charmed.cygnus.com>
- * pt.c (push_template_decls): Make the pushed level pseudo
- global.
+ * 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 (extdefs): Don't pop everything if the current binding
- level is pseudo_global.
+Wed Apr 24 00:36:21 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pop_everything): Stop on reaching a pseudo-global
- binding level.
+ * decl2.c (finish_file): Only use a sentry if the decl is public.
- * cp-tree.h (DECL_FUNCTION_MEMBER_P): Change to more reliable test.
-
- * decl.c (duplicate_decls): Only copy DECL_SOURCE_{FILE_LINE} if
- the old decl actually had an initializer.
-
- * {various}: Clean up gcc -W complaints.
-
- * cp-tree.h (DECL_FUNCTION_MEMBER_P): Currently defined to be
- (DECL_CONTEXT (NODE) != NULL_TREE).
-
- * parse.y (lang_extdef): Call pop_everything if necessary.
-
- * 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.
-
-Wed Mar 30 14:20:50 1994 Mike Stump <mrs@cygnus.com>
-
- Cures calling a more base base class function, when a more derived
- base class member should be called in some MI situations.
-
- * 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.
-
-Wed Mar 30 14:10:04 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (pushdecl): If pushing a C-linkage function, only do a
- push_overloaded_decl.
- (duplicate_decls): Standard overloading does not shadow built-ins.
-
-Tue Mar 29 00:54:18 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * pt.c (end_template_decl): Don't call push_overloaded_decl.
-
- * init.c (do_friend): Don't call push_overloaded_decl.
-
- * 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.
-
- * decl.c (start_function): If push_overloaded_decl returns an
- older version of the function, deal with it.
-
- * decl.c (start_function): Be sure only to push_overloaded_decl
- for non-members.
-
- * decl.c (grokfndecl): Put back clearing of DECL_CHAIN for
- methods.
- (start_function): Lose broken and redundant code for checking old
- decl.
+ * pt.c (tsubst_expr, DECL_STMT): If we don't have an initializer,
+ don't pass LOOKUP_ONLYCONVERTING.
- * init.c (add_friend): Give line numbers of both friend decls
- when warning about re-friending.
+Tue Apr 23 17:18:47 1996 Bob Manson <manson@charmed.cygnus.com>
- * 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.
+ * typeck.c (common_type): Fix the ARRAY_TYPE case so it
+ properly keeps track of const and volatile type modifiers.
- * call.c (build_method_call): Use brendan's candidate printing
- routine.
+Tue Apr 23 10:52:56 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (start_method): Methods defined in the class body are
- inline whether or not it's a template class.
+ * tree.c (cp_tree_equal): C++ version of simple_cst_equal.
+ * pt.c (comp_template_args): Use it.
-Mon Mar 28 16:39:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * rtti.c (get_tinfo_fn, build_dynamic_cast, expand_*_desc): Call
+ assemble_external for artificial function decls.
- * parse.y (initdcl0): Add "extern" to current_declspecs if
- have_extern_spec && ! used_extern_spcec.
+ * decl.c (cp_finish_decl): Oops.
- * tree.c (really_overloaded_fn): A fn with more than one
- overload.
+Mon Apr 22 17:28:27 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (end_template_decl): Use really_overloaded_fn.
+ * 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.
- * 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 Apr 22 15:32:45 1996 Bob Manson <manson@charmed.cygnus.com>
- * *.c: Stop using DECL_OVERLOADED, it being archaic.
- TREE_OVERLOADED should probably go, too.
+ * parse.y (empty_parms): Make sure we use C++-style prototypes
+ when we're declaring member functions.
-Mon Mar 28 14:00:45 1994 Ron Guilmette (rfg@netcom.com)
+Sun Apr 21 10:08:22 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (comp_target_types): Call comp_target_parms with
- strict == 1.
+ * Makefile.in (CONFLICTS): 16 s/r conflicts.
+ * parse.y (self_template_type): New nonterminal.
-Sun Mar 27 00:07:45 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Apr 18 08:56:54 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (empty_parms): Don't parse () as (...) in extern "C"
- sections if we're compiling with -ansi or -pedantic.
+ * decl.c (make_typename_type): Handle getting a TYPE_DECL for a
+ name.
+ * parse.y (base_class.1): Allow 'typename foo::bar'.
- * decl.c (decls_match): Don't treat (int) and (int&) as matching.
+ * 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.
- * decl2.c (grokfield): Don't pedwarn twice about initializing
- field.
+ * lex.c (check_for_missing_semicolon): Handle SELFNAME.
- * decl.c (push_overloaded_decl): Warn about shadowing
- constructor.
- (redeclaration_error_message): Don't allow 'int a; int a;'
+ * lex.c (handle_cp_pragma): Fix "#pragma implementation".
- * cvt.c (build_up_reference): Only check for valid upcast if
- LOOKUP_PROTECT is set, not just any flag.
+Wed Apr 17 16:51:33 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 25 01:22:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y: New token SELFNAME for potential constructor.
+ * spew.c (yylex): Handle it.
+ * lex.c (identifier_type): Produce it.
- * lex.c (check_newline): When we see a #pragma implementation,
- also set it for the main input file.
+ * parse.y (complete_type_name): In :: case, don't push class binding.
+ (complex_type_name): Likewise.
- * init.c (build_new): Convert array size argument to size_t.
+Wed Apr 17 15:02:40 1996 Mike Stump <mrs@cygnus.com>
- * parse.y (primary): If we're doing a parenthesized type-id, call
- groktypename before passing it to build_new.
-
- * call.c (build_method_call): Deal properly with const and
- volatile for instances of reference type.
-
- * decl.c (store_return_init): Change 'if (pedantic) error' to 'if
- (pedantic) pedwarn'.
-
- * decl.c (grokdeclarator): Don't complain about putting `static'
- and `inline' on template function decls.
-
-Thu Mar 24 23:18:19 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * call.c (build_method_call): Preserve const & volatile on
- `this'.
+ * typeck.c (build_reinterpret_cast): Handle pointer to member
+ functions.
-Thu Mar 24 16:21:52 1994 Mike Stump <mrs@cygnus.com>
+Wed Apr 17 12:28:26 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * init.c (build_new, build_vec_delete): Use global new and delete
- for arrays.
- * decl2.c (delete_sanity): Ditto.
+ * 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.
-Thu Mar 24 02:10:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Apr 17 10:28:34 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * cvt.c (cp_convert_to_pointer): Avoid doing base analysis on pmfs.
+ (convert_to_pointer_force): Likewise.
-Wed Mar 23 17:45:37 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (build_new): Fix array new without -fcheck-new.
- * decl.c (duplicate_decls): Also propagate DECL_TEMPLATE_MEMBERS
- and DECL_TEMPLATE_INSTANTIATIONS.
+Tue Apr 16 13:44:58 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_new): Handle array typedefs properly.
+ * cp-tree.h, call.c, class.c, decl.c, parse.y, pt.c, rtti.c,
+ tree.c: Lose TYPE_NESTED_NAME.
-Wed Mar 23 18:23:33 1994 Mike Stump <mrs@cygnus.com>
+ * parse.y (nested_name_specifier_1): Don't treat non-identifiers
+ as identifiers.
- 30th Cygnus<->FSF merge.
+ * 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.
-Wed Mar 23 00:46:24 1994 Mike Stump <mrs@cygnus.com>
+Mon Apr 15 16:21:29 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * method.c (make_thunk): Thunks are static.
+ (emit_thunk): Use ASM_OUTPUT_MI_THUNK if it's defined.
-Wed Mar 23 00:23:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (mark_vtable_entries): Emit thunks as needed.
+ (finish_file): Don't emit them here.
- * decl.c (duplicate_decls): If two template decls don't match,
- just return 0.
+Sun Apr 14 11:34:39 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Mar 22 23:49:41 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * rtti.c (build_dynamic_cast): Handle null pointers.
+ (ifnonnull): New function.
- * typeck.c (convert_for_assignment): Don't pedwarn about
- converting function pointer to void *.
+Fri Apr 12 09:08:27 1996 Bob Manson <manson@charmed.cygnus.com>
-Tue Mar 22 22:23:19 1994 Mike Stump <mrs@cygnus.com>
+ * 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.
- Major revamp of pointer to member functions. Cures major
- nonfunctionality when used in casts, and MI situations.
+ * search.c (expand_upcast_fixups): Mark the new fixup as
+ DECL_ARTIFICIAL.
- * 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.
+Thu Apr 11 03:57:09 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Mar 22 17:56:48 1994 Mike Stump <mrs@cygnus.com>
+ * init.c (build_new): Use a TARGET_EXPR for alloc_expr.
- * search.c (get_binfo): Return NULL instead of aborting, when
- passed a UNION_TYPE.
+ * class.c (set_rtti_entry): Fix for thunks.
-Tue Mar 22 12:44:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (import_export_decl): Still emit typeinfo fns for
+ cv-variants of builtin types.
- These patches implement handling of redefinition/redeclaration of
- templates.
+ * rtti.c (expand_class_desc): Set up base_info_type_node here.
+ (init_rtti_processing): Instead of here.
- * typeck.c (comptypes): Simplify. All TEMPLATE_TYPE_PARMs are
- considered compatible.
+Wed Apr 10 14:17:13 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (template_def): Pass defn argument to end_template_decl.
+ * rtti.c (init_rtti_processing): Do init regardless of -frtti.
+ (build_typeid): Only complain about taking dynamic typeid without
+ -frtti.
- * pt.c (end_template_decl): Add defn argument. Check for
- redefinition. Simplify.
+ * decl2.c: flag_rtti defaults to 1.
- * error.c (OB_UNPUT): New macro, to remove mistakes.
- (aggr_variety): Subroutine of dump_aggr_type.
+ * 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.
- * decl.c (decls_match): Support templates.
- (duplicate_decls): No longer static. Don't try to lay out template
- decls.
- (pushdecl): Simplify.
+Wed Apr 10 13:50:14 1996 Mike Stump <mrs@cygnus.com>
- * cp-tree.h (DECL_TEMPLATE_MEMBERS): Use DECL_SIZE instead of
- DECL_INITIAL.
+ * init.c (expand_member_init): Don't dump if name is NULL_TREE.
-Mon Mar 21 11:46:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Apr 10 12:56:02 1996 Mike Stump <mrs@cygnus.com>
- * error.c (dump_decl): Support class template decls.
- (dump_type): Don't adorn template type parms.
+ * 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.
- * 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.
+Tue Apr 9 23:06:09 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Mar 21 19:36:06 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * 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.
- * 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.
+Tue Apr 9 14:20:57 1996 Mike Stump <mrs@cygnus.com>
-Mon Mar 21 11:46:55 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.
- * parse.y (after_type_declarator1): Expand type_quals.
- (notype_declarator1): Ditto.
- (absdcl1): Ditto.
+Tue Apr 9 12:10:26 1996 Jason Merrill <jason@yorick.cygnus.com>
-Sat Mar 19 01:05:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * rtti.c (build_dynamic_cast): Handle downcasting to X* given
+ other X subobjects in the most derived type. Ack.
- * 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.
+ * 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.
- * parse.y (decl): Change direct_* back to *.
- (type_id): Change direct_abstract_declarator to absdcl.
- (direct_declarator, direct_initdecls, direct_initdcl0): Remove again.
+Mon Apr 8 17:23:23 1996 Bob Manson <manson@charmed.cygnus.com>
-Fri Mar 18 12:47:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst): When calling set_nested_typename, use
+ TYPE_NESTED_NAME (current_class_type) instead of
+ current_class_name.
- These two patches fix crashes on instantiating a template inside a
- function with C linkage or containing labels.
+ * 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 <jason@yorick.cygnus.com>
- * class.c (current_lang_stacksize): No longer static.
-
- * 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.
-
- * gxxint.texi (Parser): Update.
-
- 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.
+ * rtti.c (synthesize_tinfo_fn): Handle arrays.
+
+ * cp-tree.h (DECL_REALLY_EXTERN): New macro.
+
+Sat Apr 6 13:56:27 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * 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 <typeinfo>.
+
+Fri Apr 5 17:02:09 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ RTTI rewrite to initialize nodes as needed, not require that
+ users #include <typeinfo>, complete functionality and reduce wasted
+ 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.
- * 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.
+ * lex.c (cons_up_default_function): Use the type, not the name, in
+ declspecs.
- * spew.c (yylex): #if 0 out START_DECLARATOR insertion.
+ * decl2.c (import_export_vtable): Fix weak vtables.
- 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.
+Fri Apr 5 13:30:17 1996 Bob Manson <manson@charmed.cygnus.com>
- * spew.c (arbitrate_lookup): #if 0 out.
+ * search.c (get_base_distance_recursive): Fix access checks for
+ protected bases.
- * decl.c (lookup_name): Never call arbitrate_lookup.
+Fri Apr 5 11:02:06 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * parse.y (complex_notype_declarator1): Add '*'
- complex_notype_declarator1 and '&' complex_notype_declarator1 rules.
+ * 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 (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 Apr 4 13:33:10 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Mar 17 17:30:01 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- 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.
+Thu Apr 4 11:00:53 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * rtti.c (build_dynamic_cast): Make sure we strip qualifiers on
+ cast to pointer types for type searching.
- * 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?
+Wed Apr 3 17:10:57 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Mar 17 12:16:10 1994 Mike Stump <mrs@cygnus.com>
+ * typeck.c (get_delta_difference): Use cp_error, not error, in the
+ case where BINFO == 0.
- These changes break binary compatibility in code with classes
- that use virtual bases.
+Wed Apr 3 12:01:02 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * call.c (build_method_call): Fix wording of error messages so
+ constructors come out right.
-Thu Mar 17 12:01:10 1994 Jason Merrill (jason@deneb.cygnus.com)
+Tue Apr 2 16:06:59 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y: s/ typename / type_id /g
+ * 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.
-Wed Mar 16 17:42:52 1994 Kung Hsu (kung@mexican.cygnus.com)
+Mon Apr 1 09:03:13 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y (typespec): add SCOPE TYPENAME for global scoped
- type. e.g. ::B x.
+ * class.c (finish_struct_1): Propagate the TYPE_PACKED
+ flag for the type to the type's fields.
- * decl.c (complete_array_type): fix a bug that in -pendantic
- mode even there's no initializer, it will continue to build
- default index.
+Sat Mar 30 12:14:33 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Mar 16 17:43:07 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y (complex_parmlist, ELLIPSES): Take out ARM-based warning.
- * parse.y (direct_notype_declarator): Add PTYPENAME rule, remove
- all of the scoped PTYPENAME rules.
+Fri Mar 29 15:51:36 1996 Bob Manson <manson@charmed.cygnus.com>
-Wed Mar 16 16:39:02 1994 Mike Stump <mrs@cygnus.com>
+ * class.c (base_info, finish_base_struct): Replace
+ needs_virtual_dtor with base_has_virtual.
- * init.c (build_offset_ref): The value of A::typedef_name is
- always the TYPE_DECL, and never an error.
+ (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.
-Tue Mar 15 20:02:35 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Mar 29 14:02:36 1996 Jason Merrill <jason@yorick.cygnus.com>
- * search.c (get_base_distance_recursive): Two binfos can only
- represent the same object if they are both via_virtual.
+ * pt.c (push_template_decl): Complain about template decl with
+ inappropriate declaration.
- * class.c (finish_base_struct): Check vbases for ambiguity, too.
+Fri Mar 29 12:15:35 1996 Bob Manson <manson@charmed.cygnus.com>
- * search.c (get_vbase_types): Accept binfo argument, too.
+ * typeck.c (build_x_unary_op): Remove bogus check for taking
+ the address of a member function.
-Tue Mar 15 19:22:05 1994 Kung Hsu (kung@mexican.cygnus.com)
+Fri Mar 29 11:56:02 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (complete_array_type): complete TYPE_DOMAIN of the
- initializer also, because back-end requires it.
+ * parse.y (constructor_declarator): Only push the class if
+ we are not already in the class.
-Tue Mar 15 15:33:31 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Mar 29 09:41:02 1996 Jeffrey A. Law <law@cygnus.com>
- * error.c (dump_expr): Support member functions (which show up as
- OFFSET_REFs).
+ * method.c (emit_thunk): Remove current_call_is_indirect nonsense.
+ Add additional argument to INIT_CUMULATIVE_ARGS.
-Mon Mar 14 16:24:36 1994 Mike Stump <mrs@cygnus.com>
+Thu Mar 28 16:41:39 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_new): Set the return type of multidimensional
- news correctly.
+ * decl.c (shadow_tag): Fix error about anon union with methods.
-Fri Mar 11 15:35:39 1994 Kung Hsu (kung@mexican.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.
- * call.c (build_method_call): if basetype not equal to type
- of the instance, use the type of the instance in building
- destructor.
+ * parse.y (component_decl_1): Use constructor_declarator.
+ (fn.def2): Likewise.
+ (notype_component_declarator0): Likewise.
-Thu Mar 10 17:07:10 1994 Kung Hsu (kung@mexican.cygnus.com)
+Thu Mar 28 15:11:35 1996 Bob Manson <manson@charmed.cygnus.com>
- * parse.y (direct_notype_declarator): add push_nested_type for
- 'template_type SCOPED_NAME' rule.
+ * 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.
-Tue Mar 8 00:19:58 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Mar 28 14:49:26 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (parm): Add typed_declspec1 {absdcl, epsilon} rules.
+ * pt.c (process_template_parm): Allow template type parms to be
+ used as types for template const parms.
-Sat Mar 5 04:47:48 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Mar 27 15:51:19 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * init.c (expand_vec_init): Ensure the eh cleanups are on the
+ function_obstack.
-Fri Mar 4 18:22:39 1994 Jason Merrill (jason@deneb.cygnus.com)
+Wed Mar 27 10:14:30 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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".
+ * 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.
- * decl2.c (reparse_decl_as_expr): Recursive function to change
- parse nodes for `A()()' from "function returning function returning
- A" to "A().operator()".
+ * parse.y (constructor_declarator): New nonterminal.
+ (fn.def1): Use it.
+ (explicit_instantiation): Likewise.
- * 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.
+Tue Mar 26 13:41:33 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 4 16:18:03 1994 Mike Stump <mrs@cygnus.com>
-
- * tree.c (lvalue_p): Improve OFFSET_REF handling, so that it
- matches Section 5.5.
+ 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.
-Fri Mar 4 14:01:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (do_function_instantiation): Separate handling of member
+ functions and non-member functions properly.
- * error.c (dump_type_prefix): Don't print basetype twice for
- pmfs.
+Mon Mar 25 14:23:22 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Mar 4 13:24:33 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (process_template_parm): Improve error for 'volatile class K'.
- * typeck.c (convert_arguments): Handle setHandler(A::handlerFn)
- so that it is like setHandler(&A::handlerFn). Cures an `invalid
- lvalue in unary `&''.
+ * class.c (finish_struct_1): Check the right slot for destructors.
-Fri Mar 4 11:15:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (start_enum): Complain about enum templates.
- * gxxint.texi (Copying Objects): New section discussing default
- op= problems with virtual inheritance.
+Mon Mar 25 13:25:31 1996 Mike Stump <mrs@cygnus.com>
- * decl2.c (grokoptypename): Just does grokdeclarator and
- build_typename_overload, since the parser can't call grokdeclarator
- directly.
+ * init.c (resolve_offset_ref): Offset pointers to member data by one.
+ * typeck.c (unary_complex_lvalue): Likewise.
- * method.c (build_typename_overload): Set IDENTIFIER_GLOBAL_VALUE
- and TREE_TYPE on generated identifiers.
+Mon Mar 25 13:30:42 1996 Bob Manson <manson@charmed.cygnus.com>
- * decl.c (grokdeclarator): Don't deal with TYPE_EXPRs anymore.
+ * typeck.c (c_expand_return): Check for a returned local
+ array name, similar to the check for an ADDR_EXPR.
- * parse.y (parm): Convert `const char *' to `__opPCc' here.
+Mon Mar 25 13:07:19 1996 Jason Merrill <jason@yorick.cygnus.com>
- * error.c (dump_decl): Say sorry rather than my_friendly_aborting
- if we can't figure out what to do.
- (dump_type*): Ditto.
+ * decl.c (cp_finish_decl): Don't build cleanups for static
+ variables here.
- * 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.
+Fri Mar 22 17:57:55 1996 Mike Stump <mrs@cygnus.com>
-Fri Mar 4 04:46:05 1994 Mike Stump <mrs@cygnus.com>
+ * 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.
- * 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 `&''.
+Fri Mar 22 13:48:29 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Mar 3 12:38:15 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * parse.y: Add precedence specification for START_DECLARATOR.
- (type_quals): Move before primary.
- (typename): Move before typed_declspecs, add 'typespec absdcl1' rule.
+ * pt.c (tsubst, case TYPE_DECL): Set DECL_CONTEXT.
- * decl2.c (grokoptypename): Lose.
+ * typeck.c (require_complete_type): Be sure to instantiate the
+ MAIN_VARIANT of the type.
- * decl.c (grokdeclarator): Parse TYPE_EXPRs in the initial scan,
- rather than waiting until later.
+ * decl2.c (finish_file): Instantiate pending templates before
+ processing static constructors and destructors.
-Wed Mar 2 14:12:23 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (instantiate_decl): Don't instantiate functions at toplevel
+ unless at_eof.
- * 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.
+Fri Mar 22 09:30:17 1996 Bob Manson <manson@beauty.cygnus.com>
- * 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 (delete_sanity): If error_mark_node is passed
+ in as an expression, quit while we're ahead.
- * 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.
+ * decl.c (grokdeclarator): Give an error message if `friend'
+ is combined with any storage class specifiers.
- * parse.y (absdcl1): Don't require parens around
- abs_member_declarator.
- (abs_member_declarator): Lose see_typename from rules.
- (after_type_member_declarator): Ditto.
+Wed Mar 20 14:51:55 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * parse.y (named_complex_class_head_sans_basetype): Don't crash on
+ definition of nonexistent nested type.
- * 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.
+ * error.c (dump_decl, case TYPE_DECL): Fix decision for whether or
+ not to say 'typedef'.
-Wed Mar 2 14:29:18 1994 Jason Merrill (jason@cygnus.com)
+Wed Mar 20 00:11:47 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cvt.c (build_up_reference): If we aren't checking visibility,
- also allow base->derived conversions.
+ * 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.
-Mon Feb 28 15:14:29 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Tue Mar 19 17:56:03 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_c_cast): Remove bogus hack when converting
- to a reference type.
+ * except.c (build_throw): Support minimal parse.
+ * pt.c (tsubst_copy): Support THROW_EXPR.
+ * decl2.c (build_expr_from_tree): Likewise.
- * 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.
+ * pt.c (mangle_class_name_for_template): Always allocate
+ scratch_firstobj.
- * 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.
+Tue Mar 19 16:34:31 1996 Bob Manson <manson@beauty.cygnus.com>
-Mon Feb 28 14:54:13 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * cvt.c (cp_convert_to_pointer): Give an appropriate error
+ when trying to cast from an incomplete type.
- * parse.y (component_decl): Don't include "typed_declspecs
- declarator ';'" speedup, since it breaks enums.
+Tue Mar 19 16:00:33 1996 Jason Merrill <jason@yorick.cygnus.com>
-Fri Feb 25 15:43:44 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * pt.c (instantiate_class_template): Don't bother setting up
+ CLASSTYPE_TAGS explicitly, as the nested types will add
+ themselves.
- * class.c (finish_struct): Minor optimization for building
- fn_fields list.
+Tue Mar 19 15:48:43 1996 Bob Manson <manson@beauty.cygnus.com>
-Fri Feb 25 15:23:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * decl.c (start_function): Fix detection of function overloading.
+Tue Mar 19 09:21:35 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 24 22:26:19 1994 Mike Stump <mrs@cygnus.com>
+ * lex.c (do_identifier): Only do name consistency check if we're
+ parsing.
- * 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.
+ * pt.c (push_template_decl): Don't crash if we get a member defn
+ that doesn't match.
-Thu Feb 24 17:09:01 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * parse.y (components): Handle list of one again.
- (notype_components): Ditto.
- (after_type_declarator1): Take maybe_raises out again.
+ * typeck2.c (build_functional_cast): Pull out a single parm before
+ passing it to build_c_cast.
- * gxxint.texi (Parser): Document additional r/r conflict.
+Tue Mar 19 09:07:15 1996 Bob Manson <manson@beauty.cygnus.com>
-Wed Feb 23 14:42:55 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * expr.c (do_case): Give an error message if a pointer is
+ given as a case value.
- * gxxint.texi (Parser): Add node.
+Mon Mar 18 21:57:54 1996 Jason Merrill <jason@yorick.cygnus.com>
- * Makefile.in (stamp-parse): Update expected conflict count.
+ * typeck.c (build_c_cast): Don't pull single TEMPLATE_DECL out of
+ an overload list.
- * 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.
+ * lex.c (cons_up_default_function): Really, now, interface hackery
+ does not apply to synthesized methods.
- (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.
+Mon Mar 18 18:20:57 1996 Mike Stump <mrs@cygnus.com>
- (named_class_head): Move intermediate code block into separate
- nonterminal so that we can stick %prec EMPTY on it.
+ * 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 <mrs@cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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.
- Add more %prec EMPTY's to eliminate remaining shift/reduce
- conflicts.
+ * tree.c (min_tree_cons): Call copy_to_permanent for the purpose
+ and value.
- (after_type_declarator): Add maybe_raises to fndecl rules.
- (after_type_declarator_no_typename): Remove.
- For correctness.
+Mon Mar 18 11:25:52 1996 Bob Manson <manson@beauty.cygnus.com>
- Document remaining reduce/reduce conflicts.
+ * method.c (build_opfncall): When deleting a pointer to an
+ array, build a new pointer to the tree past any ARRAY_TYPE
+ nodes.
-Tue Feb 22 12:10:32 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Mar 18 10:11:46 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * search.c (get_base_distance): Only bash BINFO_INHERITANCE_CHAIN
- (TYPE_BINFO (type)) if we care about the path.
+ * decl.c (lookup_name_real): Initialize local var TYPE to NULL_TREE.
- * tree.c (lvalue_p): A COND_EXPR is an lvalue if both of the
- options are.
+Fri Mar 15 11:03:57 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Feb 21 19:59:40 1994 Mike Stump <mrs@cygnus.com>
+ * pt.c (instantiate_decl): Only call import_export_decl if at_eof
+ and ! DECL_INLINE.
- * Makefile.in (mostlyclean): lex.c is a source file, don't
- remove.
+ * 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.
-Sat Feb 19 01:27:14 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (build_expr_from_tree): If a unary op already has a
+ type, just return it.
- * parse.y: Eliminate 20 shift/reduce conflicts.
+ * decl2.c (finish_prevtable_vardecl): Use ADJUST_VTABLE_LINKAGE.
-Fri Feb 18 11:49:42 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * 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.
+ * 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.
- * 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.
+Thu Mar 14 10:00:19 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_overload_call_real): Pass subr argument to
- type_unification.
- * pt.c (do_function_instantiation): Ditto.
- * class.c (instantiate_type): Ditto.
+ * cp-tree.h: Lose SIGNATURE_GROKKING_TYPEDEF.
- * search.c (get_base_distance): If BINFO is a binfo, use it and
- don't mess with its BINFO_INHERITANCE_CHAIN.
+ * decl.c (grokdeclarator): Lose special handling of class-level
+ typedef. Lose SIGNATURE_GROKKING_TYPEDEF. Set
+ SIGNATURE_HAS_OPAQUE_TYPEDECLS later.
- * cvt.c (convert_to_reference): Fix temporary generation.
- If ambiguous, return error_mark_node.
+ * cvt.c (convert_pointer_to_real): Retain cv-quals in conversion.
- * init.c (build_new): Put back some necessary code.
+ * pt.c (tsubst_copy): Strip cv-quals from destructor name types.
-Thu Feb 17 15:39:47 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * init.c (build_new): Deal with array types properly.
+ * typeck.c (build_x_function_call): For static member functions,
+ hand off to build_member_call.
- * 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.
+Wed Mar 13 14:03:34 1996 Jason Merrill <jason@yorick.cygnus.com>
- * parse.y (explicit_instantiation): Syntax is 'template class
- A<int>', not 'template A<int>'.
+ * typeck.c (build_component_ref): Handle OFFSET_REFs.
- * typeck.c (convert_for_initialization): Remove bogus warning.
+ * init.c (expand_vec_init): Fix init == 0 case.
- * parse.y (datadef): Revert patch of Oct 27.
+Tue Mar 12 14:36:02 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 17 15:12:29 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * init.c (build_new): Pedwarn about init and array new.
+ (expand_vec_init): Handle lists, use convert_for_initialization
- * class.c (build_vfn_ref): Cast delta field to ptrdiff_type_node,
- rather than integer_type_node. Does wonders for the Alpha.
+ * typeck.c (convert_for_initialization): Pass LOOKUP_NO_CONVERSION
+ when converting to an aggregate type.
+ * cvt.c (cp_convert): Pass it through.
-Thu Feb 17 13:36:21 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck.c (build_conditional_expr): Handle user-defined
+ conversions to slightly different types.
- * decl.c (build_ptrmemfunc_type): Make sure that the pmf type
- goes onto the same obstack as its target type.
+ * decl.c (grokdeclarator): Force an array type in a parm to be
+ permanent.
-Wed Feb 16 00:34:46 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (do_using_directive): Sorry.
+ (do_namespace_alias): Likewise.
+ * lex.c (real_yylex): Warn about using the `namespace' keyword.
- * cvt.c (convert_to_reference): If converting via constructor
- on local level, go back to build_cplus_new approach.
+Sun Mar 10 22:26:09 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * parse.y (datadef): Move call to note_list_got_semicolon up.
- * lex.c (default_assign_ref_body): Return *this from the memcpy
- version, too.
+Fri Mar 8 11:47:26 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (grok_reference_init): Just return if called with
- error_mark_node, don't worry about initializing non-const reference
- with temporary.
+ * tree.c (unsave_expr): Don't unsave, UNSAVE_EXPRs.
- * cvt.c (convert_to_reference): Do the right thing for
- non-aggregate reference conversions, pedwarn when generating a
- non-const reference to a temporary.
+Fri Mar 8 11:29:06 1996 Mike Stump <mrs@cygnus.com>
- * class.c (finish_struct): TYPE_HAS_COMPLEX_{INIT,ASSIGN}_REF and
- TYPE_NEEDS_CONSTRUCTING all depend on TYPE_USES_VIRTUAL_BASECLASSES
- again.
+ * 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.
-Tue Feb 15 19:47:19 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Mar 7 17:46:06 1996 Mike Stump <mrs@cygnus.com>
- * decl.c (grok_reference_init): Pawn off a lot of the work on
- convert_to_reference. Generally do the right thing.
+ * tree.c (vec_binfo_member): Don't core dump if we have no bases.
- * 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.
+Thu Mar 7 14:11:49 1996 Jason Merrill <jason@yorick.cygnus.com>
- * call.c (build_method_call): Set TREE_HAS_CONSTRUCTOR on
- constructor calls.
+ * tree.def: Add RETURN_INIT.
+ * pt.c (instantiate_decl): Handle RETURN_INIT.
+ * decl.c (store_return_init): Handle minimal_parse_mode.
-Mon Feb 14 14:50:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * decl.c (grok_reference_init): Make a temporary for initializing
- const reference from constant expression.
+Wed Mar 6 18:47:50 1996 Per Bothner <bothner@kalessin.cygnus.com>
-Mon Feb 14 11:31:31 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * decl.c (poplevel): Make sure we clear out and restore old local
+ non-VAR_DECL values by default when they go out of scope.
- * 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).
+Wed Mar 6 09:57:36 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * method.c (build_overload_value): Use DECL_ASSEMBLER_NAME in
+ referring to addresses of variables and functions.
- * 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.
+ * error.c (dump_expr): Support SIZEOF_EXPR.
-Sun Feb 13 19:04:56 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (do_friend): Use the return value of check_classfn.
- * class.h (candidate): Add basetypes field.
+ * typeck.c (convert_arguments): Call complete_type.
- * call.c (build_method_call): Do access checking after choosing a
- function, not before.
+ * method.c (hack_identifier): After giving an error, set value to
+ error_mark_node.
- * Makefile.in (cvt.o, call.o, method.o): Depend on class.h.
- (mostlyclean): Remove ../cc1plus.
+Tue Mar 5 16:00:15 1996 Jason Merrill <jason@yorick.cygnus.com>
+
+ * 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.
-Fri Feb 11 11:52:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+Mon Mar 4 22:38:39 1996 Gerald Baumgartner <gb@alexander.cs.purdue.edu>
- * class.c (finish_struct): Don't allow adjusting access to a field
- of a base class if a local field has the same name.
+ * 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.
- * error.c (dump_type_prefix): Output basetype for METHOD_TYPEs.
+Tue Mar 5 10:21:01 1996 Jason Merrill <jason@yorick.cygnus.com>
-hu Jan 13 17:55:51 EST 1994 Gnanasekaran Swaminathan (gs4t@virginia.edu)
+ * 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-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.
+Mon Mar 4 20:03:33 1996 Jason Merrill <jason@yorick.cygnus.com>
- Now `template <class T, T f(T&), const T*> class A {...}' works.
+ * init.c (build_offset_ref): Call complete_type.
- * 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.
+ * decl.c (pop_from_top_level): Always pop previous_class_type.
- * pt.c (tsubst): Traverse method list using DECL_CHAIN.
+ * parse.y: Handle multiple decls in a for-init-statement.
+ * pt.c (tsubst_expr): Likewise.
- * decl.c (grok_op_properties): Allow operator++/-- to have
- default arguments.
+ * pt.c (tsubst): Use tsubst_expr for the second operand of an
+ ARRAY_REF.
- * typeck2.c (store_init_value): Don't abort when called to
- initialize a type that needs constructing with a CONSTRUCTOR.
+ * 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.
- * 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.
+ * decl.c (maybe_push_to_top_level): Save current_template_parms,
+ and clear it if !pseudo.
+ (pop_from_top_level): Restore it.
-Fri Feb 11 02:49:23 1994 Mike Stump <mrs@cygnus.com>
+ * decl2.c (finish_file): Push the dummy each time we walk the list
+ of vtables.
- * 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.
+ * error.c (dump_expr): Support LOOKUP_EXPR and actually do
+ something for CAST_EXPR.
+
+Mon Feb 19 14:49:18 1996 Rusty Russell <rusty@adelaide.maptek.com.au>
-Fri Feb 11 00:26:46 1994 Mike Stump <mrs@cygnus.com>
+ * cvt.c (cp_convert): Warn about implicit conversion of the
+ address of a function to bool, as it is always true.
- * 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.
+Fri Feb 23 23:06:01 1996 Rusty Russell <rusty@adelaide.maptek.com.au>
-Thu Feb 10 21:49:35 1994 Mike Stump <mrs@cygnus.com>
+ * typeck.c (c_expand_return): Fix warning for local externs returned.
- * 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.
+Mon Mar 4 15:03:11 1996 Jason Merrill <jason@yorick.cygnus.com>
-Thu Feb 10 17:19:32 1994 Mike Stump <mrs@cygnus.com>
+ * tree.c (mapcar): Propagate const and volatile properly.
- * 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.
+ * typeck.c (complete_type): Be sure to instantiate the
+ MAIN_VARIANT of the type.
-Thu Feb 10 12:18:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * method.c (synthesize_method): Class interface hackery does not
+ apply to synthesized methods.
- * typeck2.c (build_functional_cast): #if 0 out constructor
- inheritance code, improve error messages.
+Mon Mar 4 14:05:23 1996 Jason Merrill <jason@yorick.cygnus.com>
- * class.c (finish_base_struct): Complain about base with only
- non-default constructors in derived class with no constructors.
+ * pt.c (comp_template_args): Use comptypes rather than just
+ checking for TEMPLATE_TYPE_PARM equivalence.
- * decl.c (grokdeclarator): Fix detection of virtual new/delete.
+ * typeck.c (build_x_function_call): Call complete_type before
+ checking TYPE_OVERLOADS_CALL_EXPR.
-Wed Feb 9 22:02:32 1994 Mike Stump <mrs@cygnus.com>
+Mon Mar 4 18:48:30 1996 Manfred Hollstein <manfred@lts.sel.alcatel.de>
- * search.c (build_mi_virtuals, add_mi_virtuals,
- report_ambiguous_mi_virtuals): Removed unneeded code.
- * class.c (finish_struct_bits): Ditto.
+ * g++.c (main): Check also for new define ALT_LIBM.
-Wed Feb 9 11:27:17 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Mar 1 13:09:33 1996 Jason Merrill <jason@yorick.cygnus.com>
- * pt.c (end_template_instantiation): Push decl before
- pop_from_top_level.
+ * 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.
- * typeck2.c (build_m_component_ref): Make sure datum is of
- aggregate type.
+ * decl.c (grok_reference_init): Make sure there's a type before
+ checking its code.
- * init.c (get_type_value): New function, returns
- IDENTIFIER_TYPE_VALUE or IDENTIFIER_CLASS_TYPE_VALUE or NULL_TREE.
+ * pt.c (do_function_instantiation): Avoid crashing on invalid decls.
+ (push_template_decl): Likewise.
- * call.c (build_method_call): Don't die on call to destructor for
- non-type.
+ * parse.y (named_class_head): Set
+ CLASSTYPE_TEMPLATE_SPECIALIZATION here if we have basetypes.
- * decl.c (grokdeclarator): Complain about virtual op new and op
- delete, make static virtuals unvirtual instead of unstatic.
+ * decl.c (xref_tag): Diagnose redeclaration of template
+ type-parameter name.
- * typeck.c (build_c_cast): Also call default_conversion on
- methods.
+ * error.c (dump_type): Handle anonymous template type parms.
- * decl.c (grokdeclarator): Don't complain about anonymous
- bitfields.
+ * pt.c (instantiate_template): Use TYPE_MAIN_DECL instead of
+ TYPE_STUB_DECL.
+ (coerce_template_parms): Likewise.
- * parse.y (simple_stmt, for loops): Move the continue point after
- the cleanups.
+Thu Feb 29 16:26:01 1996 Mike Stump <mrs@cygnus.com>
- * class.c (finish_struct): Fix setting of
- TYPE_HAS_COMPLEX_INIT_REF.
+ * class.c (instantiate_type, case {ARRAY,INDIRECT}_REF,
+ case ADDR_EXPR): Don't modify rhs if a subinstantiation fails.
-Tue Feb 8 13:21:40 1994 Jason Merrill (jason@deneb.cygnus.com)
+Thu Feb 29 08:20:25 1996 Jason Merrill <jason@yorick.cygnus.com>
- * init.c (build_new): Deal with `new double (1)'.
+ * pt.c (instantiate_template): Take the MAIN_VARIANT of the type
+ before trying to get its STUB_DECL.
+ (coerce_template_parms): Likewise.
- * 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.
+ * parse.y (template_type_parm): If they didn't use 'class',
+ pretend they did after giving an error.
- * decl.c (duplicate_decls): Propagate access decls.
+ * pt.c (coerce_template_parms): Diagnose use of local class.
- * typeck2.c (process_init_constructor): Accept empty_init_node
- for initializing unions.
+ * decl.c (grok_reference_init): Use instantiate_type.
- * 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.
+ * error.c (dump_expr): Handle TEMPLATE_DECLs.
- * decl.c (finish_decl): Don't complain about uninitialized const
- if it was initialized before.
+ * parse.y (named_class_head): Diagnose mismatching types and tags.
-Mon Feb 7 18:12:34 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (pushdecl): Type decls and class templates clash with
+ artificial type decls, not hide them.
- * lex.c (default_assign_ref_body): Don't deal with vbases for
- now.
+ * decl.c (redeclaration_error_message): Diagnose redefinition of
+ templates properly.
+ (duplicate_decls): Diagnose disallowed overloads for template
+ functions, too.
- * decl.c (finish_decl): Fix reversed logic for objects and other
- things that need to be constructed but have no initializer.
+ * decl.c (start_decl): Call complete_type before checking for a
+ destructor.
- * class.c (finish_struct): Don't set TYPE_HAS_* flags that are
- set by grok_op_properties or finish_decl.
+ * pt.c (tsubst): Use tsubst_expr on the elts of a VEC.
- * decl.c: Don't warn about extern redeclared inline unless
- -Wextern-inline is given.
- * decl2.c (lang_decode_option): Ditto.
- * cp-tree.h: Ditto.
+ * decl.c (xref_tag): A TEMPLATE_TYPE_PARM is a match.
-Mon Feb 7 17:29:24 1994 Per Bothner (bothner@kalessin.cygnus.com)
+Wed Feb 28 09:28:44 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (pushdecl_with_scope): Fix thinko. Add forward
- declaration.
+ * decl.c (grok_op_properties): Don't check for operator++(int) in
+ a template.
- * 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.
+ * tree.c (perm_manip): Return a copy of variable and function
+ decls with external linkage.
-Mon Feb 7 14:42:03 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * call.c, cvt.c, init.c, search.c, cp-tree.h:
- Eradicate LOOKUP_PROTECTED_OK.
+ * decl.c (cp_finish_decl): Call complete_type before deciding
+ whether or not to lay out the decl.
-Mon Feb 7 13:57:19 1994 Per Bothner (bothner@kalessin.cygnus.com)
+ * lex.c (do_identifier): Check for DECL_INITIAL before using it.
- * 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.
+Tue Feb 27 16:35:32 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Feb 7 00:22:59 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck2.c (build_x_arrow): Call complete_type.
- * cp-tree.h (ACCESSIBLY_UNIQUELY_DERIVED_P): New macro, means what
- ACCESSIBLY_DERIVED_FROM_P meant before.
- (ACCESSIBLY_DERIVED_FROM_P): Now disregards ambiguity.
+ * 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.
- * cvt.c (build_up_reference): Call get_binfo with PROTECT == 1.
+Tue Feb 27 15:51:32 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * search.c, lex.c, decl.c, class.c, cp-tree.h: Don't wrap the
+ memoized lookup stuff inside GATHER_STATISTICS.
- * method.c (build_opfncall): Do check access on operator new here.
+Tue Feb 27 10:38:08 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (finish_function): Don't check access on operator new
+ * decl.c (start_decl): Complain about array of incomplete type
here.
+ (grokdeclarator): Not here.
-Sun Feb 6 14:06:58 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (xref_tag): The base of a derived struct is NOT always
- public. Duh.
-
- * 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.
-
- * parse.y (datadef): Move explicit_instantiation here.
- (structsp): From here.
- (datadef): Complain about `int;'.
-
-Sun Feb 6 12:33:18 1994 Per Bothner (bothner@kalessin.cygnus.com)
-
- * 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.
-
-Sun Feb 6 02:49:37 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck2.c (build_functional_cast): int() -> int(0).
-
-Sat Feb 5 00:53:21 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct): Don't do a bitwise copy for op= if the
- class has a virtual function table.
-
- * typeck.c (convert_for_initialization): Restore warnings about
- not using defined op=. Should really be my_friendly_aborts, I
- s'pose.
-
-Fri Feb 4 14:21:00 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct): Tidy up conditions for doing bitwise
- copies of objects.
-
- * decl.c (build_default_constructor): #if 0 out.
-
- * *: Eradicate TYPE_GETS_{ASSIGNMENT,ASSIGN_REF,CONST_ASSIGN_REF,
- CONST_INIT_REF}, TYPE_HAS_REAL_CONSTRUCTOR.
-
- * decl.c (grokdeclarator): Don't return void_type_node for
- friends being defined here.
-
- * init.c (perform_member_init): Only do the init if it's useful.
-
- * 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 (grokdeclarator): If friendp && virtualp, friendp = 0.
-
-Fri Feb 4 13:02:56 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Fri Feb 4 00:41:21 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (grokdeclarator): Don't try to set TYPE_WAS_ANONYMOUS on
- enums.
-
- * decl2.c (constructor_name_full): Use IS_AGGR_TYPE_CODE instead of
- IS_AGGR_TYPE, since we don't know it's a type.
-
-Thu Feb 3 11:36:46 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (grokdeclarator): Don't complain about anonymous unions.
-
- * cp-tree.h (TYPE_WAS_ANONYMOUS): This struct was originally
- anonymous, but had a name given to it by a typedef.
-
- * decl.c (grokdeclarator): When renaming an anonymous struct, set
- TYPE_WAS_ANONYMOUS.
-
- * decl2.c (constructor_name_full): Use TYPE_WAS_ANONYMOUS.
-
- * cp-tree.h (DECL_UNDEFINED_FRIENDS): #if 0 out.
-
- * 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.
-
- * decl.c (grokdeclarator): Always return void_type_node for
- friends.
-
- * 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.
-
- * decl.c (grokdeclarator): Give error on abstract declarator used
- in an invalid context (i.e. `void (*)();').
-
- * error.c (cp_line_of): Support _TYPE nodes.
- (cp_file_of): Ditto.
-
- * 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.
-
- * init.c (expand_aggr_init_1): Deal with bracketed initializer
- lists properly.
-
- * class.c (finish_struct): Deal with enumerators and typedefs
- again.
-
-Wed Feb 2 11:30:22 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct): Tidy up loop over fields.
-
- * errfn.c (cp_thing): Don't advance twice after a format.
-
- * 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.
-
- * decl.c (finish_decl): Also do the constructor thing if
- TYPE_NEEDS_CONSTRUCTING is set (for arrays).
-
- * search.c (unuse_fields): New function: mark all fields in this
- type unused.
- (dfs_unuse_fields): Helper function.
-
- * class.c (pushclass): If the new class is the same as the old
- class, still unuse the fields.
- (unuse_fields): Move to search.c.
+ * parse.y (template_parm): Expand full_parm inline so we can set
+ the rule's precedence.
- * decl.c (grok_op_properties): Add friendp argument.
- (grokfndecl): Pass it.
- (start_method): Ditto.
+ * 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.
- * decl2.c (delete_sanity): Add use_global_delete parameter to catch
- ::delete calls.
+ * decl.c (define_label): Make the min decl go on permanent_obstack.
- * parse.y (unary_expr): Pass new parameter to delete_sanity.
+ * pt.c (unify): Don't handle CONST_DECLs.
+ (uses_template_parms): Don't check DECL_INITIAL on a CONST_DECL.
+ (tsubst_copy): Likewise.
- * lex.c (default_copy_constructor_body): Don't choke if the union
- has no fields.
- (default_assign_ref_body): Ditto.
+ * lex.c (do_identifier): Do pull the DECL_INITIAL out of a
+ CONST_DECL for a template parm.
- * call.c (compute_conversion_costs_ansi): Do the right thing for
- ellipsis matches.
+Mon Feb 26 12:48:18 1996 Jason Merrill <jason@yorick.cygnus.com>
- * decl.c (push_to_top_level): Optimize.
-
- * decl.c (start_function): Look for the lexical scope of a friend
- in DECL_CLASS_CONTEXT.
-
- * init.c (do_friend): Set DECL_CLASS_CONTEXT on global friends.
-
-Tue Feb 1 15:59:24 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cp-tree.h (TREE_GETS_PLACED_NEW): New macro.
-
- * 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.
-
- * decl.c (grok_op_properties): Don't set TREE_GETS_NEW for a decl of
- op new with placement, set TREE_GETS_PLACED_NEW.
-
- * cp-tree.h (ANON_UNION_P): New macro. Applies to decls.
-
- * 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".
-
- * decl2.c (grok_x_components): Wipe out memory of synthesized methods
- in anonymous unions.
-
- * lex.c (default_copy_constructor_body): Support unions.
- (default_assign_ref_body): Ditto.
-
-Mon Jan 31 12:07:30 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cp-tree.h: Fix documentation of LOOKUP_GLOBAL, add prototypes.
-
- * error.c (args_as_string): New function (%A), like type_as_string
- except NULL_TREE -> "..."
-
- * call.c (build_overload_call_real): Fix for new overloading.
-
- * decl.c (grok_op_properties): Set all of the TYPE_OVERLOADS_* flags
+ * decl.c (grokdeclarator): Complain about array of incomplete type
here.
+ (start_decl_1): Not here.
- * parse.y (operator_name): Instead of here.
-
- * typeck2.c (build_functional_cast): Treat a TREE_LIST as a list
- of functions.
-
- * call.c (build_overload_call_real): Support LOOKUP_SPECULATIVELY.
-
- * method.c (build_opfncall): Don't need to massage return value
- any more, call build_overload_call with all flags.
-
- * typeck.c (build_x_binary_op): Put back speculative call to
- build_opfncall.
- (build_x_unary_op): Ditto.
- (build_x_conditional_expr): Ditto.
-
-Mon Jan 31 10:00:30 1994 Mike Stump <mrs@cygnus.com>
-
- * cvt.c (build_type_conversion_1): Change call to pedwarn into
- warning, and conditionalize upon warn_cast_qual.
-
-Fri Jan 28 11:48:15 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * search.c (lookup_field): If xbasetype is a binfo, copy it to
- avoid clobbering its inheritance info.
-
- * call.c (build_method_call): Don't overwrite basetype_path with
- TYPE_BINFO (inst_ptr_basetype) if they have the same type.
-
- * search.c (compute_access): Fix handling of protected inheritance
- and friendship with the enclosing class.
-
- * typeck2.c (store_init_value): Allow passing of TREE_CHAIN for
- initialization of arbitrary variable.
-
- * typeck2.c (build_functional_cast): Only try calling a method if
- one exists.
-
- * decl.c (grokdeclarator): Move handling of constructor syntax
- initialization into first loop for generality.
- (parmlist_is_random): Lose.
-
- * lex.c (cons_up_default_function): Set TREE_PARMLIST on arguments
- to default function.
-
-Thu Jan 27 19:26:51 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (grokparms): Abort if we get called with something we don't
- expect.
-
-Thu Jan 27 17:37:25 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Thu Jan 27 14:36:20 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * call.c (build_method_call): Don't check for being called with
- a pointer.
-
- * decl2.c (finish_file): Don't play with DECL_CLASS_CONTEXT for the
- static initializer function.
-
- * init.c (build_member_call): Use convert_force here, too.
-
- * search.c (compute_access): Only treat static members specially
- if they are referenced directly.
-
-Wed Jan 26 18:28:14 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * gxxint.texi (Access Control): New node.
-
- * 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!
-
- * cp-tree.h: #if 0 out DECL_PUBLIC & friends.
-
- * typeck.c (build_component_ref_1): Don't check DECL_PUBLIC.
-
- * call.c (build_method_call): Use convert_force to cast `this' --
- rely on the access checking for the method itself.
-
- * 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?
-
-Wed Jan 26 17:50:00 1994 Mike Stump <mrs@cygnus.com>
-
- * cvt.c (build_type_conversion_1): Don't conditionalize call to
- pedwarn upon pedantic.
-
-Wed Jan 26 17:20:46 1994 Mike Stump <mrs@cygnus.com>
-
- * 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 Jan 26 14:35:06 1994 Mike Stump <mrs@cygnus.com>
-
- * 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 Jan 26 11:28:14 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cp-tree.h (VTABLE_NAME_P): Change other occurrence of
- VTABLE_NAME_FORMAT to VTABLE_NAME.
-
- * *: s/visibility/access/g
-
-Tue Jan 25 18:39:12 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (build_modify_expr): Don't smash references if INIT_EXPR.
-
-Tue Jan 25 13:54:29 1994 Mike Stump <mrs@cygnus.com>
-
- * init.c (build_delete): Back out Jan 17th & 18th pacthes, as
- they break libg++.
-
-Tue Jan 25 13:11:45 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * decl.c (duplicate_decls): Fix pointer arithmetic.
-
-Mon Jan 24 15:50:06 1994 Chip Salzenberg (chip@fin.uucp)
-
- [ cp-* changes propagated from c-* changes in 940114 snapshot ]
- * cp-parse.y (maybe_attribute): Allow multiple __attribute__
- clauses on a declaration.
-
-Mon Jan 24 17:06:23 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct): Do synthesize methods for anon
- structs, just not unions.
-
-Mon Jan 24 13:50:13 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * 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.
-
- * parse.y : get rid of 'goto do_components'. It is much better
- for debugging.
-
- * decl.c (is_anon_name): get rid of the function and use the
- macro ANON_AGGRNAME_P.
- * pt.c : ditto.
-
-Fri Jan 21 14:06:02 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct): Don't synthesize any methods for
- anonymous structs/unions.
-
- * typeck.c (build_modify_expr): Don't treat pmf's as class objects.
-
-Thu Jan 20 18:56:46 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * method.c (build_opfncall): Call build_indirect_ref on
- synthesized instance for operator delete.
-
- * pt.c (type_unification): Don't abort if called with a list of
- types in ARGS.
+ * pt.c (tsubst): Handle pointer-to-function declarators.
- * class.c (instantiate_type): Deal with function templates.
+ * method.c (hack_identifier): If pedantic, diagnose local class
+ methods that require a static chain.
-Thu Jan 20 16:55:35 1994 Jim Wilson (wilson@sphagnum.cygnus.com)
+ * 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.
- * Makefile.in (CC): Default to cc not gcc.
+ * parse.y (template_arg): The expr has precedence like '>'.
-Thu Jan 20 13:47:54 1994 Jason Merrill (jason@deneb.cygnus.com)
+Fri Feb 23 14:51:52 1996 Jason Merrill <jason@yorick.cygnus.com>
- * typeck.c (build_modify_expr): Call constructor if appropriate.
-
- * decl.c (push_to_top_level): Clear out class-level bindings cache.
-
-Wed Jan 19 13:51:22 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * call.c (resolve_scope_to_name): Work recursively (previously only
- looked down one level).
-
- * lex.c (do_pending_inlines): If we're still dealing with the last
- batch of inlines, don't start working on a new one.
-
- * Makefile.in (stamp-parse): Update conflict count.
- (TAGS): Fix.
-
- * parse.y (explicit_instantiation): New rule; implements
- 'template A<int>' syntax (though not 'template foo(int)' yet).
- (structsp): Add explicit_instantiation.
-
-Tue Jan 18 13:53:05 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * class.c (finish_struct, etc.): Simplify decision to synthesize
- a destructor.
-
- * 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.
-
- * class.c (finish_base_struct): Set cant_have_default_ctor and
- cant_synth_copy_ctor properly.
- (finish_struct): Ditto.
-
-Mon Jan 17 13:58:18 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * typeck.c (build_modify_expr_1): #if 0 out again.
- (build_modify_expr): #if 0 out memberwise init code again.
-
- * lex.c (default_copy_constructor_body): Be const-correct.
- (default_assign_ref_body): Ditto.
-
- * 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.
-
- * class.c (base_info): Lose needs_default_ctor.
- (finish_base_struct): Ditto.
- (finish_struct): Ditto.
-
- * 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.
-
- * class.c (finish_struct): Synthesize default ctor whenever
- allowed.
-
- * Makefile.in (TAGS): Don't try to run etags on cp-parse.y.
-
-Sat Jan 15 18:34:33 1994 Mike Stump <mrs@cygnus.com>
-
- * Makefile.in, configure: Handle the C++ front-end in a
- subdirectory.
- * cp-*: Move C++ front-end to cp/*.
-
-Fri Jan 14 14:09:37 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cp-typeck.c (build_function_call_real): Modify to match other
- instances of taking the address of the function.
-
- * 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.
-
- * cp-tree.h (lang_type): Add has_real_constructor bitfield.
- (TYPE_HAS_REAL_CONSTRUCTOR): Define.
-
- * cp-lex.c (default_copy_constructor_body): Use init syntax
- for all bases.
-
- * cp-type2.c (store_init_value): Only give error for initializer list
- if TYPE_HAS_REAL_CONSTRUCTOR.
-
-Thu Jan 13 15:38:29 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cp-tree.h (DECL_SYNTHESIZED): Add defn.
- (lang_decl): Add synthesized bitfield to decl_flags.
-
- * cp-lex.c (cons_up_default_function): Use DECL_SYNTHESIZED to mark
- artificial methods, rather than a line # of 0.
-
-Fri Jan 14 18:25:29 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * 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.
-
-Fri Jan 14 17:00:29 1994 Mike Stump <mrs@cygnus.com>
-
- * cp-decl.c (pushdecl): Revert patch from Jan 11 19:33:03, as it is
- not right.
-
-Thu Jan 13 14:00:35 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * cp-decl2.c (grok_x_components): fix a bug that enum type does not
- have type_flags.
-
-Thu Jan 13 11:39:34 1994 Mike Stump <mrs@cygnus.com>
-
- Ensure that all vtable pointers are initialized with all the right
- values.
-
- * 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.
-
-Wed Jan 12 18:24:16 1994 Kung Hsu (kung@mexican.cygnus.com)
-
- * 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.
-
-Wed Jan 12 14:08:09 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cp-decl.c (grokdeclarator): Don't set TREE_PUBLIC on friend
- decls with a definition attached.
-
- * cp-typeck.c (build_modify_expr): Undo previous change in the case
- of INIT_EXPRs.
-
-Tue Jan 11 19:33:03 1994 Jason Merrill (jason@deneb.cygnus.com)
-
- * cp-typeck.c (build_modify_expr): Replace code for generating
- assignment semantics for classes with an error.
- (build_modify_expr_1): #if 0 out.
-
- * cp-decl.c (pushdecl): Patch bogus design of pushdecl
- behavior for overloaded functions (it doesn't push anything).
-
- * cp-class.c (finish_struct): When generating default op=,
- set TYPE_HAS_ASSIGNMENT.
-
-Mon Jan 10 18:48:06 1994 Mike Stump <mrs@cygnus.com>
-
- * 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.
-
-Mon Jan 10 17:48:37 1994 Kung Hsu (kung@mexican.cygnus.com)
+ * 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 <brendan@lisa.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst_expr): Add default return.
+
+Thu Feb 22 16:47:24 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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 <brendan@lisa.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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 <brendan@lisa.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * pt.c (do_poplevel): Oops; really return what we get from
+ poplevel this time.
+
+Thu Feb 22 11:41:44 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * pt.c (tsubst): Only look for matching decls at file scope for
+ non-member functions.
- * cp-decl.c (finish_decl): fix incorrect popclass call.
+ * call.c (build_scoped_method_call): Handle scoped destructor
+ calls in templates.
- * 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.
+ * decl.c (*_top_level): Also save previous_class_values.
-Mon Jan 10 14:32:18 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * pt.c (tsubst_expr): Support do {} while loops.
+ * parse.y (simple_stmt): Likewise.
+ * tree.def: Likewise.
- * cp-init.c (build_member_call): Propagate qualifiers to new type.
+ * method.c (build_overload_identifier): For a class nested in a
+ template class, don't mangle in the template parms from our
+ context.
- * cp-call.c (build_method_call): Count functions the new way.
+ * 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 <brendan@lisa.cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ * 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.
-Fri Jan 7 19:03:26 1994 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * cp-decl.c (pushtag): Set DECL_ASSEMBLER_NAME for nested classes,
- too.
+ * 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.
-Tue Jan 4 16:45:51 1994 Kung Hsu (kung@cirdan.cygnus.com)
+ * 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.
- * cp-parse.y: change to handle whether to globalize nested class.
- * cp-decl.c(xref_tag, maybe_globalize_type): Ditto.
+Tue Feb 20 18:21:51 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Jan 3 22:22:32 1994 Gerald Baumgartner (gb@cygnus.com)
+ * 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.
- * 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.
+Tue Feb 20 17:14:29 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * gcc.1 g++.1: Added explanation for the `-fhandle-signatures'
- and `-fno-handle-signatures' command line flags.
+ * decl2.c (check_cp_case_value): Use STRIP_TYPE_NOPS.
- * gcc.texi: Changed the last-modification date.
- * invoke.texi: Added `-fhandle-signatures' in the list of
- C++ language options. Added explanation for this option.
+Thu Feb 15 18:44:42 1996 Mike Stump <mrs@cygnus.com>
-Tue Dec 28 21:10:03 1993 Mike Stump <mrs@cygnus.com>
+ * 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.
- * cp-init.c (expand_vec_init): Remove comptypes test, as it is too
- harsh here.
+Thu Feb 15 09:39:08 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Dec 28 13:42:22 1993 Mike Stump <mrs@cygnus.com>
+ * decl2.c (grokfield): Still call pop_nested_class for access decls.
- * 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.
+Wed Feb 14 17:30:04 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Dec 28 05:42:31 1993 Mike Stump <mrs@cygnus.com>
+ * decl.c (lookup_label): Call label_rtx.
- * 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 (make_binding_level): New function.
+ (pushlevel, pushlevel_class): Call it instead of explicit
+ duplicate calls to xmalloc.
-Fri Dec 24 09:40:52 1993 Michael Tiemann (tiemann@blues.cygnus.com)
+ * decl.c (init_decl_processing): Delete useless build_pointer_type
+ call.
- * cp-typeck.c (c_expand_start_case): Use default_conversion to
- convert expression from reference type if necessary.
+ * 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.
-Wed Dec 22 17:58:43 1993 Jason Merrill (jason@deneb.cygnus.com)
+Wed Feb 14 16:21:25 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-typeck.c (build_unary_op): Make sure that it's a TREE_LIST before
- trying to read its TREE_VALUE.
+ * 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.
- * cp-class.c (finish_struct_methods): Clear DECL_IN_AGGR_P here.
- (finish_struct): Instead of here.
+ * 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.
-Tue Dec 21 14:34:25 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * search.c (get_matching_virtual): Use cp_error_at.
- * 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.
+Wed Feb 14 10:36:58 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-tree.h (VTABLE_NAME): No def with NO_{DOLLAR,DOT} defined.
- (VTABLE_NAME_P): Use it instead of VTABLE_NAME_FORMAT.
+ * 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.
-Mon Dec 20 13:35:03 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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-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.
+ * typeck.c (convert_sequence): #if 0 unused function.
- * 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).
+ * 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.
-Fri Dec 17 15:45:46 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (cp_finish_decl): Use DECL_IN_MEMORY_P.
- * cp-decl.c (grokdeclarator): Forbid declaration of a function as
- static if it's being done inside another function.
+Tue Feb 13 12:51:21 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-search.c (compute_visibility): Check for friendship both ways.
+ * class.c (finish_struct_1): Check for a pure-specifier on a
+ non-virtual function here.
-Fri Dec 17 14:28:25 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (grok_function_init): Don't check whether the function
+ is virtual here.
+ (grokfield): Don't call check_for_override here.
- * cp-cvt.c (build_default_binary_type_conversion): Make error
- messages more helpful.
+ * decl.c (push_to_top_level): Start from inner_binding_level,
+ check class_shadowed in class levels.
- * cp-error.c (op_as_string): New function, returns "operator =="
- given EQ_EXPR or suchlike.
+Mon Feb 12 17:46:59 1996 Mike Stump <mrs@cygnus.com>
-Fri Dec 17 13:28:11 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * decl.c (resume_level): Ignore things that don't have names, instead
+ of core dumping.
- * cp-call.c (print_n_candidates): New function.
- (build_overload_call_real): Use it when we complain about a call
- being ambiguous.
+Mon Feb 12 15:47:44 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Fri Dec 17 12:41:17 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (grokfield): Set DECL_VINDEX properly for FUNCTION_DECLs.
- * cp-call.c (build_method_call): Fix checking for static call
- context.
+Sat Feb 10 17:59:45 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-method.c (build_opfncall): Call build_indirect_ref on argument
- to operator new.
+ * class.c (finish_struct_1): Set DECL_VINDEX properly on a
+ synthesized dtor.
- * cp-init.c (build_new): Don't mess with rval when building
- indirect ref.
+ * parse.y (complete_type_name): Bind global_scope earlier.
+ (complex_type_name): Likewise.
+ (qualified_type_name): Remove.
-Thu Dec 16 16:48:05 1993 Kung Hsu (kung@cirdan.cygnus.com)
+Thu Feb 8 15:15:14 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * 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.
-Thu Dec 16 14:46:06 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * cp-tree.h: Declare warn_sign_compare.
- * 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.
+ * 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.
-Thu Dec 16 14:44:39 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl2.c (lang_decode_option): Handle warn_sign_compare. -Wall
+ implies -Wsign-compare. -Wall doesn't imply -W.
- * cp-decl.c, cp-init.c, cp-typeck.c: Fix arguments to
- build_method_call that I messed up before.
+Wed Feb 7 15:27:57 1996 Mike Stump <mrs@cygnus.com>
- * cp-search.c (get_base_distance): If protect > 1, allow immediate
- private base.
+ * typeck.c (build_component_ref): Fix to handle anon unions in base
+ classes as well.
- * 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.
+Wed Feb 7 14:29:12 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Thu Dec 16 12:17:06 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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-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.
+Tue Feb 6 13:39:22 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-method.c (hack_identifier): Also check for a TYPE_PTRMEMFUNC_P
- to see if something is a method.
+ 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.
-Wed Dec 15 18:35:58 1993 Mike Stump <mrs@cygnus.com>
+Tue Feb 6 13:12:15 1996 Per Bothner <bothner@kalessin.cygnus.com>
- * 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.
+ * 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.
-Wed Dec 15 18:25:32 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c (do_identifier): Use global binding in preference of
+ dead for local variable.
- * cp-parse.y (member_init): ANSI C++ doesn't forbid old-style base
- initializers; it's just anachronistic.
+Mon Feb 5 17:46:46 1996 Mike Stump <mrs@cygnus.com>
- * cp-decl.c (finish_decl): Don't require external-linkage arrays
- to have a complete type at declaration time when pedantic.
+ * 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.
-Tue Dec 14 11:37:23 1993 Jason Merrill (jason@deneb.cygnus.com)
+Fri Feb 2 14:54:04 1996 Doug Evans <dje@charmed.cygnus.com>
- * cp-decl.c (pushdecl): Don't set DECL_CONTEXT if it's already set.
+ * 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-call.c (build_method_call): Don't dereference pointer given
- as instance.
+Thu Feb 1 16:19:56 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-decl.c (finish_function): Don't pass pointer to
- build_method_call.
- (finish_function): Ditto.
+ * init.c (is_friend): Make sure there's a context before we see if
+ it's an aggr type.
- * cp-typeck.c (build_x_function_call): Ditto.
+Thu Feb 1 15:44:53 1996 Mike Stump <mrs@cygnus.com>
- * cp-method.c (build_component_type_expr): Ditto.
+ * init.c (is_friend): Classes are not friendly with nested classes.
- * cp-init.c (build_member_call): Ditto.
- (build_new): Ditto.
+Thu Feb 1 15:27:37 1996 Doug Evans <dje@charmed.cygnus.com>
-Mon Dec 13 18:04:33 1993 Kung Hsu (kung@cirdan.cygnus.com)
+ * lex.c (check_newline): Pass last character read to HANDLE_PRAGMA,
+ and record its result.
- * 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.
+Thu Feb 1 09:27:01 1996 Mike Stump <mrs@cygnus.com>
-Fri Dec 10 12:40:25 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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 (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.
+Tue Jan 30 18:18:23 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * cvt.c (build_up_reference): Make the INDIRECT_BIND case come after
+ code that ensures that copy ctors are used if appropriate.
-Thu Dec 9 18:27:22 1993 Mike Stump <mrs@cygnus.com>
+Tue Jan 30 17:35:14 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * init.c (build_vec_delete): Only give an error if base isn't an
+ error_mark_node.
-Thu Dec 9 16:19:05 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Mon Jan 29 17:09:06 1996 Mike Stump <mrs@cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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 <brendan@lisa.cygnus.com>
+
+ * decl.c (grokdeclarator): Avoid trying to get an operand off an
+ identifier node.
+
+Wed Jan 24 11:25:30 1996 Jim Wilson <wilson@chestnut.cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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 <brendan@lisa.cygnus.com>
+
+ * 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.
- * 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.
+ * lex.c (do_pending_inlines): Delete synthesized method kludge.
-Wed Dec 8 17:38:06 1993 Mike Stump <mrs@cygnus.com>
+ 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 <jason@yorick.cygnus.com>
+
+ * 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 <brendan@lisa.cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * typeck.c (build_component_ref): Handle getting vbase pointers
+ out of complex multiple inheritance better.
+
+Fri Jan 19 16:27:40 1996 Mike Stump <mrs@cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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 <jason@yorick.cygnus.com>
- * cp-decl.c (finish_decl): Make sure things that can go into
- "common", do go into common, if -fcommon is given.
+ * 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.
-Wed Dec 8 13:01:54 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Fri Jan 19 13:53:14 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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.
- * 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.
+Fri Jan 19 12:23:08 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Dec 7 18:29:14 1993 Kung Hsu (kung@cirdan.cygnus.com)
+ * decl2.c (grokbitfield): Strip the NOPs from WIDTH before we
+ check that it's usable as the bitfield width.
- * cp-decl.c (xref_tag, pushtag): Fix nested class search/resolution
- problem.
+Wed Jan 17 21:22:40 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
-Tue Dec 7 16:09:34 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * 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-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.
+Wed Jan 17 12:10:38 1996 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * parse.y (qualified_type_name): Use the TYPE_DECL, not the type.
+ (nested_type): Likewise.
+ (nested_name_specifier): Use lastiddecl.
- * cp-tree.h: Declare flag_alt_external_templates.
+ * decl.c (grokdeclarator): Adjust accordingly.
+ * init.c (expand_member_init): Likewise.
+ * parse.y (base_class): Likewise.
+ * typeck2.c (build_functional_cast): Likewise.
- * cp-decl2.c (lang_decode_option): Support -falt-external-templates.
+ * typeck2.c (build_functional_cast): Fill in name after we've
+ checked for non-aggr type.
- * toplev.c (lang_options): Ditto.
+Wed Jan 17 10:18:01 1996 Mike Stump <mrs@cygnus.com>
- Mon Oct 4 12:50:02 1993 Chip Salzenberg (chip@fin.uucp)
+ * decl2.c (warn_pointer_arith): Default to on.
- [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.
+Tue Jan 16 12:45:38 1996 Jason Merrill <jason@yorick.cygnus.com>
-Tue Dec 7 10:46:48 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * lex.c (is_rid): New function.
+ * decl.c (grokdeclarator): Diagnose reserved words used as
+ declarator-ids.
- * cp-init.c (expand_vec_init): When creating a temporary for copying
- arrays, use the type of the source, not the target.
+Tue Jan 16 11:39:40 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-cvt.c (convert): Pass an argument for errtype to
- convert_to_reference.
+ * tree.c (get_decl_list): Don't lose cv-quals.
- * cp-error.c (dump_expr, COMPONENT_REF & CALL_EXPR): Deal with
- methods, -> and `this'.
+ * decl.c (grokdeclarator): Fix SCOPE_REF handling and diagnose
+ typespecs used as declarator-ids.
-Mon Dec 6 17:12:33 1993 Jason Merrill (jason@deneb.cygnus.com)
+Tue Jan 16 11:09:42 1996 Mike Stump <mrs@cygnus.com>
- * cp-error.c (parm_as_string): New function; returns `this' or arg
- number. Corresponds to %P.
- (dump_expr): Deal with method calls.
+ * decl.c (poplevel): When poping a level, don't give a warning for
+ any subblocks that already exist.
- * cp-cvt.c (convert_to_reference): Stop using warn_for_assignment.
- * cp-typeck.c (convert_for_assignment): Ditto.
- (warn_for_assignment): Lose.
+Tue Jan 16 00:25:33 1996 Jason Merrill <jason@yorick.cygnus.com>
-Mon Dec 6 11:33:35 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * typeck.c (build_object_ref): Finish what I started.
- * 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.
+ * parse.y (qualified_type_name): Don't check TYPE_BUILT_IN.
- * cp-cvt.c (convert_to_aggr): Make sure to always set H_LEN.
+ * decl2.c (constructor_name_full): Handle TEMPLATE_TYPE_PARMs.
-Mon Dec 6 12:49:17 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (grokdeclarator): Also accept TEMPLATE_TYPE_PARM as a
+ scope.
- * cp-init.c (get_aggr_from_typedef): New function, like
- is_aggr_typedef but returns the _TYPE.
+Mon Jan 15 16:19:32 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-call.c, cp-init.c, cp-method.c: Eradicate err_name.
+ * decl.c (xref_tag): Handle passing a type in directly.
-Sun Dec 5 18:12:48 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * 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.
- * cp-lex.c (readescape): Pedwarn when a hex escape is out of range.
+Mon Jan 15 08:45:01 1996 Jeffrey A Law <law@cygnus.com>
-Thu Nov 25 23:50:19 1993 Chip Salzenberg (chip@fin.uucp)
+ * tree.c (layout_basetypes): Call build_lang_field_decl instead
+ of build_lang_decl if first arg is a FIELD_DECL.
- Delay language context change until beginning of next decl.
+Thu Jan 11 14:55:07 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- * 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.
+ * 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.
-Mon Nov 15 15:39:15 1993 Chip Salzenberg (chip@fin.uucp)
+Mon Jan 8 17:35:12 1996 Jason Merrill <jason@yorick.cygnus.com>
- * cp-typeck.c (build_binary_op_nodefault): Warn for ordered
- compare of ptr with 0 only if pedantic in both cases.
+ * typeck.c (build_modify_expr): Use a COMPOUND_EXPR instead of
+ expand_target_expr.
-Thu Nov 25 13:31:37 1993 Chip Salzenberg (chip@fin.uucp)
+Thu Jan 4 12:30:32 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
- 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 $$.
+ 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.
-Wed Nov 17 19:03:30 1993 Chip Salzenberg (chip@fin.uucp)
+Thu Jan 4 11:02:20 1996 Mike Stump <mrs@cygnus.com>
- * cp-parse.y (attrib): Allow "ident(ident)" like the C front end.
+ * typeck.c (pointer_int_sum, pointer_diff): Make code agree with C
+ frontend, and make it more consistent with respect to
+ warn_pointer_arith.
-Fri Oct 22 20:43:37 1993 Paul Eggert (eggert@twinsun.com)
+Tue Jan 2 00:13:38 1996 Rusty Russell <rusty@adelaide.maptek.com.au>
- * cp-lex.c (real_yylex): Diagnose floating point constants
- that are too large.
+ * decl.c (pushdecl): Check for duplicate parameter names.
-Wed Nov 17 19:10:37 1993 Chip Salzenberg (chip@fin.uucp)
+Wed Jan 3 09:25:48 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * decl.c (expand_static_init): Call assemble_external for atexit.
-Wed Nov 17 19:07:18 1993 Chip Salzenberg (chip@fin.uucp)
+Wed Jan 3 07:55:19 1996 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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 <mrs@cygnus.com>
+
+ * except.c (expand_throw): Call assemble_external for __empty, if we
+ use it.
-Mon Oct 11 23:10:53 1993 Chip Salzenberg (chip@fin.uucp)
+Thu Dec 28 11:13:15 1995 Mike Stump <mrs@cygnus.com>
- * cp-decl.c (duplicate_decls): Note redeclarations of library
- functions, and generate distinct warnings for them.
+ * except.c (expand_builtin_throw): Use RETURN_ADDR_OFFSET instead of
+ NORMAL_RETURN_ADDR_OFFSET.
+ (end_eh_unwinder): Likewise.
-Mon Oct 4 12:26:49 1993 Chip Salzenberg (chip@fin.uucp)
+Wed Dec 27 22:18:16 1995 Mike Stump <mrs@cygnus.com>
- Support format warnings in G++.
+ * 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.
- * 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.
+Thu Dec 21 23:50:35 1995 Mike Stump <mrs@cygnus.com>
-Sat Jul 24 12:04:29 1993 Chip Salzenberg (chip@fin.uucp)
+ * 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.
- * 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.
+Wed Dec 20 12:42:51 1995 Jason Merrill <jason@yorick.cygnus.com>
-Thu Dec 2 20:44:58 1993 Chip Salzenberg (chip@fin.uucp)
+ * decl2.c (finish_file): Also prune uninteresting functions in the
+ inline emission loop.
- * 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" {}'.
+Wed Dec 20 02:32:07 1995 Jeffrey A Law <law@cygnus.com>
-Fri Dec 3 16:01:10 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * sig.c (build_signature_table_constructor): Mark functions
+ in the signature as referenced.
- * 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.
+Tue Dec 19 22:36:56 1995 Jason Merrill <jason@yorick.cygnus.com>
-Fri Dec 3 15:32:34 1993 Kung Hsu (kung@cirdan.cygnus.com)
+ * decl2.c (finish_file): Do all the vtable/synthesis stuff before
+ the inline emission stuff.
- * 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.
+Mon Dec 18 15:51:33 1995 Jason Merrill <jason@yorick.cygnus.com>
-Fri Dec 3 12:28:59 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * 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/.
- * cp-lex.c (init_lex): Initialize input_filename to "<internal>" for
- code such as ExceptionHandler::operator=.
+Sun Dec 17 21:13:23 1995 Rusty Russell <rusty@adelaide.maptek.com.au>
-Fri Dec 3 10:32:08 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * init.c (expand_member_init): warning for base init after members.
- * 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.
+Fri Dec 15 15:32:18 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-decl2.c: Default to flag_ansi_overloading.
+ * cvt.c (build_expr_type_conversion): Don't convert to a reference
+ type.
-Thu Dec 2 18:05:56 1993 Kung Hsu (kung@cirdan.cygnus.com)
+Thu Dec 14 16:05:58 1995 Mike Stump <mrs@cygnus.com>
+
+ * method.c (report_type_mismatch): Improve wording for volatile
+ mismatches.
+
+Thu Dec 14 14:16:26 1995 Mike Stump <mrs@cygnus.com>
+
+ * 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 <eggert@twinsun.com>
+
+ * 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 <jason@yorick.cygnus.com>
+
+ 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.
- * cp-call.c (build_method_call): use binfo from instance if it's
- different from binfo (basetype_path) passed from above.
+ * search.c (add_conversions): Don't use TREE_CHAIN to traverse method
+ vector.
-Thu Dec 2 12:48:36 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * call.c (build_method_call): Synthesize here even when not inlining.
+ * typeck.c (build_function_call_real): Likewise.
-Wed Nov 17 19:14:29 1993 Chip Salzenberg (chip@fin.uucp)
+Wed Dec 13 15:02:39 1995 Ian Lance Taylor <ian@cygnus.com>
- cp-error.c (dump_expr): Use unsigned chars to output a
- TREE_REAL_CST in hex.
+ * 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.
-Thu Dec 2 11:05:48 1993 Jason Merrill (jason@deneb.cygnus.com)
+Tue Dec 12 20:38:55 1995 Mike Stump <mrs@cygnus.com>
- * cp-class.c (finish_struct): Fix typo in setting
- cant_synth_asn_ref.
+ * except.c (start_anon_func): Push to the top level.
+ (end_anon_func): Pop from the top level.
- * cp-tree.h (TYPE_NESTED_NAME): New macro, does
- DECL_NESTED_TYPENAME (TYPE_NAME (NODE)).
+Mon Dec 11 18:56:14 1995 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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 <mrs@cygnus.com>
+
+ * except.c (expand_throw): Ensure that we have cleanups, if we try
+ and expand cleanups.
+
+Wed Dec 6 11:48:21 1995 Mike Stump <mrs@cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * gc.c (build_t_desc): Update error message to say <typeinfo>.
+
+Thu Nov 30 12:30:05 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
+
+ * decl.c (pushdecl): Only warn about shadowing a local variable if
+ warn_shadow is true.
+
+Sun Nov 26 16:06:55 1995 Rusty Russell <rusty@adelaide.maptek.com.au>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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 <mrs@cygnus.com>
+
+ * 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.
-Thu Dec 2 10:47:15 1993 Michael Tiemann (tiemann@blues.cygnus.com)
+Wed Nov 22 11:52:19 1995 Paul Russell <Rusty.Russell@adelaide.maptek.com.au>
- * 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.
+ * typeck.c (build_unary_op): Set TREE_NO_UNUSED_WARNING to avoid
+ warnings.
-Thu Dec 2 10:41:16 1993 Torbjorn Granlund (tege@cygnus.com)
+Tue Nov 21 17:15:23 1995 Mike Stump <mrs@cygnus.com>
- * cp-typeck.c (build_binary_op_nodefault): In *_DIV_EXPR *_MOD_EXPR
- cases, tests for unsigned operands by peeking inside a NOP_EXPR.
+ * 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.
-Wed Dec 1 13:33:34 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+Tue Nov 21 13:32:03 1995 Mike Stump <mrs@cygnus.com>
- * 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.
+ * 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.
- * 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.
+Thu Nov 9 13:35:30 1995 Jason Merrill <jason@yorick.cygnus.com>
-Wed Dec 1 09:53:59 1993 Torbjorn Granlund (tege@cygnus.com)
+ * pt.c (do_function_instantiation): Don't try to find a file-scope
+ template for a member function.
- * 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.
+Tue Nov 14 06:20:35 1995 Mike Stump <mrs@cygnus.com>
-Tue Nov 30 14:07:26 1993 Brendan Kehoe (brendan@lisa.cygnus.com)
+ * g++.c (main): Add handling of -nodefaultlibs.
- * cp-method.c (hack_identifier): If the field itself is private, and
- not from a private base class, say so.
+Mon Nov 13 15:45:34 1995 Mike Stump <mrs@cygnus.com>
-Mon Nov 29 03:00:56 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * 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.
- * cp-decl.c (grokdeclarator): Always warn on initialization of
- const member.
+Fri Nov 10 09:18:09 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-Wed Nov 24 00:49:35 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * 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-class.c (finish_struct): Set TYPE_GETS_CONST_* properly.
- (finish_base_struct): Set cant_synth_asn_ref properly.
+Mon Nov 6 18:36:13 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-lex.c (cons_up_default_function): Add section for operator=.
- (default_assign_ref_body): New function, mostly cribbed from
- default_copy_constructor_body.
+ * call.c (build_method_call): Make sure instance has a
+ TYPE_LANG_SPECIFIC node before we dive into it.
- * 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=.
+Sat Nov 4 20:01:52 1995 Jason Molenda <crash@phydeaux.cygnus.com>
-Tue Nov 23 20:24:58 1993 Mike Stump <mrs@cygnus.com>
+ * method.c (make_thunk): use TREE_SET_CODE to set thunk's tree code.
- * 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.
+Thu Nov 2 17:56:57 1995 Mike Stump <mrs@cygnus.com>
-Tue Nov 23 18:06:58 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * decl.c (duplicate_decls): When smashing decls, smash staticness in
+ the usual way.
- * cp-error.c (dump_expr): Do the right thing for variables of
- reference type.
+Thu Nov 2 16:44:02 1995 Mike Stump <mrs@cygnus.com>
- * cp-decl.c (grok_op_properties): Set TYPE_HAS_ASSIGN_REF
- and its kin properly.
- (xref_tag): Propagate TYPE_GETS_ASSIGN_REF.
+ * 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.
-Tue Nov 23 12:26:13 1993 Mike Stump <mrs@cygnus.com>
+Wed Nov 1 12:33:53 1995 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * method.c (hack_identifier): Don't abort when we get a TREE_LIST
+ that's not a list of overloaded functions.
-Mon Nov 22 14:22:23 1993 Jason Merrill (jason@deneb.cygnus.com)
+Wed Nov 1 11:38:58 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-decl.c (grok_op_properties): Allow operator?: with pedwarn
- (since it's supported in other compiler bits).
+ * decl2.c (mark_vtable_entries): Check DECL_LANG_SPECIFIC on fn
+ before trying to use DECL_ABSTRACT_VIRTUAL_P.
- * cp-method.c (report_type_mismatch): Use cp_error; ignore err_name
- argument.
+Tue Oct 31 11:56:55 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-error.c (dump_function_decl): Don't print return type for
- constructors and destructors.
+ * 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-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 (grokclassfn): Tweak __in_chrg attributes.
- * 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.
+Thu Oct 26 16:45:58 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-init.c (build_delete): Don't use TYPE_BUILT_IN (there are now
- no uses of it in the compiler).
+ * errfn.c: Include stdio.h.
+ (cp_sprintf): Take out decl of sprintf, and cast sprintf to errorfn*.
- * cp-call.c (build_scoped_method_call): Fix for destructors of simple
- types.
- (build_method_call): Ditto.
+Wed Oct 25 18:58:41 1995 Mike Stump <mrs@cygnus.com>
-Fri Nov 19 12:59:38 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * typeck2.c (digest_init): Always convert initializers to the
+ right type.
- * cp-tree.c (count_functions): Abstraction function.
+Wed Oct 25 13:25:24 1995 Mike Stump <mrs@cygnus.com>
- * cp-call.c (build_overload_call_real): Deal with new overloading
- properly, remove dead code.
+ * init.c (member_init_ok_or_else): Don't allow member initializers
+ for indirect members, as it is invalid.
- * gcc.c (default_compilers): Generate and use .ii files in the
- intermediate stage of compiling C++ source.
+Wed Oct 25 11:35:28 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
-Fri Nov 19 11:26:09 1993 Jim Wilson (wilson@sphagnum.cygnus.com)
+ * decl.c (grokdeclarator): Don't allow `friend signed ()'.
- * cp-expr.c (cplus_expand_expr): Make call_target a valid memory
- address before using it, so it can be later safely compared.
+Fri Oct 20 10:30:59 1995 Mike Stump <mrs@cygnus.com>
-Fri Nov 12 15:30:27 1993 Jason Merrill (jason@deneb.cygnus.com)
+ * parse.y (for.init.statement): Catch compound statements inside for
+ initializations, if we're being pedantic.
- * cp-pt.c (tsubst): Deal with new overloading.
+Fri Oct 20 10:03:42 1995 Mike Stump <mrs@cygnus.com>
- * 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.
+ * decl.c (lookup_tag): Return NULL_TREE if we don't find what we are
+ looking for.
- * cp-tree.c (decl_list_length): Deal with new overloading.
- (decl_value_member): Like value_member, but for DECL_CHAINs.
+Thu Oct 19 14:26:10 1995 Mike Stump <mrs@cygnus.com>
- * cp-decl.c (duplicate_decls): Deal with new overloading.
- (start_decl): Ditto.
+ * error.c (dump_expr): Don't core dump when a boolean expression is
+ used as a default argument.
- * cp-class.c (instantiate_type): Deal with new overloading.
+Thu Oct 19 10:36:30 1995 Jason Merrill <jason@yorick.cygnus.com>
- * cp-call.c (convert_harshness_ansi): Deal with new overloading.
- (convert_harshness_old): Deal with new overloading.
- (build_overload_call_real): Ditto.
+ * class.c (finish_struct_bits): Check aggregate_value_p instead of
+ RETURN_IN_MEMORY.
-Mon Nov 8 13:50:49 1993 Jason Merrill (jason@deneb.cygnus.com)
+Wed Oct 18 18:12:32 1995 Jason Merrill <jason@yorick.cygnus.com>
- * 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.
+ * class.c (finish_struct_bits): Also set TREE_ADDRESSABLE on a
+ BLKmode type that would otherwise be returned in registers.
- * cp-init.c (init_init_processing): use `get_first_fn' to find
- the FUNCTION_DEFN for new and delete.
+Mon Oct 16 12:32:19 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-decl.c (push_overloaded_decl): Use new overloading strategy, cut
- code size in half (I spit on special cases).
+ * 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.
-Tue Sep 7 20:03:33 1993 Jason Merrill (jason@deneb.cygnus.com)
+Wed Oct 11 16:30:34 1995 Brendan Kehoe <brendan@lisa.cygnus.com>
- * cp-decl.c: Allow references and template type parameters as well
+ * parse.y (fn.def1): Call split_specs_attrs in
+ declmods notype_declarator case.
+
+Use a consistent time stamp format in ChangeLog entries.
+Not everyone has Emacs 20 yet, so stick with Emacs 19 format for now.
Local Variables:
-eval: (auto-fill-mode)
-left-margin: 8
-fill-column: 76
+add-log-time-format: current-time-string
End:
diff --git a/gnu/usr.bin/gcc/cp/Make-lang.in b/gnu/usr.bin/gcc/cp/Make-lang.in
index c9d0a39dde2..7646cf66bdf 100644
--- a/gnu/usr.bin/gcc/cp/Make-lang.in
+++ b/gnu/usr.bin/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)" \
@@ -52,7 +52,17 @@ GXX_CROSS_NAME = `t='$(program_transform_cross_name)'; echo g++ | sed $$t`
# The name to use for the demangler program.
DEMANGLER_PROG = c++filt
-
+
+# 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 new1.o new2.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
@@ -62,19 +72,36 @@ C++ c++: cc1plus
# Tell GNU make to ignore these if they exist.
.PHONY: C++ c++
+g++.c: $(srcdir)/gcc.c
+ -rm -f $@
+ $(LN) $(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
+ $(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 $(LIBDEPS) $(EXTRA_GCC_OBJS)
+ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ g++.o g++spec.o prefix.o \
+ version.o choose-temp.o pexecute.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) $(srcdir)/cplus-dem.c cxxmain.c
$(CC) -c -DMAIN $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DVERSION=\"$(version)\" cxxmain.c
rm -f cxxmain.c
@@ -86,26 +113,76 @@ $(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
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
-
+#
# Build hooks:
-c++.all.build: g++ $(DEMANGLER_PROG)
-c++.all.cross: g++-cross $(DEMANGLER_PROG)
-c++.start.encap: g++
+c++.all.build: g++$(exeext) $(DEMANGLER_PROG)
+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 $(srcdir)/cp/tinfo.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/tinfo.cc
+tinfo2.o: cc1plus $(srcdir)/cp/tinfo2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/tinfo2.cc
+exception.o: cc1plus $(srcdir)/cp/exception.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c -fexceptions $(srcdir)/cp/exception.cc
+new.o: cc1plus $(srcdir)/cp/new.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new.cc
+new1.o: cc1plus $(srcdir)/cp/new1.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new1.cc
+new2.o: cc1plus $(srcdir)/cp/new2.cc
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) $(INCLUDES) \
+ -c $(srcdir)/cp/new2.cc
+
+# 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).
@@ -157,7 +234,7 @@ c++.uninstall:
-rm -rf $(bindir)/$(GXX_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 +242,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; \
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/gnu/usr.bin/gcc/cp/call.c b/gnu/usr.bin/gcc/cp/call.c
index 3f293ac809b..8dcbd95776a 100644
--- a/gnu/usr.bin/gcc/cp/call.c
+++ b/gnu/usr.bin/gcc/cp/call.c
@@ -1,5 +1,5 @@
/* Functions related to invoking methods and overloaded functions.
- 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) and
hacked by Brendan Kehoe (brendan@cygnus.com).
@@ -21,7 +21,7 @@ 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 "tree.h"
@@ -31,22 +31,78 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "flags.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
#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 ();
-
/* Compute the ease with which a conversion can be performed
between an expected and the given type. */
-static struct harshness_code convert_harshness ();
+
+static struct harshness_code convert_harshness PROTO((register tree, register tree, tree));
+static tree build_new_method_call PROTO((tree, tree, tree, tree, int));
+
+static int rank_for_ideal PROTO((struct candidate *,
+ struct candidate *));
+static int user_harshness PROTO((tree, tree));
+static int strictly_better PROTO((unsigned int, unsigned int));
+static struct candidate * ideal_candidate PROTO((struct candidate *,
+ int, int));
+static int may_be_remote PROTO((tree));
+static tree build_field_call PROTO((tree, tree, tree, tree));
+static tree find_scoped_type PROTO((tree, tree, tree));
+static void print_candidates PROTO((tree));
+static struct z_candidate * tourney PROTO((struct z_candidate *));
+static int joust PROTO((struct z_candidate *, struct z_candidate *));
+static int compare_qual PROTO((tree, tree));
+static int compare_ics PROTO((tree, tree));
+static tree build_over_call PROTO((tree, tree, tree, int));
+static tree convert_default_arg PROTO((tree, tree));
+static void enforce_access PROTO((tree, tree));
+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));
+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 void print_n_candidates PROTO((struct candidate *, int));
+static tree default_parm_conversions PROTO((tree, tree *));
+static int is_subseq PROTO((tree, tree));
#define EVIL_RETURN(ARG) ((ARG).code = EVIL_CODE, (ARG))
#define STD_RETURN(ARG) ((ARG).code = STD_CODE, (ARG))
@@ -56,6 +112,7 @@ static struct harshness_code convert_harshness ();
/* Ordering function for overload resolution. Compare two candidates
by gross quality. */
+
int
rank_for_overload (x, y)
struct candidate *x, *y;
@@ -83,7 +140,8 @@ rank_for_overload (x, y)
}
/* Compare two candidates, argument by argument. */
-int
+
+static int
rank_for_ideal (x, y)
struct candidate *x, *y;
{
@@ -112,6 +170,7 @@ rank_for_ideal (x, y)
/* 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;
@@ -175,8 +234,8 @@ convert_harshness (type, parmtype, parm)
if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
return EVIL_RETURN (h);
- if (TYPE_READONLY (ttl) < constp
- || TYPE_VOLATILE (ttl) < volatilep)
+ if ((TYPE_READONLY (ttl) < constp)
+ || (TYPE_VOLATILE (ttl) < volatilep))
return EVIL_RETURN (h);
/* When passing a non-const argument into a const reference, dig it a
@@ -232,10 +291,10 @@ convert_harshness (type, parmtype, parm)
tree ttl = TYPE_METHOD_BASETYPE (type);
tree ttr = TYPE_METHOD_BASETYPE (parmtype);
- int b_or_d = get_base_distance (ttr, ttl, 0, 0);
+ int b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (ttl, ttr, 0, 0);
+ b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
@@ -319,7 +378,7 @@ convert_harshness (type, parmtype, parm)
if (h2.distance)
{
- /* This only works for pointers and references. */
+ /* 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);
@@ -365,10 +424,10 @@ convert_harshness (type, parmtype, parm)
h.code = 0;
else
{
- int b_or_d = get_base_distance (ttr, ttl, 0, 0);
+ int b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (ttl, ttr, 0, 0);
+ b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
@@ -433,13 +492,6 @@ convert_harshness (type, parmtype, parm)
== 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;
@@ -475,10 +527,6 @@ convert_harshness (type, parmtype, parm)
}
/* Convert arrays which have not previously been converted. */
-#if 0
- if (codel == ARRAY_TYPE)
- codel = POINTER_TYPE;
-#endif
if (coder == ARRAY_TYPE)
{
coder = POINTER_TYPE;
@@ -519,14 +567,8 @@ convert_harshness (type, parmtype, parm)
#if 1
if (TREE_CODE (ttl) != VOID_TYPE
- && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
+ && (TREE_CODE (ttr) != VOID_TYPE || !parm || !null_ptr_cst_p (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);
}
@@ -541,22 +583,18 @@ convert_harshness (type, parmtype, parm)
return EVIL_RETURN (h);
#endif
- if (penalty == 10 || ttr == ttl)
+ if (ttr == ttl)
{
tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
- /* 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;
-
+ h.code = 0;
/* 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))))
+ if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+ h.code = EVIL_CODE;
+ else if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
h.code |= QUAL_CODE;
h.distance = 0;
@@ -566,10 +604,10 @@ convert_harshness (type, parmtype, parm)
if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
{
- int b_or_d = get_base_distance (ttl, ttr, 0, 0);
+ int b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (ttr, ttl, 0, 0);
+ b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
@@ -595,8 +633,11 @@ convert_harshness (type, parmtype, parm)
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)))
+ if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+ h.code = EVIL_CODE;
+ else if ((TYPE_READONLY (tmp1) > TREE_READONLY (tmp2))
+ || (TYPE_VOLATILE (tmp1) > TYPE_VOLATILE (tmp2)))
h.code |= QUAL_CODE;
}
return h;
@@ -626,10 +667,10 @@ convert_harshness (type, parmtype, parm)
if (codel == RECORD_TYPE && coder == RECORD_TYPE)
{
- int b_or_d = get_base_distance (type, parmtype, 0, 0);
+ int b_or_d = get_base_distance (type, parmtype, 0, (tree*)0);
if (b_or_d < 0)
{
- b_or_d = get_base_distance (parmtype, type, 0, 0);
+ b_or_d = get_base_distance (parmtype, type, 0, (tree*)0);
if (b_or_d < 0)
return EVIL_RETURN (h);
h.distance = -b_or_d;
@@ -645,10 +686,9 @@ convert_harshness (type, parmtype, parm)
/* A clone of build_type_conversion for checking user-defined conversions in
overload resolution. */
-int
-user_harshness (type, parmtype, parm)
+static int
+user_harshness (type, parmtype)
register tree type, parmtype;
- tree parm;
{
tree conv;
tree winner = NULL_TREE;
@@ -663,18 +703,19 @@ user_harshness (type, parmtype, parm)
for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv))
{
struct harshness_code tmp;
+ tree cand = TREE_VALUE (conv);
- if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+ if (winner && winner == cand)
continue;
- if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE),
- tmp.code < USER_CODE && tmp.distance >= 0)
+ tmp = convert_harshness (type, TREE_TYPE (TREE_TYPE (cand)), NULL_TREE);
+ if ((tmp.code < USER_CODE) && (tmp.distance >= 0))
{
if (winner)
return EVIL_CODE;
else
{
- winner = conv;
+ winner = cand;
code = tmp.code;
}
}
@@ -686,24 +727,6 @@ user_harshness (type, parmtype, parm)
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;
-}
-
-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;
-}
-
#ifdef DEBUG_MATCHING
static char *
print_harshness (h)
@@ -969,8 +992,8 @@ compute_conversion_costs (function, tta_in, cp, arglen)
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);
+ formal_type = complete_type (TYPE_MAIN_VARIANT (formal_type));
+ actual_type = complete_type (TYPE_MAIN_VARIANT (actual_type));
if (TYPE_HAS_CONSTRUCTOR (formal_type))
{
@@ -1022,7 +1045,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
}
/* Const member functions get a small penalty because defaulting
- to const is less useful than defaulting to non-const. */
+ 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) */
@@ -1063,9 +1086,10 @@ compute_conversion_costs (function, tta_in, cp, arglen)
/* 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 int x, y;
{
unsigned short xor;
@@ -1091,11 +1115,9 @@ strictly_better (x, y)
LEN is the length of the parameter list. */
static struct candidate *
-ideal_candidate (basetype, candidates, n_candidates, parms, len)
- tree basetype;
+ideal_candidate (candidates, n_candidates, len)
struct candidate *candidates;
int n_candidates;
- tree parms;
int len;
{
struct candidate *cp = candidates+n_candidates;
@@ -1107,36 +1129,9 @@ ideal_candidate (basetype, candidates, n_candidates, parms, len)
list for the last argument is the intersection of all the best-liked
functions. */
-#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);
+ (int (*) PROTO((const void *, const void *))) rank_for_overload);
best_code = cp[-1].h.code;
-#endif
/* 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))
@@ -1149,7 +1144,7 @@ ideal_candidate (basetype, candidates, n_candidates, parms, len)
break;
qsort (candidates+j, n_candidates-j, sizeof (struct candidate),
- rank_for_ideal);
+ (int (*) PROTO((const void *, const void *))) rank_for_ideal);
for (i = 0; i < len; i++)
{
if (cp[-1].harshness[i].code < cp[-2].harshness[i].code)
@@ -1186,6 +1181,7 @@ ideal_candidate (basetype, candidates, n_candidates, parms, len)
/* 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;
@@ -1223,7 +1219,7 @@ build_vfield_ref (datum, 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)), 0, 0);
+ rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0);
flag_assume_nonnull_objects = old_assume_nonnull_objects;
return rval;
@@ -1231,13 +1227,17 @@ build_vfield_ref (datum, type)
/* 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)
+ if (name == ctor_identifier || name == dtor_identifier)
+ return NULL_TREE;
+
+ if (instance_ptr == current_class_ptr)
{
/* Check to see if we really have a reference to an instance variable
with `operator()()' overloaded. */
@@ -1253,12 +1253,13 @@ build_field_call (basetype_path, instance_ptr, name, parms)
{
/* 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);
+ 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))
- && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance)))
+ && (TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance))
+ || flag_ansi_overloading))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE);
if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
@@ -1266,7 +1267,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
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 build_function_call (instance, expr_tree_cons (NULL_TREE, current_class_ptr, parms));
}
}
return NULL_TREE;
@@ -1289,7 +1290,8 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (TREE_CODE (ftype) == REFERENCE_TYPE)
ftype = TREE_TYPE (ftype);
- if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype))
+ if (TYPE_LANG_SPECIFIC (ftype)
+ && (TYPE_OVERLOADS_CALL_EXPR (ftype) || flag_ansi_overloading))
{
/* Make the next search for this field very short. */
basetype = DECL_FIELD_CONTEXT (field);
@@ -1326,7 +1328,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
return NULL_TREE;
}
-tree
+static tree
find_scoped_type (type, inner_name, inner_types)
tree type, inner_name, inner_types;
{
@@ -1341,28 +1343,19 @@ find_scoped_type (type, inner_name, inner_types)
if (TREE_PURPOSE (tags) == inner_name)
{
if (inner_types == NULL_TREE)
- return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags)));
+ return TYPE_MAIN_DECL (TREE_VALUE (tags));
return resolve_scope_to_name (TREE_VALUE (tags), inner_types);
}
tags = TREE_CHAIN (tags);
}
-#if 0
- /* XXX This needs to be fixed better. */
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- {
- sorry ("nested class lookup in template type");
- return NULL_TREE;
- }
-#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 tags;
return resolve_scope_to_name (TREE_TYPE (tags), inner_types);
}
@@ -1374,6 +1367,7 @@ find_scoped_type (type, inner_name, 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;
@@ -1394,7 +1388,7 @@ resolve_scope_to_name (outer_type, inner_stuff)
if (rval != NULL_TREE)
return rval;
- type = DECL_CONTEXT (TYPE_NAME (type));
+ type = DECL_CONTEXT (TYPE_MAIN_DECL (type));
}
}
@@ -1460,9 +1454,10 @@ resolve_scope_to_name (outer_type, inner_stuff)
/* 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;
+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',
@@ -1470,35 +1465,51 @@ build_scoped_method_call (exp, scopes, name, parms)
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 binfo, decl;
tree type = TREE_TYPE (exp);
if (type == error_mark_node
- || basename == NULL_TREE)
+ || basetype == error_mark_node)
return error_mark_node;
- basetype = IDENTIFIER_TYPE_VALUE (basename);
+ if (processing_template_decl)
+ {
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 1);
+ 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);
+ if (TREE_CODE (basetype) == TREE_VEC)
+ {
+ binfo = basetype;
+ basetype = BINFO_TYPE (binfo);
+ }
+ else
+ binfo = 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 (TREE_CODE (name) == BIT_NOT_EXPR && ! IS_AGGR_TYPE (basetype))
{
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))
+ if (basetype != name && basetype != get_type_value (name))
cp_error ("qualified type `%T' does not match destructor name `~%T'",
basetype, name);
- return convert (void_type_node, exp);
+ return cp_convert (void_type_node, exp);
}
- if (! is_aggr_typedef (basename, 1))
+ if (! is_aggr_type (basetype, 1))
return error_mark_node;
if (! IS_AGGR_TYPE (type))
@@ -1508,22 +1519,31 @@ build_scoped_method_call (exp, scopes, name, parms)
return error_mark_node;
}
- if ((binfo = binfo_or_else (basetype, type)))
+ 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 (binfo,
- build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR);
+ decl = build_indirect_ref
+ (convert_pointer_to_real
+ (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR);
else
- decl = build_scoped_ref (exp, scopes);
+ decl = build_scoped_ref (exp, basetype);
/* Call to a destructor. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
/* Explicit call to destructor. */
name = TREE_OPERAND (name, 0);
- if (! (name == constructor_name (TREE_TYPE (decl))
+ if (! (name == TYPE_MAIN_VARIANT (TREE_TYPE (decl))
+ || name == constructor_name (TREE_TYPE (decl))
|| TREE_TYPE (decl) == get_type_value (name)))
{
cp_error
@@ -1532,7 +1552,7 @@ build_scoped_method_call (exp, scopes, name, parms)
return error_mark_node;
}
if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
- return convert (void_type_node, exp);
+ return cp_convert (void_type_node, exp);
return build_delete (TREE_TYPE (decl), decl, integer_two_node,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
@@ -1572,6 +1592,103 @@ print_n_candidates (candidates, n)
cp_error_at (" %D", candidates[i].function);
}
+/* 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);
+
+ /* We have to do these by hand to avoid real pointer to member
+ functions. */
+ if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ 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. */
+
+tree
+build_call (function, result_type, parms)
+ tree function, result_type, parms;
+{
+ int is_constructor = 0;
+
+ 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 (TREE_CODE (function) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
+ && DECL_CONSTRUCTOR_P (TREE_OPERAND (function, 0)))
+ is_constructor = 1;
+
+ 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;
+}
+
+static tree
+default_parm_conversions (parms, last)
+ tree parms, *last;
+{
+ tree parm, parmtypes = NULL_TREE;
+
+ *last = NULL_TREE;
+
+ for (parm = parms; parm; parm = TREE_CHAIN (parm))
+ {
+ tree t = TREE_TYPE (TREE_VALUE (parm));
+
+ if (TREE_CODE (t) == OFFSET_TYPE
+ || TREE_CODE (t) == METHOD_TYPE
+ || TREE_CODE (t) == FUNCTION_TYPE)
+ {
+ TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
+ t = TREE_TYPE (TREE_VALUE (parm));
+ }
+
+ if (t == error_mark_node)
+ return error_mark_node;
+
+ *last = build_tree_list (NULL_TREE, t);
+ parmtypes = chainon (parmtypes, *last);
+ }
+
+ return parmtypes;
+}
+
+
/* Build something of the form ptr->method (args)
or object.method (args). This can also build
calls to constructors, and find friends.
@@ -1603,6 +1720,7 @@ print_n_candidates (candidates, n)
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;
@@ -1610,16 +1728,18 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
register tree function, fntype, value_type;
register tree basetype, save_basetype;
- register tree baselink, result, method_name, parmtypes, parm;
+ register tree baselink, result, parmtypes;
tree last;
int pass;
- enum access_type access = access_public;
+ tree access = access_public_node;
+ tree orig_basetype = basetype_path ? BINFO_TYPE (basetype_path) : NULL_TREE;
/* 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;
+ tree save_name = name;
int ever_seen = 0;
tree instance_ptr = NULL_TREE;
int all_virtual = flag_all_virtual;
@@ -1639,8 +1759,19 @@ build_method_call (instance, name, parms, basetype_path, flags)
|| (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
return error_mark_node;
+ if (processing_template_decl)
+ {
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 1);
+ name = build_min_nt (BIT_NOT_EXPR, type);
+ }
+
+ 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. */
+ operator delete, if it is not needed. */
if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
{
tree save_last = TREE_CHAIN (parms);
@@ -1650,7 +1781,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
result = build_method_call (instance, name, parms, basetype_path,
(LOOKUP_SPECULATIVELY|flags)
&~LOOKUP_COMPLAIN);
- /* If it finds a match, return it. */
+ /* 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 */
@@ -1658,6 +1789,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
}
/* 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;
@@ -1670,17 +1802,18 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype = TREE_TYPE (instance);
if (TREE_CODE (basetype) == REFERENCE_TYPE)
basetype = TREE_TYPE (basetype);
- if (! ((IS_AGGR_TYPE (basetype)
- && name == constructor_name (basetype))
+ if (! (name == basetype
+ || (IS_AGGR_TYPE (basetype)
+ && name == constructor_name (basetype))
|| basetype == get_type_value (name)))
{
cp_error ("destructor name `~%D' does not match type `%T' of expression",
name, basetype);
- return convert (void_type_node, instance);
+ return cp_convert (void_type_node, instance);
}
- if (! TYPE_HAS_DESTRUCTOR (basetype))
- return convert (void_type_node, instance);
+ 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),
@@ -1688,6 +1821,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
}
+ if (flag_ansi_overloading)
+ return build_new_method_call (instance, name, parms, basetype_path, flags);
+
{
char *xref_name;
@@ -1730,13 +1866,17 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (basetype != NULL_TREE)
;
- /* call to a constructor... */
+ /* call to a constructor... */
else if (basetype_path)
- basetype = BINFO_TYPE (basetype_path);
+ {
+ basetype = BINFO_TYPE (basetype_path);
+ if (name == TYPE_IDENTIFIER (basetype))
+ name = ctor_identifier;
+ }
else if (IDENTIFIER_HAS_TYPE_VALUE (name))
{
basetype = IDENTIFIER_TYPE_VALUE (name);
- name = constructor_name_full (basetype);
+ name = ctor_identifier;
}
else
{
@@ -1745,7 +1885,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
/* Canonicalize the typedef name. */
basetype = TREE_TYPE (typedef_name);
- name = TYPE_IDENTIFIER (basetype);
+ name = ctor_identifier;
}
else
{
@@ -1758,18 +1898,18 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (! IS_AGGR_TYPE (basetype))
{
non_aggr_error:
- if ((flags & LOOKUP_COMPLAIN) && TREE_CODE (basetype) != ERROR_MARK)
+ 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);
return error_mark_node;
}
}
- else if (instance == C_C_D || instance == current_class_decl)
+ else if (instance == current_class_ref || instance == current_class_ptr)
{
/* 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);
+ current_class_ref, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE. */
+ basetype = TREE_TYPE (current_class_ref);
/* Anything manifestly `this' in constructors and destructors
has a known type, so virtual function tables are not needed. */
@@ -1785,14 +1925,13 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& TYPE_IDENTIFIER (basetype) != name)
{
basetype = SIGNATURE_TYPE (basetype);
- instance_ptr = build_optr_ref (instance);
- instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
+ instance_ptr = instance;
basetype_path = TYPE_BINFO (basetype);
}
else
{
- instance = C_C_D;
- instance_ptr = current_class_decl;
+ instance = current_class_ref;
+ instance_ptr = current_class_ptr;
basetype_path = TYPE_BINFO (current_class_type);
}
result = build_field_call (basetype_path, instance_ptr, name, parms);
@@ -1815,10 +1954,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
/* The MAIN_VARIANT of the type that `instance_ptr' winds up being. */
tree inst_ptr_basetype;
- 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);
+ 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);
if (TREE_CODE (instance) == OFFSET_REF)
instance = resolve_offset_ref (instance);
@@ -1853,6 +1992,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& TYPE_IDENTIFIER (basetype) != name)
basetype = SIGNATURE_TYPE (basetype);
+ basetype = complete_type (basetype);
+
if ((IS_SIGNATURE (basetype)
&& (instance_ptr = instance))
|| (lvalue_p (instance)
@@ -1886,7 +2027,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (TREE_CODE (instance) != CALL_EXPR)
my_friendly_abort (125);
if (TYPE_NEEDS_CONSTRUCTING (basetype))
- instance = build_cplus_new (basetype, instance, 0);
+ instance = build_cplus_new (basetype, instance);
else
{
instance = get_temp_name (basetype, 0);
@@ -1903,7 +2044,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype = inst_ptr_basetype;
else
{
- instance_ptr = convert (build_pointer_type (basetype), instance_ptr);
+ instance_ptr = cp_convert (build_pointer_type (basetype), instance_ptr);
if (instance_ptr == error_mark_node)
return error_mark_node;
}
@@ -1914,8 +2055,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
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))
+ else if (basetype_path == NULL_TREE
+ || (BINFO_TYPE (basetype_path)
+ != TYPE_MAIN_VARIANT (inst_ptr_basetype)))
basetype_path = TYPE_BINFO (inst_ptr_basetype);
result = build_field_call (basetype_path, instance_ptr, name, parms);
@@ -1944,7 +2086,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
}
}
- if (TYPE_SIZE (basetype) == 0)
+ if (save_name == ctor_identifier)
+ save_name = TYPE_IDENTIFIER (basetype);
+
+ if (TYPE_SIZE (complete_type (basetype)) == 0)
{
/* This is worth complaining about, I think. */
cp_error ("cannot lookup method in incomplete type `%T'", basetype);
@@ -1953,44 +2098,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
save_basetype = TYPE_MAIN_VARIANT (basetype);
-#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;
-#endif
-
- last = NULL_TREE;
- for (parmtypes = NULL_TREE, parm = parms; parm; parm = TREE_CHAIN (parm))
+ parmtypes = default_parm_conversions (parms, &last);
+ if (parmtypes == error_mark_node)
{
- tree t = TREE_TYPE (TREE_VALUE (parm));
- if (TREE_CODE (t) == OFFSET_TYPE)
- {
- /* Convert OFFSET_TYPE entities to their normal selves. */
- TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
- t = TREE_TYPE (TREE_VALUE (parm));
- }
- if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
- && TREE_CODE (t) == METHOD_TYPE)
- {
- TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
- }
-#if 0
- /* This breaks reference-to-array parameters. */
- if (TREE_CODE (t) == ARRAY_TYPE)
- {
- /* 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));
- }
-#endif
- if (t == error_mark_node)
- return error_mark_node;
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
+ return error_mark_node;
}
if (instance && IS_SIGNATURE (basetype))
@@ -1999,14 +2110,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
of the signature pointer? */
constp = TYPE_READONLY (basetype);
volatilep = TYPE_VOLATILE (basetype);
- parms = tree_cons (NULL_TREE, instance_ptr, parms);
+ parms = expr_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);
+ parms = expr_tree_cons (NULL_TREE, instance_ptr, parms);
}
else
{
@@ -2015,33 +2126,35 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& ! (flags & LOOKUP_HAS_IN_CHARGE))
{
flags |= LOOKUP_HAS_IN_CHARGE;
- parms = tree_cons (NULL_TREE, integer_one_node, parms);
- parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);
+ parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);
+ parmtypes = scratch_tree_cons (NULL_TREE, integer_type_node, parmtypes);
}
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);
+ parms = expr_tree_cons (NULL_TREE, instance_ptr, parms);
}
- parmtypes = tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
+ parmtypes = scratch_tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
if (last == NULL_TREE)
last = parmtypes;
/* Look up function name in the structure type definition. */
+ /* FIXME Axe most of this now? */
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))
+ && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name)))
+ || name == constructor_name (basetype)
+ || name == ctor_identifier)
{
tree tmp = NULL_TREE;
if (IDENTIFIER_TYPE_VALUE (name) == basetype
- || name == constructor_name (basetype))
+ || name == constructor_name (basetype)
+ || name == ctor_identifier)
tmp = TYPE_BINFO (basetype);
else
tmp = get_binfo (IDENTIFIER_TYPE_VALUE (name), basetype, 0);
@@ -2058,10 +2171,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
tree tmplist;
flags |= LOOKUP_HAS_IN_CHARGE;
- tmplist = tree_cons (NULL_TREE, integer_zero_node,
+ tmplist = expr_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));
+ tmplist = scratch_tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes));
TREE_CHAIN (parmtypes) = tmplist;
}
basetype = BINFO_TYPE (tmp);
@@ -2080,19 +2193,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
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++)
{
struct candidate *candidates;
@@ -2100,10 +2200,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
int len;
unsigned best = 1;
- /* 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;
-
baselink = result;
if (pass > 0)
@@ -2129,13 +2225,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
else
my_friendly_abort (167);
- friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
+ friend_parms = expr_tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
cp->h_len = len;
cp->harshness = (struct harshness_code *)
alloca ((len + 1) * sizeof (struct harshness_code));
- result = build_overload_call (name, friend_parms, 0, cp);
+ result = build_overload_call_real (name, friend_parms, 0, cp, 1);
+
/* If it turns out to be the one we were actually looking for
(it was probably a friend function), the return the
good result. */
@@ -2155,7 +2252,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
}
}
- while (baselink)
+ if (baselink)
{
/* We have a hit (of sorts). If the parameter list is
"error_mark_node", or some variant thereof, it won't
@@ -2171,30 +2268,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
basetype_path = TREE_VALUE (basetype_path);
basetype = BINFO_TYPE (basetype_path);
-#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);
- }
- }
-
- /* 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 (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
- function = DECL_CHAIN (function);
-
for (; function; function = DECL_CHAIN (function))
{
#ifdef GATHER_STATISTICS
@@ -2202,19 +2275,13 @@ build_method_call (instance, name, parms, basetype_path, flags)
#endif
ever_seen++;
if (pass > 0)
- found_fns = tree_cons (NULL_TREE, function, found_fns);
+ found_fns = scratch_tree_cons (NULL_TREE, function, found_fns);
/* Not looking for friends here. */
if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE
&& ! DECL_STATIC_FUNCTION_P (function))
continue;
-#if 0
- if (pass == 0
- && DECL_ASSEMBLER_NAME (function) == method_name)
- goto found;
-#endif
-
if (pass > 0)
{
tree these_parms = parms;
@@ -2236,7 +2303,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
cp->function = function;
cp->basetypes = basetype_path;
- /* Don't allow non-converting constructors to convert. */
+ /* Don't allow non-converting constructors to convert. */
if (flags & LOOKUP_ONLYCONVERTING
&& DECL_LANG_SPECIFIC (function)
&& DECL_NONCONVERTING_P (function))
@@ -2251,14 +2318,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
}
}
}
- /* 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)
{
tree igv = lookup_name_nonclass (name);
@@ -2282,10 +2343,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
TREE_CHAIN (last) = void_list_node;
if (flags & LOOKUP_GLOBAL)
cp_error ("no global or member function `%D(%A)' defined",
- name, parmtypes);
+ save_name, parmtypes);
else
cp_error ("no member function `%T::%D(%A)' defined",
- save_basetype, name, TREE_CHAIN (parmtypes));
+ save_basetype, save_name, TREE_CHAIN (parmtypes));
return error_mark_node;
}
continue;
@@ -2303,15 +2364,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
int n_candidates = cp - candidates;
extern int warn_synth;
TREE_VALUE (parms) = instance_ptr;
- cp = ideal_candidate (save_basetype, candidates,
- n_candidates, parms, len);
+ cp = ideal_candidate (candidates, n_candidates, 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));
+ name_kind, save_name, TREE_CHAIN (parmtypes));
print_n_candidates (candidates, n_candidates);
}
return error_mark_node;
@@ -2333,7 +2393,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
if (flags & LOOKUP_COMPLAIN)
cp_error ("ambiguous type conversion requested for %s `%D'",
- name_kind, name);
+ name_kind, save_name);
return error_mark_node;
}
else
@@ -2378,7 +2438,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
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),
+ save_name, TREE_CHAIN (parmtypes),
TREE_TYPE (TREE_TYPE (instance_ptr)));
TREE_CHAIN (last) = NULL_TREE;
print_candidates (found_fns);
@@ -2391,7 +2451,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
== LOOKUP_COMPLAIN)
{
- cp_error ("%T has no method named %D", save_basetype, name);
+ cp_error ("%T has no method named %D", save_basetype, save_name);
return error_mark_node;
}
return NULL_TREE;
@@ -2421,7 +2481,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
if (flags & LOOKUP_PROTECT)
access = compute_access (basetype_path, function);
- if (access == access_private)
+ if (access == access_private_node)
{
if (flags & LOOKUP_COMPLAIN)
{
@@ -2432,7 +2492,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
}
return error_mark_node;
}
- else if (access == access_protected)
+ else if (access == access_protected_node)
{
if (flags & LOOKUP_COMPLAIN)
{
@@ -2448,37 +2508,25 @@ build_method_call (instance, name, parms, basetype_path, flags)
type (if it exists) is a pointer to. */
if (DECL_ABSTRACT_VIRTUAL_P (function)
- && instance == C_C_D
+ && 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)
+ if (IS_SIGNATURE (basetype))
{
- cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
- basetype, name);
- return error_mark_node;
+ if (static_call_context)
+ {
+ cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
+ basetype, save_name);
+ return error_mark_node;
}
- else if (IS_SIGNATURE (basetype))
- return build_signature_method_call (basetype, instance, function, parms);
+ return build_signature_method_call (function, parms);
+ }
function = DECL_MAIN_VARIANT (function);
- /* Declare external function if necessary. */
- assemble_external (function);
-
-#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
-
- 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);
+ mark_used (function);
fntype = TREE_TYPE (function);
if (TREE_CODE (fntype) == POINTER_TYPE)
@@ -2505,21 +2553,23 @@ build_method_call (instance, name, parms, basetype_path, flags)
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;
+ /* Let's be nasty to the user now, and give reasonable
+ error messages. */
+ instance_ptr = current_class_ptr;
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)
+ if (basetype == error_mark_node)
return error_mark_node;
+ else
+ {
+ if (orig_basetype != NULL_TREE)
+ error_not_base_type (orig_basetype, current_class_type);
+ else
+ error_not_base_type (function, current_class_type);
+ return error_mark_node;
+ }
}
}
/* Only allow a static member function to call another static member
@@ -2535,7 +2585,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
- if (TYPE_SIZE (value_type) == 0)
+ if (TYPE_SIZE (complete_type (value_type)) == 0)
{
if (flags & LOOKUP_COMPLAIN)
incomplete_type_error (0, value_type);
@@ -2549,14 +2599,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
{
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))
+ if (TYPE_METHOD_BASETYPE (TREE_TYPE (function))
+ != TYPE_MAIN_VARIANT (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,
+ parms = expr_tree_cons (NULL_TREE, instance_ptr,
convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, sub_flags));
}
else
@@ -2597,58 +2647,17 @@ build_method_call (instance, name, parms, basetype_path, flags)
&& 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)
+ else if (instance_ptr == error_mark_node)
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,
+ parms = expr_tree_cons (NULL_TREE, instance_ptr,
convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL));
}
-#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;
-
- parms = TREE_CHAIN (parms);
-
- 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);
-
- result = build_opfncall (METHOD_CALL_EXPR, LOOKUP_NORMAL, instance, fn_as_int, parms);
-
- 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 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
-
- return result;
- }
-#endif
-
if (parms == error_mark_node
|| (parms && TREE_CHAIN (parms) == error_mark_node))
return error_mark_node;
@@ -2664,29 +2673,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
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;
- }
+ result = build_call (function, value_type, parms);
+ if (IS_AGGR_TYPE (value_type))
+ result = build_cplus_new (value_type, result);
+ result = convert_from_reference (result);
+ return result;
}
/* Similar to `build_method_call', but for overloaded non-member functions.
@@ -2710,15 +2701,15 @@ build_method_call (instance, name, parms, basetype_path, flags)
function's new name. */
tree
-build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
+build_overload_call_real (fnname, parms, flags, final_cp, require_complete)
tree fnname, parms;
int flags;
struct candidate *final_cp;
- int buildxxx;
+ int require_complete;
{
/* must check for overloading here */
- tree overload_name, functions, function, parm;
- tree parmtypes = NULL_TREE, last = NULL_TREE;
+ tree functions, function;
+ tree parmtypes, last;
register tree outer;
int length;
int parmlength = list_length (parms);
@@ -2734,31 +2725,14 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
final_cp[1].h.code = EVIL_CODE;
}
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
+ parmtypes = default_parm_conversions (parms, &last);
+ if (parmtypes == error_mark_node)
{
- register tree t = TREE_TYPE (TREE_VALUE (parm));
-
- if (t == error_mark_node)
- {
- if (final_cp)
- final_cp->h.code = EVIL_CODE;
- return error_mark_node;
- }
- if (TREE_CODE (t) == OFFSET_TYPE)
-#if 0
- /* This breaks reference-to-array parameters. */
- || TREE_CODE (t) == ARRAY_TYPE
-#endif
- {
- /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
- 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));
- }
- last = build_tree_list (NULL_TREE, t);
- parmtypes = chainon (parmtypes, last);
+ if (final_cp)
+ final_cp->h.code = EVIL_CODE;
+ return error_mark_node;
}
+
if (last)
TREE_CHAIN (last) = void_list_node;
else
@@ -2838,7 +2812,6 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
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))
{
enum tree_code code = TREE_CODE (function);
@@ -2868,15 +2841,20 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
}
if (TREE_CODE (function) == TEMPLATE_DECL)
{
- int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (function));
- tree *targs = (tree *) alloca (sizeof (tree) * ntparms);
+ int ntparms = DECL_NTPARMS (function);
+ tree targs = make_scratch_vec (ntparms);
int i;
- i = type_unification (DECL_TEMPLATE_PARMS (function), targs,
+ i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
+ &TREE_VEC_ELT (targs, 0),
TYPE_ARG_TYPES (TREE_TYPE (function)),
- parms, &template_cost, 0);
+ parms, NULL_TREE, &template_cost, 0, 0);
if (i == 0)
- function = instantiate_template (function, targs);
+ {
+ function = instantiate_template (function, targs);
+ if (function == error_mark_node)
+ return function;
+ }
}
if (TREE_CODE (function) == TEMPLATE_DECL)
@@ -2907,7 +2885,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
passed to calling function. */
cp->h_len = parmlength;
cp->harshness = (struct harshness_code *)
- oballoc ((parmlength + 1) * sizeof (struct harshness_code));
+ scratchalloc ((parmlength + 1) * sizeof (struct harshness_code));
compute_conversion_costs (function, parms, cp, parmlength);
@@ -2931,8 +2909,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
if (cp - candidates > 1)
{
struct candidate *best_cp
- = ideal_candidate (NULL_TREE, candidates,
- cp - candidates, parms, parmlength);
+ = ideal_candidate (candidates, cp - candidates, parmlength);
if (best_cp == (struct candidate *)0)
{
if (flags & LOOKUP_COMPLAIN)
@@ -2960,34 +2937,3320 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
if (final_cp)
return rval;
- return buildxxx ? build_function_call_real (rval, parms, 0, flags)
- : build_function_call_real (rval, parms, 1, flags);
+ return build_function_call_real (rval, parms, require_complete, flags);
}
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
if (flags & LOOKUP_COMPLAIN)
- report_type_mismatch (cp, parms, "function",
- decl_as_string (cp->function, 1));
+ report_type_mismatch (cp, parms, "function");
return error_mark_node;
}
+/* This requires a complete type on the result of the call. */
+
tree
-build_overload_call (fnname, parms, flags, final_cp)
+build_overload_call (fnname, parms, flags)
tree fnname, parms;
int flags;
- struct candidate *final_cp;
{
- return build_overload_call_real (fnname, parms, flags, final_cp, 0);
+ return build_overload_call_real (fnname, parms, flags, (struct candidate *)0, 1);
+}
+
+/* New overloading code. */
+
+struct z_candidate {
+ tree fn;
+ tree convs;
+ tree second_conv;
+ int viable;
+ tree basetype_path;
+ tree template;
+ 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_FN(NODE) TREE_OPERAND (NODE, 1)
+
+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));
+ tree nconv = NULL_TREE;
+
+ if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (from)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (to)), 1))
+ nconv = conv;
+ 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))));
+ nconv = 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)))
+ {
+ from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
+ from = build_pointer_type (from);
+ nconv = build_conv (PMEM_CONV, from, conv);
+ }
+ }
+ else if (IS_AGGR_TYPE (TREE_TYPE (from))
+ && IS_AGGR_TYPE (TREE_TYPE (to)))
+ {
+ 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);
+ nconv = build_conv (PTR_CONV, from, conv);
+ }
+ }
+
+ if (nconv && comptypes (from, to, 1))
+ conv = nconv;
+ else if (nconv && comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
+ conv = build_conv (QUAL_CONV, to, nconv);
+ else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
+ {
+ 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 (tcode == BOOLEAN_TYPE)
+ {
+ 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))
+ conv = build_conv (BASE_CONV, to, conv);
+ else
+ return 0;
+
+ 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;
+
+ related = (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from)
+ || (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
+ && DERIVED_FROM_P (to, from)));
+
+ if (lvalue && related
+ && TYPE_READONLY (to) >= TYPE_READONLY (from)
+ && TYPE_VOLATILE (to) >= TYPE_VOLATILE (from))
+ {
+ conv = build1 (IDENTITY_CONV, from, expr);
+
+ if (TYPE_MAIN_VARIANT (to) == TYPE_MAIN_VARIANT (from))
+ conv = build_conv (REF_BIND, rto, conv);
+ else
+ {
+ conv = build_conv (REF_BIND, rto, conv);
+ ICS_STD_RANK (conv) = STD_RANK;
+ }
+ }
+ else
+ conv = NULL_TREE;
+
+ if (! conv)
+ {
+ conv = standard_conversion (to, rfrom, expr);
+ if (conv)
+ {
+ 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);
+ }
+ 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;
+ }
+
+ return conv;
+}
+
+/* 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. */
+
+static tree
+implicit_conversion (to, from, expr, flags)
+ tree to, from, expr;
+ int flags;
+{
+ tree conv;
+ struct z_candidate *cand;
+
+ if (expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return 0;
+ from = TREE_TYPE (expr);
+ }
+
+ if (TREE_CODE (to) == REFERENCE_TYPE)
+ conv = reference_binding (to, from, expr, flags);
+ else
+ conv = standard_conversion (to, from, expr);
+
+ if (conv)
+ ;
+ else if ((IS_AGGR_TYPE (non_reference (from))
+ || IS_AGGR_TYPE (non_reference (to)))
+ && (flags & LOOKUP_NO_CONVERSION) == 0)
+ {
+ 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)
+ {
+ 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);
+ }
+ }
+ }
+
+ return conv;
+}
+
+/* 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;
+ struct z_candidate *cand;
+
+ /* The `this' and `in_chrg' arguments to constructors are not considered
+ in overload resolution. */
+ if (DECL_CONSTRUCTOR_P (fn))
+ {
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
+ if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ {
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
+ }
+ }
+
+ len = list_length (argnode);
+ convs = make_scratch_vec (len);
+
+ for (i = 0; i < len; ++i)
+ {
+ tree arg = TREE_VALUE (argnode);
+ tree argtype = TREE_TYPE (arg);
+ tree t;
+
+ argtype = cp_build_type_variant
+ (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
+
+ if (parmnode == void_list_node)
+ break;
+ else if (parmnode)
+ t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags);
+ else
+ {
+ t = build1 (IDENTITY_CONV, argtype, arg);
+ ICS_ELLIPSIS_FLAG (t) = 1;
+ }
+
+ if (i == 0 && t && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
+ && ! DECL_CONSTRUCTOR_P (fn))
+ ICS_THIS_FLAG (t) = 1;
+
+ TREE_VEC_ELT (convs, i) = t;
+ if (! t)
+ break;
+
+ if (ICS_BAD_FLAG (t))
+ viable = -1;
+
+ if (parmnode)
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
+ }
+
+ if (i < len)
+ viable = 0;
+
+ /* Make sure there are default args for the rest of the parms. */
+ for (; parmnode && parmnode != void_list_node;
+ parmnode = TREE_CHAIN (parmnode))
+ if (! TREE_PURPOSE (parmnode))
+ {
+ viable = 0;
+ break;
+ }
+
+ 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->next = candidates;
+
+ return cand;
+}
+
+/* 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. */
+
+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;
+ struct z_candidate *cand;
+ int flags = LOOKUP_NORMAL;
+
+ for (i = 0; i < len; ++i)
+ {
+ 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
+ {
+ t = build1 (IDENTITY_CONV, argtype, arg);
+ ICS_ELLIPSIS_FLAG (t) = 1;
+ }
+
+ TREE_VEC_ELT (convs, i) = t;
+ if (! t)
+ break;
+
+ if (ICS_BAD_FLAG (t))
+ viable = -1;
+
+ if (i == 0)
+ continue;
+
+ if (parmnode)
+ parmnode = TREE_CHAIN (parmnode);
+ argnode = TREE_CHAIN (argnode);
+ }
+
+ if (i < len)
+ viable = 0;
+
+ for (; parmnode && parmnode != void_list_node;
+ parmnode = TREE_CHAIN (parmnode))
+ if (! TREE_PURPOSE (parmnode))
+ {
+ viable = 0;
+ break;
+ }
+
+ 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->next = candidates;
+
+ return cand;
+}
+
+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;
+
+{
+ tree t, convs;
+ int viable = 1, i;
+ struct z_candidate *cand;
+ tree types[2];
+
+ types[0] = type1;
+ types[1] = type2;
+
+ convs = make_scratch_vec (args[2] ? 3 : (args[1] ? 2 : 1));
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (! args[i])
+ break;
+
+ t = implicit_conversion (types[i], argtypes[i], args[i], flags);
+ if (! t)
+ {
+ 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;
+ }
+
+ /* 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;
+ }
+
+ cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
+
+ cand->fn = fnname;
+ cand->convs = convs;
+ cand->second_conv = NULL_TREE;
+ cand->viable = viable;
+ cand->basetype_path = NULL_TREE;
+ cand->template = NULL_TREE;
+ cand->next = candidates;
+
+ return cand;
+}
+
+static int
+is_complete (t)
+ tree t;
+{
+ return TYPE_SIZE (complete_type (t)) != NULL_TREE;
+}
+
+/* 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;
+{
+ switch (code)
+ {
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ args[1] = integer_zero_node;
+ type2 = integer_type_node;
+ }
+
+ switch (code)
+ {
+
+/* 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;
+
+/* 7 For every cv-qualified or cv-unqualified complete object type T, there
+ exist candidate operator functions of the form
+
+ T& operator*(T*);
+
+ 8 For every function type T, there exist candidate operator functions of
+ the form
+ T& operator*(T*); */
+
+ case INDIRECT_REF:
+ if (TREE_CODE (type1) == POINTER_TYPE
+ && (TYPE_PTROB_P (type1)
+ || TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE))
+ break;
+ return candidates;
+
+/* 9 For every type T, there exist candidate operator functions of the form
+ T* operator+(T*);
+
+ 10For every promoted arithmetic type T, there exist candidate operator
+ functions of the form
+ T operator+(T);
+ T operator-(T); */
+
+ 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;
+
+/* 11For every promoted integral type T, there exist candidate operator
+ functions of the form
+ T operator~(T); */
+
+ 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;
+ }
+ 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))
+ {
+ 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 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]))
+ {
+ type2 = type1;
+ break;
+ }
+ if ((TYPE_PTRMEMFUNC_P (type2) || TYPE_PTRMEM_P (type2))
+ && null_ptr_cst_p (args[0]))
+ {
+ type1 = type2;
+ break;
+ }
+ 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]))
+ {
+ type2 = type1;
+ break;
+ }
+ if (null_ptr_cst_p (args[0]) && TYPE_PTR_P (type2))
+ {
+ type1 = type2;
+ break;
+ }
+ 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))
+ {
+ type1 = ptrdiff_type_node;
+ break;
+ }
+ if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ {
+ type2 = ptrdiff_type_node;
+ break;
+ }
+ 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;
+
+ 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;
+
+ 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))
+ {
+ type2 = type1;
+ break;
+ }
+ if (((TYPE_PTRMEMFUNC_P (type2) || TREE_CODE (type2) == POINTER_TYPE)
+ && null_ptr_cst_p (args[0]))
+ || IS_AGGR_TYPE (type2))
+ {
+ type1 = type2;
+ break;
+ }
+ return candidates;
+
+ default:
+ my_friendly_abort (367);
+ }
+
+ /* 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);
+ }
+
+ return build_builtin_candidate
+ (candidates, fnname, type1, type2, args, argtypes, flags);
}
tree
-build_overload_call_maybe (fnname, parms, flags, final_cp)
- tree fnname, parms;
+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;
+}
+
+/* There are three conditions of builtin candidates:
+
+ 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... */
+
+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;
- struct candidate *final_cp;
{
- return build_overload_call_real (fnname, parms, flags, final_cp, 1);
+ 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;
+ }
+
+ switch (code)
+ {
+/* 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;
+ }
+
+ types[0] = types[1] = NULL_TREE;
+
+ for (i = 0; i < 2; ++i)
+ {
+ if (! args[i])
+ ;
+ else if (IS_AGGR_TYPE (argtypes[i]))
+ {
+ tree convs = lookup_conversions (argtypes[i]);
+
+ if (code == COND_EXPR)
+ {
+ if (real_lvalue_p (args[i]))
+ types[i] = scratch_tree_cons
+ (NULL_TREE, build_reference_type (argtypes[i]), types[i]);
+
+ types[i] = scratch_tree_cons
+ (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
+ }
+
+ else if (! convs || (i == 0 && code == MODIFY_EXPR
+ && code2 == NOP_EXPR))
+ return candidates;
+
+ 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 (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE)
+ types[i] = scratch_tree_cons (NULL_TREE, type, types[i]);
+
+ 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);
+ }
+
+ if (! value_member (type, types[i]))
+ types[i] = scratch_tree_cons (NULL_TREE, type, types[i]);
+ }
+ }
+ 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)
+ {
+ 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]);
+ }
+ }
+
+ 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 candidates;
+}
+
+/* If TMPL can be successfully instantiated as indicated by
+ EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES.
+
+ 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. FLAGS are as for
+ add_function_candidate. */
+
+static struct z_candidate *
+add_template_candidate (candidates, tmpl, explicit_targs,
+ arglist, return_type, flags)
+ struct z_candidate *candidates;
+ tree tmpl, explicit_targs, arglist, return_type;
+ int flags;
+{
+ int ntparms = DECL_NTPARMS (tmpl);
+ tree targs = make_scratch_vec (ntparms);
+ struct z_candidate *cand;
+ int i;
+ tree fn;
+
+ i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
+ return_type, 0);
+
+ if (i != 0)
+ return candidates;
+
+ fn = instantiate_template (tmpl, targs);
+ if (fn == error_mark_node)
+ return candidates;
+
+ cand = add_function_candidate (candidates, fn, arglist, flags);
+ cand->template = DECL_TEMPLATE_INFO (fn);
+ return cand;
+}
+
+
+static struct z_candidate *
+add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
+ struct z_candidate *candidates;
+ tree tmpl, obj, arglist, return_type;
+{
+ int ntparms = DECL_NTPARMS (tmpl);
+ tree targs = make_scratch_vec (ntparms);
+ struct z_candidate *cand;
+ int i;
+ tree fn;
+
+ i = fn_type_unification (tmpl, NULL_TREE, targs, arglist, return_type, 0);
+
+ if (i != 0)
+ return candidates;
+
+ fn = instantiate_template (tmpl, targs);
+ if (fn == error_mark_node)
+ return candidates;
+
+ cand = add_conv_candidate (candidates, fn, obj, arglist);
+ cand->template = DECL_TEMPLATE_INFO (fn);
+ return cand;
+}
+
+
+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;
+}
+
+static struct z_candidate *
+splice_viable (cands)
+ struct z_candidate *cands;
+{
+ struct z_candidate **p = &cands;
+
+ for (; *p; )
+ {
+ if (pedantic ? (*p)->viable == 1 : (*p)->viable)
+ p = &((*p)->next);
+ else
+ *p = (*p)->next;
+ }
+
+ return cands;
+}
+
+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);
+}
+
+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)
+ {
+ if (candidates->fn == ansi_opname [COND_EXPR])
+ cp_error ("%s %D(%T, %T, %T) <builtin>", 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) <builtin>", 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) <builtin>", str, candidates->fn,
+ TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
+ }
+ else
+ cp_error_at ("%s %+D%s", str, candidates->fn,
+ candidates->viable == -1 ? " <near match>" : "");
+ str = " ";
+ }
+}
+
+/* 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. */
+
+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;
+ 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)
+ {
+ 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 = DECL_CHAIN (ctors))
+ {
+ if (DECL_NONCONVERTING_P (ctors))
+ continue;
+
+ if (TREE_CODE (ctors) == TEMPLATE_DECL)
+ {
+ templates = scratch_tree_cons (NULL_TREE, ctors, templates);
+ candidates =
+ add_template_candidate (candidates, ctors,
+ NULL_TREE, args, NULL_TREE, flags);
+ }
+ else
+ candidates = add_function_candidate (candidates, ctors,
+ args, flags);
+
+ if (candidates)
+ {
+ candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE);
+ candidates->basetype_path = TYPE_BINFO (totype);
+ }
+ }
+
+ if (convs)
+ args = build_scratch_list (NULL_TREE, build_this (expr));
+
+ for (; convs; convs = TREE_CHAIN (convs))
+ {
+ tree fn = 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;
+
+ ics = implicit_conversion
+ (totype, TREE_TYPE (TREE_TYPE (fn)), 0, convflags);
+
+ if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
+ /* ignore the near match. */;
+ else if (ics)
+ for (; fn; fn = DECL_CHAIN (fn))
+ {
+ 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);
+ }
+ else
+ candidates = add_function_candidate (candidates, fn,
+ args, flags);
+
+ if (candidates)
+ {
+ candidates->second_conv = ics;
+ candidates->basetype_path = TREE_PURPOSE (convs);
+ 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
+
+ return 0;
+ }
+
+ 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, cand->fn, cand->convs, cand->basetype_path);
+ ICS_USER_FLAG (cand->second_conv) = 1;
+ if (cand->viable == -1)
+ ICS_BAD_FLAG (cand->second_conv) = 1;
+
+ return cand;
+}
+
+tree
+build_user_type_conversion (totype, expr, flags)
+ tree totype, expr;
+ int flags;
+{
+ struct z_candidate *cand
+ = build_user_type_conversion_1 (totype, expr, flags);
+
+ if (cand)
+ {
+ 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;
+}
+
+/* Do any initial processing on the arguments to a function call. */
+
+static tree
+resolve_args (args)
+ tree args;
+{
+ tree t;
+ for (t = args; t; t = TREE_CHAIN (t))
+ {
+ if (TREE_VALUE (t) == error_mark_node)
+ return error_mark_node;
+ else if (TREE_CODE (TREE_TYPE (TREE_VALUE (t))) == VOID_TYPE)
+ {
+ 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;
+}
+
+tree
+build_new_function_call (fn, args, obj)
+ tree fn, args, obj;
+{
+ struct z_candidate *candidates = 0, *cand;
+ tree explicit_targs = NULL_TREE;
+ int template_only = 0;
+
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ {
+ explicit_targs = TREE_OPERAND (fn, 1);
+ fn = TREE_OPERAND (fn, 0);
+ template_only = 1;
+ }
+
+ if (obj == NULL_TREE && really_overloaded_fn (fn))
+ {
+ tree t;
+ tree templates = NULL_TREE;
+
+ args = resolve_args (args);
+
+ if (args == error_mark_node)
+ return error_mark_node;
+
+ for (t = TREE_VALUE (fn); t; t = DECL_CHAIN (t))
+ {
+ 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);
+ }
+ else if (! template_only)
+ candidates = add_function_candidate
+ (candidates, t, args, LOOKUP_NORMAL);
+ }
+
+ 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)'",
+ TREE_PURPOSE (fn), args);
+ if (candidates)
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
+ candidates = splice_viable (candidates);
+ cand = tourney (candidates);
+
+ if (cand == 0)
+ {
+ cp_error ("call of overloaded `%D (%A)' is ambiguous",
+ TREE_PURPOSE (fn), args);
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
+
+ /* 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->fn, cand->convs, args, LOOKUP_NORMAL);
+ }
+
+ return build_function_call (fn, args);
+}
+
+static tree
+build_object_call (obj, args)
+ tree obj, args;
+{
+ struct z_candidate *candidates = 0, *cand;
+ tree fns, convs, mem_args;
+ tree type = TREE_TYPE (obj);
+ tree templates = NULL_TREE;
+
+ fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 0);
+
+ args = resolve_args (args);
+
+ if (args == error_mark_node)
+ return error_mark_node;
+
+ if (fns)
+ {
+ tree fn = TREE_VALUE (fns);
+ mem_args = scratch_tree_cons (NULL_TREE, build_this (obj), args);
+
+ for (; fn; fn = DECL_CHAIN (fn))
+ {
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ {
+ templates = scratch_tree_cons (NULL_TREE, fn, templates);
+ candidates
+ = add_template_candidate (candidates, fn, NULL_TREE,
+ mem_args, NULL_TREE,
+ LOOKUP_NORMAL);
+ }
+ else
+ candidates = add_function_candidate
+ (candidates, fn, mem_args, LOOKUP_NORMAL);
+
+ if (candidates)
+ candidates->basetype_path = TREE_PURPOSE (fns);
+ }
+ }
+
+ convs = lookup_conversions (type);
+
+ for (; convs; convs = TREE_CHAIN (convs))
+ {
+ tree fn = TREE_VALUE (convs);
+ tree totype = TREE_TYPE (TREE_TYPE (fn));
+
+ if (TREE_CODE (totype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+ for (; fn; fn = DECL_CHAIN (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);
+ }
+ }
+
+ 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);
+
+ if (cand == 0)
+ {
+ 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->fn, cand->convs, mem_args, LOOKUP_NORMAL);
+
+ obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
+
+ /* FIXME */
+ return build_function_call (obj, args);
+}
+
+static void
+op_error (code, code2, arg1, arg2, arg3, problem)
+ enum tree_code code, code2;
+ tree arg1, arg2, arg3;
+ char *problem;
+{
+ char * opname
+ = (code == MODIFY_EXPR ? assignop_tab [code2] : opname_tab [code]);
+
+ 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));
+ }
+}
+
+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, arglist, fnname;
+ enum tree_code code2 = NOP_EXPR;
+ tree templates = NULL_TREE;
+ tree conv;
+
+ if (arg1 == error_mark_node
+ || arg2 == error_mark_node
+ || arg3 == error_mark_node)
+ return error_mark_node;
+
+ /* 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;
+ }
+
+ if (code == MODIFY_EXPR)
+ {
+ code2 = TREE_CODE (arg3);
+ arg3 = NULL_TREE;
+ fnname = ansi_assopname[code2];
+ }
+ else
+ fnname = ansi_opname[code];
+
+ 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_name_nonclass (fnname), arglist, NULL_TREE);
+
+ /* 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;
+ TREE_CALLS_NEW (rval) = 1;
+ return rval;
+ }
+
+ case VEC_DELETE_EXPR:
+ case DELETE_EXPR:
+ {
+ tree rval;
+
+ if (flags & LOOKUP_GLOBAL)
+ return build_new_function_call
+ (lookup_name_nonclass (fnname),
+ build_scratch_list (NULL_TREE, arg1), NULL_TREE);
+
+ 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;
+ }
+
+ case CALL_EXPR:
+ return build_object_call (arg1, arg2);
+ }
+
+ /* 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);
+
+ 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;
+
+ fns = lookup_name_nonclass (fnname);
+ /* + Koenig lookup */
+
+ 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);
+
+ if (fns && TREE_CODE (fns) == TREE_LIST)
+ fns = TREE_VALUE (fns);
+ for (; fns; fns = DECL_CHAIN (fns))
+ {
+ if (TREE_CODE (fns) == TEMPLATE_DECL)
+ {
+ templates = scratch_tree_cons (NULL_TREE, fns, templates);
+ candidates
+ = add_template_candidate (candidates, fns, NULL_TREE,
+ arglist, TREE_TYPE (fnname),
+ flags);
+ }
+ else
+ candidates = add_function_candidate (candidates, fns, arglist, flags);
+ }
+
+ if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
+ fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 0);
+ else
+ fns = NULL_TREE;
+
+ if (fns)
+ {
+ tree fn = TREE_VALUE (fns);
+ mem_arglist = scratch_tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
+ for (; fn; fn = DECL_CHAIN (fn))
+ {
+ tree this_arglist;
+
+ 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), LOOKUP_NORMAL);
+ }
+ else
+ candidates = add_function_candidate
+ (candidates, fn, this_arglist, flags);
+
+ if (candidates)
+ candidates->basetype_path = TREE_PURPOSE (fns);
+ }
+ }
+
+ {
+ 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)
+ {
+ args[0] = arg2;
+ args[1] = arg3;
+ args[2] = arg1;
+ }
+ else
+ {
+ args[0] = arg1;
+ args[1] = arg2;
+ args[2] = NULL_TREE;
+ }
+
+ candidates = add_builtin_candidates
+ (candidates, code, code2, fnname, args, flags);
+ }
+
+ if (! any_viable (candidates))
+ {
+ switch (code)
+ {
+ 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;
+ }
+ if (flags & LOOKUP_COMPLAIN)
+ {
+ 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 (cand == 0)
+ {
+ if (flags & LOOKUP_COMPLAIN)
+ {
+ op_error (code, code2, arg1, arg2, arg3, "ambiguous overload");
+ print_z_candidates (candidates);
+ }
+ 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)
+ {
+ 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);
+ }
+
+ if (DECL_FUNCTION_MEMBER_P (cand->fn))
+ enforce_access (cand->basetype_path, cand->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->fn, cand->convs,
+ 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));
+ }
+ }
+
+ /* 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);
+ }
+}
+
+static void
+enforce_access (basetype_path, function)
+ tree basetype_path, function;
+{
+ tree access = compute_access (basetype_path, function);
+
+ if (access == access_private_node)
+ {
+ cp_error_at ("`%+#D' is %s", function,
+ TREE_PRIVATE (function) ? "private"
+ : "from private base class");
+ error ("within this context");
+ }
+ else if (access == access_protected_node)
+ {
+ cp_error_at ("`%+#D' %s", function,
+ TREE_PROTECTED (function) ? "is protected"
+ : "has protected accessibility");
+ error ("within this context");
+ }
+}
+
+/* Perform the conversions in CONVS on the expression EXPR. */
+
+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_CODE (t) == USER_CONV)
+ {
+ expr = convert_like (t, expr);
+ break;
+ }
+ 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);
+ }
+
+ switch (TREE_CODE (convs))
+ {
+ case USER_CONV:
+ {
+ tree fn = TREE_OPERAND (convs, 1);
+ tree args;
+ enforce_access (TREE_OPERAND (convs, 3), fn);
+
+ 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
+ (TREE_OPERAND (convs, 1), TREE_OPERAND (convs, 2),
+ 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);
+ };
+
+ 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:
+ return build_user_type_conversion
+ (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
+ 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);
+ }
+ return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT,
+ LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
+}
+
+static 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;
+}
+
+static tree
+build_over_call (fn, convs, args, flags)
+ tree fn, convs, args;
+ int flags;
+{
+ tree converted_args = NULL_TREE;
+ tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree conv, arg, val;
+ int i = 0;
+ int is_method = 0;
+
+ 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))
+ {
+ 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)))
+ {
+ converted_args = expr_tree_cons
+ (NULL_TREE, TREE_VALUE (arg), converted_args);
+ arg = TREE_CHAIN (arg);
+ parm = TREE_CHAIN (parm);
+ }
+ }
+ /* 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)))
+ {
+ int dv = (TYPE_VOLATILE (TREE_TYPE (parmtype))
+ < TYPE_VOLATILE (TREE_TYPE (argtype)));
+ int dc = (TYPE_READONLY (TREE_TYPE (parmtype))
+ < TYPE_READONLY (TREE_TYPE (argtype)));
+ char *p = (dv && dc ? "const and volatile"
+ : dc ? "const" : dv ? "volatile" : "");
+
+ cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards %s",
+ TREE_TYPE (argtype), fn, p);
+ }
+ converted_args = expr_tree_cons
+ (NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST),
+ converted_args);
+ 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))
+ {
+ 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
+ converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
+ }
+
+ /* Default arguments */
+ for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
+ {
+ tree arg = TREE_PURPOSE (parm);
+
+ if (DECL_TEMPLATE_INFO (fn))
+ /* This came from a template. Instantiate the default arg here,
+ not in tsubst. */
+ arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
+ TREE_VEC_LENGTH (DECL_TI_ARGS (fn)), NULL_TREE);
+ converted_args = expr_tree_cons
+ (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
+ converted_args);
+ }
+
+ /* Ellipsis */
+ for (; arg; arg = TREE_CHAIN (arg))
+ {
+ val = TREE_VALUE (arg);
+
+ if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
+ && (TYPE_PRECISION (TREE_TYPE (val))
+ < TYPE_PRECISION (double_type_node)))
+ /* Convert `float' to `double'. */
+ val = cp_convert (double_type_node, val);
+ else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
+ && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
+ cp_warning ("cannot pass objects of type `%T' through `...'",
+ TREE_TYPE (val));
+ else
+ /* Convert `short' and `char' to full-size `int'. */
+ val = default_conversion (val);
+
+ converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
+ }
+
+ converted_args = nreverse (converted_args);
+
+ /* 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 targ;
+ arg = TREE_VALUE (TREE_CHAIN (converted_args));
+
+ /* 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
+ 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)))
+ {
+ if (! real_lvalue_p (arg))
+ return arg;
+ else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
+ {
+ val = build (VAR_DECL, DECL_CONTEXT (fn));
+ layout_decl (val, 0);
+ val = build (TARGET_EXPR, DECL_CONTEXT (fn), val, arg, 0, 0);
+ TREE_SIDE_EFFECTS (val) = 1;
+ return val;
+ }
+ }
+ 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));
+ val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
+ TREE_SIDE_EFFECTS (val) = 1;
+ return build_unary_op (ADDR_EXPR, val, 0);
+ }
+ }
+ else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
+ && copy_args_p (fn)
+ && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
+ {
+ tree to = stabilize_reference
+ (build_indirect_ref (TREE_VALUE (converted_args), 0));
+ arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
+ val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+ TREE_SIDE_EFFECTS (val) = 1;
+ return val;
+ }
+
+ mark_used (fn);
+
+ if (DECL_CONTEXT (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);
+
+ 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);
+}
+
+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, 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);
+ template_only = 1;
+ }
+
+ /* 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);
+
+ args = resolve_args (args);
+
+ if (args == error_mark_node)
+ return error_mark_node;
+
+ 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);
+
+ /* 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);
+
+ return error_mark_node;
+ }
+
+ /* 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 (basetype_path == NULL_TREE)
+ basetype_path = TYPE_BINFO (basetype);
+
+ if (instance)
+ {
+ instance_ptr = build_this (instance);
+
+ /* 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);
+ }
+
+ pretty_name
+ = (name == ctor_identifier ? constructor_name (basetype) : name);
+
+ fns = lookup_fnfields (basetype_path, name, 1);
+
+ if (fns == error_mark_node)
+ return error_mark_node;
+ if (fns)
+ {
+ tree t = 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);
+ }
+ mem_args = scratch_tree_cons (NULL_TREE, instance_ptr, args);
+ for (; t; t = DECL_CHAIN (t))
+ {
+ tree this_arglist;
+
+ /* 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 (TREE_CODE (t) == TEMPLATE_DECL)
+ {
+ /* A member template. */
+ templates = scratch_tree_cons (NULL_TREE, t, templates);
+ candidates =
+ add_template_candidate (candidates, t, explicit_targs,
+ this_arglist,
+ TREE_TYPE (name),
+ LOOKUP_NORMAL);
+ }
+ else if (! template_only)
+ candidates = add_function_candidate (candidates, t,
+ this_arglist, flags);
+
+ if (candidates)
+ candidates->basetype_path = TREE_PURPOSE (fns);
+ }
+ }
+
+ if (! any_viable (candidates))
+ {
+ /* 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;
+ }
+ candidates = splice_viable (candidates);
+ cand = tourney (candidates);
+
+ if (cand == 0)
+ {
+ cp_error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
+ user_args);
+ print_z_candidates (candidates);
+ return error_mark_node;
+ }
+
+ enforce_access (cand->basetype_path, cand->fn);
+ if (DECL_ABSTRACT_VIRTUAL_P (cand->fn)
+ && instance == current_class_ref
+ && DECL_CONSTRUCTOR_P (current_function_decl)
+ && ! (flags & LOOKUP_NONVIRTUAL)
+ && 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->fn, cand->convs,
+ TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
+ flags);
+}
+
+/* Compare two implicit conversion sequences that differ only in their
+ qualification conversion. Subroutine of compare_ics. */
+
+static int
+compare_qual (ics1, ics2)
+ tree ics1, ics2;
+{
+ tree to1 = TREE_TYPE (ics1);
+ tree to2 = TREE_TYPE (ics2);
+
+ if (TYPE_PTRMEMFUNC_P (to1))
+ to1 = TYPE_PTRMEMFUNC_FN_TYPE (to1);
+ if (TYPE_PTRMEMFUNC_P (to2))
+ to2 = TYPE_PTRMEMFUNC_FN_TYPE (to2);
+
+ to1 = TREE_TYPE (to1);
+ to2 = TREE_TYPE (to2);
+
+ if (TREE_CODE (to1) == OFFSET_TYPE)
+ {
+ to1 = TREE_TYPE (to1);
+ to2 = TREE_TYPE (to2);
+ }
+
+ if (TYPE_READONLY (to1) >= TYPE_READONLY (to2)
+ && TYPE_VOLATILE (to1) > TYPE_VOLATILE (to2))
+ return -1;
+ else if (TYPE_READONLY (to1) > TYPE_READONLY (to2)
+ && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
+ return -1;
+ else if (TYPE_READONLY (to1) <= TYPE_READONLY (to2)
+ && TYPE_VOLATILE (to1) < TYPE_VOLATILE (to2))
+ return 1;
+ else if (TYPE_READONLY (to1) < TYPE_READONLY (to2)
+ && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
+ return 1;
+ return 0;
+}
+
+/* Determine whether standard conversion sequence ICS1 is a proper
+ subsequence of ICS2. We assume that a conversion of the same code
+ between the same types indicates a subsequence. */
+
+static int
+is_subseq (ics1, ics2)
+ tree ics1, ics2;
+{
+ /* Do not consider lvalue transformations here. */
+ if (TREE_CODE (ics2) == RVALUE_CONV
+ || TREE_CODE (ics2) == LVALUE_CONV)
+ return 0;
+
+ for (;; 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 (ics2) == USER_CONV
+ || TREE_CODE (ics2) == AMBIG_CONV
+ || TREE_CODE (ics2) == IDENTITY_CONV)
+ return 0;
+ }
+}
+
+/* Compare two implicit conversion sequences according to the rules set out in
+ [over.ics.rank]. Return values:
+
+ 1: ics1 is better than ics2
+ -1: ics2 is better than ics1
+ 0: ics1 and ics2 are indistinguishable */
+
+static int
+compare_ics (ics1, ics2)
+ tree ics1, ics2;
+{
+ tree main1, main2;
+
+ if (TREE_CODE (ics1) == QUAL_CONV)
+ main1 = TREE_OPERAND (ics1, 0);
+ else
+ main1 = ics1;
+
+ if (TREE_CODE (ics2) == QUAL_CONV)
+ main2 = TREE_OPERAND (ics2, 0);
+ else
+ main2 = ics2;
+
+ /* Conversions for `this' are PTR_CONVs, but we compare them as though
+ they were REF_BINDs. */
+ if (ICS_THIS_FLAG (ics1))
+ {
+ tree t = main1;
+ 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, TREE_TYPE (ics1), t);
+ ICS_STD_RANK (t) = ICS_STD_RANK (main1);
+ main1 = ics1 = t;
+ }
+ if (ICS_THIS_FLAG (ics2))
+ {
+ tree t = main2;
+ 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, TREE_TYPE (ics2), t);
+ ICS_STD_RANK (t) = ICS_STD_RANK (main2);
+ main2 = ics2 = t;
+ }
+
+ if (ICS_RANK (ics1) > ICS_RANK (ics2))
+ return -1;
+ else if (ICS_RANK (ics1) < ICS_RANK (ics2))
+ return 1;
+
+ if (ICS_RANK (ics1) == BAD_RANK)
+ {
+ 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;
+
+ /* else fall through */
+ }
+
+ /* 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. */
+
+ 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;
+ else if (ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
+ return -1;
+ else if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
+ return 1;
+
+ /* else fall through */
+ }
+
+#if 0 /* Handled by ranking */
+ /* 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. */
+#endif
+
+ if (TREE_CODE (main1) != TREE_CODE (main2))
+ {
+ /* ...if S1 is a proper subsequence of S2 */
+ if (is_subseq (main1, main2))
+ return 1;
+ if (is_subseq (main2, main1))
+ return -1;
+ return 0;
+ }
+
+ if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV
+ || TREE_CODE (main1) == REF_BIND || TREE_CODE (main1) == BASE_CONV)
+ {
+ tree to1 = TREE_TYPE (main1);
+ tree from1 = TREE_TYPE (TREE_OPERAND (main1, 0));
+ tree to2 = TREE_TYPE (main2);
+ tree from2 = TREE_TYPE (TREE_OPERAND (main2, 0));
+ int distf, distt;
+
+ /* Standard conversion sequence S1 is a better conversion sequence than
+ standard conversion sequence S2 if...
+
+ S1 and S2 differ only in their qualification conversion and they
+ yield types identical except for cv-qualifiers and S2 adds all the
+ qualifiers that S1 adds (and in the same places) and S2 adds yet
+ more cv-qualifiers than S1, or the similar case with reference
+ binding15). */
+ if (TREE_CODE (main1) == REF_BIND)
+ {
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (to1))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (to2)))
+ return compare_qual (ics1, ics2);
+ }
+ else if (TREE_CODE (main1) != BASE_CONV && from1 == from2 && to1 == to2)
+ return compare_qual (ics1, ics2);
+
+ if (TYPE_PTRMEMFUNC_P (to1))
+ {
+ to1 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to1)));
+ from1 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from1)));
+ }
+ else if (TREE_CODE (main1) != BASE_CONV)
+ {
+ to1 = TREE_TYPE (to1);
+ if (TREE_CODE (main1) != REF_BIND)
+ from1 = TREE_TYPE (from1);
+
+ if (TREE_CODE (to1) == OFFSET_TYPE)
+ {
+ to1 = TYPE_OFFSET_BASETYPE (to1);
+ from1 = TYPE_OFFSET_BASETYPE (from1);
+ }
+ }
+
+ if (TYPE_PTRMEMFUNC_P (to2))
+ {
+ to2 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2)));
+ from2 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from2)));
+ }
+ else if (TREE_CODE (main1) != BASE_CONV)
+ {
+ to2 = TREE_TYPE (to2);
+ if (TREE_CODE (main1) != REF_BIND)
+ from2 = TREE_TYPE (from2);
+
+ if (TREE_CODE (to2) == OFFSET_TYPE)
+ {
+ to2 = TYPE_OFFSET_BASETYPE (to2);
+ from2 = TYPE_OFFSET_BASETYPE (from2);
+ }
+ }
+
+ if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2)))
+ return 0;
+
+ /* The sense of pmem conversions is reversed from that of the other
+ conversions. */
+ if (TREE_CODE (main1) == PMEM_CONV)
+ {
+ tree t = from1; from1 = from2; from2 = t;
+ t = to1; to1 = to2; to2 = t;
+ }
+
+ distf = get_base_distance (from1, from2, 0, 0);
+ if (distf == -1)
+ {
+ distf = -get_base_distance (from2, from1, 0, 0);
+ if (distf == 1)
+ return 0;
+ }
+
+ /* If class B is derived directly or indirectly from class A,
+ conver- sion 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 (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE)
+ {
+ if (distf > 0)
+ return 1;
+ else if (distf < 0)
+ return -1;
+ }
+ else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1)
+ && get_base_distance (to1, from1, 0, 0) != -1)
+ return 1;
+ else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2)
+ && get_base_distance (to2, from2, 0, 0) != -1)
+ return -1;
+
+ if (! (IS_AGGR_TYPE (to1) && IS_AGGR_TYPE (to2)))
+ return 0;
+
+ /* If class B is derived directly or indirectly from class A and class
+ C is derived directly or indirectly from B */
+
+ distt = get_base_distance (to1, to2, 0, 0);
+ if (distt == -1)
+ {
+ distt = -get_base_distance (to2, to1, 0, 0);
+ if (distt == 1)
+ return 0;
+ }
+
+ /* --conversion of C* to B* is better than conversion of C* to A*, */
+ if (distf == 0)
+ {
+ if (distt > 0)
+ return -1;
+ else if (distt < 0)
+ return 1;
+ }
+ /* --conversion of B* to A* is better than conversion of C* to A*, */
+ else if (distt == 0)
+ {
+ if (distf > 0)
+ return 1;
+ else if (distf < 0)
+ return -1;
+ }
+ }
+ else if (TREE_CODE (TREE_TYPE (main1)) == POINTER_TYPE
+ || TYPE_PTRMEMFUNC_P (TREE_TYPE (main1)))
+ {
+ if (TREE_TYPE (main1) == TREE_TYPE (main2))
+ return compare_qual (ics1, ics2);
+
+#if 0 /* This is now handled by making identity better than anything else. */
+ /* existing practice, not WP-endorsed: const char * -> const char *
+ is better than char * -> const char *. (jason 6/29/96) */
+ if (TREE_TYPE (ics1) == TREE_TYPE (ics2))
+ return -compare_qual (main1, main2);
+#endif
+ }
+
+ return 0;
+}
+
+/* The source type for this standard conversion sequence. */
+
+static tree
+source_type (t)
+ tree t;
+{
+ for (;; t = TREE_OPERAND (t, 0))
+ {
+ if (TREE_CODE (t) == USER_CONV
+ || TREE_CODE (t) == AMBIG_CONV
+ || TREE_CODE (t) == IDENTITY_CONV)
+ return TREE_TYPE (t);
+ }
+ my_friendly_abort (1823);
+}
+
+/* Compare two candidates for overloading as described in
+ [over.match.best]. Return values:
+
+ 1: cand1 is better than cand2
+ -1: cand2 is better than cand1
+ 0: cand1 and cand2 are indistinguishable */
+
+static int
+joust (cand1, cand2)
+ struct z_candidate *cand1, *cand2;
+{
+ 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);
+ }
+
+ for (i = 0; i < len; ++i)
+ {
+ 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)
+ {
+#if 0 /* move this warning to tourney. */
+ 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)))
+ {
+ tree type = TREE_TYPE (TREE_OPERAND (t1, 0));
+ tree type1, type2;
+ if (comp > 0)
+ type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2);
+ else
+ type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1);
+
+ cp_warning ("passing `%T' chooses `%T' over `%T'",
+ type, type1, type2);
+ cp_warning (" in call to `%D'", DECL_NAME (cand1->fn));
+ }
+#endif
+
+ if (winner && comp != winner)
+ {
+ winner = 0;
+ goto tweak;
+ }
+ winner = comp;
+ }
+ }
+
+#if 0 /* move this warning to tourney. */
+ /* warn about confusing overload resolution */
+ if (winner && cand1->second_conv
+ && ! DECL_CONSTRUCTOR_P (cand1->fn)
+ && ! DECL_CONSTRUCTOR_P (cand2->fn))
+ {
+ int comp = compare_ics (cand1->second_conv, cand2->second_conv);
+ if (comp && comp != winner)
+ {
+ struct z_candidate *w, *l;
+ if (winner == 1)
+ w = cand1, l = cand2;
+ else
+ w = cand2, l = cand1;
+ cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
+ cp_warning (" for conversion from `%T' to `%T'",
+ TREE_TYPE (source_type (TREE_VEC_ELT (w->convs, 0))),
+ TREE_TYPE (w->second_conv));
+ cp_warning (" because conversion sequence for `this' argument is better");
+ }
+ }
+#endif
+
+ if (winner)
+ return winner;
+
+ /* or, if not that,
+ F1 is a non-template function and F2 is a template function */
+
+ 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));
+
+ /* 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;
+
+ /* 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 (comptypes (t1, t2, 1))
+ {
+ 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;
+ }
+ }
+ }
+
+tweak:
+
+ /* Extension: If the worst conversion for one candidate is worse than the
+ worst conversion for the other, take the first. */
+ if (! winner && ! pedantic)
+ {
+ int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK;
+
+ for (i = 0; i < len; ++i)
+ {
+ 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;
+
+ /* 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);
+ if (fate == 1)
+ challenger = challenger->next;
+ else
+ {
+ if (fate == 0)
+ {
+ champ = challenger->next;
+ if (champ == 0)
+ return 0;
+ }
+ else
+ champ = challenger;
+
+ challenger = champ->next;
+ }
+ }
+
+ /* Make sure the champ is better than all the candidates it hasn't yet
+ been compared to. This may do one more comparison than necessary. Oh
+ well. */
+
+ for (challenger = candidates; challenger != champ;
+ challenger = challenger->next)
+ {
+ fate = joust (champ, challenger);
+ if (fate != 1)
+ return 0;
+ }
+
+ return champ;
+}
+
+int
+can_convert (to, from)
+ tree to, from;
+{
+ if (flag_ansi_overloading)
+ {
+ tree t = implicit_conversion (to, from, NULL_TREE, LOOKUP_NORMAL);
+ return (t && ! ICS_BAD_FLAG (t));
+ }
+ else
+ {
+ struct harshness_code h;
+ h = convert_harshness (to, from, NULL_TREE);
+ return (h.code < USER_CODE) && (h.distance >= 0);
+ }
+}
+
+int
+can_convert_arg (to, from, arg)
+ tree to, from, arg;
+{
+ if (flag_ansi_overloading)
+ {
+ tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
+ return (t && ! ICS_BAD_FLAG (t));
+ }
+ else
+ {
+ struct harshness_code h;
+ h = convert_harshness (to, from, arg);
+ return (h.code < USER_CODE) && (h.distance >= 0);
+ }
}
diff --git a/gnu/usr.bin/gcc/cp/class.c b/gnu/usr.bin/gcc/cp/class.c
index e2893044f75..70db2ff547f 100644
--- a/gnu/usr.bin/gcc/cp/class.c
+++ b/gnu/usr.bin/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,7 +20,7 @@ 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 "tree.h"
@@ -37,7 +37,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 +72,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,8 +82,49 @@ 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 int typecode_p PROTO((tree, enum tree_code));
+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 tree add_virtual_function PROTO((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));
+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 *, tree));
/* Way of stacking language names. */
tree *current_lang_base, *current_lang_stack;
@@ -91,15 +134,23 @@ int current_lang_stacksize;
tree lang_name_c, lang_name_cplusplus;
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_private_virtual_node; /* 6 */
+
/* 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 +159,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 +171,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 +197,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 +228,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 +238,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 +269,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 +278,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 +294,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 +341,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 +374,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.
@@ -350,26 +417,24 @@ 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.
- */
+ 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,9 +449,9 @@ 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
@@ -416,22 +481,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 +543,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 +605,78 @@ 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;
+{
+ 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));
+}
+
+/* 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 (size_zero_node, voff);
+
+ /* The second slot is for the tdesc pointer when thunks are used. */
+ TREE_VALUE (TREE_CHAIN (virtuals))
+ = build_vtable_entry (size_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 +686,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 = size_binop (MINUS_EXPR, size_zero_node, offset);
+ set_rtti_entry (virtuals, offset, type);
}
else
{
@@ -558,6 +716,7 @@ build_vtable (binfo, type)
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 +737,97 @@ 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<int>, 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));
+
+ /* We better not run out of stuff to make it unique. */
+ my_friendly_assert (for_type != basetype, 369);
+
+ 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 +841,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),
+ size_binop (MINUS_EXPR, signed_size_zero_node, offset),
for_type);
#ifdef GATHER_STATISTICS
@@ -733,10 +875,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 +901,7 @@ get_vtable_entry (virtuals, base_fndecl)
}
return virtuals;
}
+#endif
/* Put new entry ENTRY into virtual function table initializer
VIRTUALS.
@@ -776,7 +921,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 +929,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,12 +952,13 @@ 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;
int *has_virtual;
tree fndecl;
- tree t; /* Structure type. */
+ tree t; /* Structure type. */
{
/* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely
convert to void *. Make such a conversion here. */
@@ -835,11 +982,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 +995,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);
@@ -892,6 +1036,7 @@ 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;
@@ -905,7 +1050,7 @@ add_method (type, fields, method)
decl = copy_node (method);
if (DECL_RTL (decl) == 0
&& (!processing_template_decl
- || !uses_template_parms (decl)))
+ || !uses_template_parms (decl)))
{
make_function_rtl (decl);
DECL_RTL (method) = DECL_RTL (decl);
@@ -923,8 +1068,16 @@ add_method (type, fields, method)
tree method_vec = make_node (TREE_VEC);
if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))
{
- 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 (decl)))
+ TREE_VEC_ELT (method_vec, 1) = decl;
+ else
+ TREE_VEC_ELT (method_vec, 0) = decl;
+ TREE_VEC_LENGTH (method_vec) = 2;
}
else
{
@@ -932,9 +1085,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) = decl;
+ TREE_VEC_LENGTH (method_vec) = 3;
obstack_finish (current_obstack);
}
CLASSTYPE_METHOD_VEC (type) = method_vec;
@@ -948,11 +1101,12 @@ add_method (type, fields, method)
METHOD_VEC always has a slot for such entries. */
if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))
{
- /* TREE_VEC_ELT (method_vec, 0) = decl; */
- if (decl != TREE_VEC_ELT (method_vec, 0))
+ int idx = !!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl));
+ /* TREE_VEC_ELT (method_vec, idx) = decl; */
+ if (decl != TREE_VEC_ELT (method_vec, idx))
{
- DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, 0);
- TREE_VEC_ELT (method_vec, 0) = decl;
+ DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, idx);
+ TREE_VEC_ELT (method_vec, idx) = decl;
}
}
else
@@ -1030,6 +1184,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;
@@ -1076,11 +1231,23 @@ delete_duplicate_fields_1 (field, fields)
x);
else if (TREE_CODE (field) == TYPE_DECL
&& TREE_CODE (x) == TYPE_DECL)
- cp_error_at ("duplicate nested type `%D'", x);
+ {
+ if (TREE_TYPE (field) == TREE_TYPE (x))
+ continue;
+ 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);
+ {
+ /* 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)
@@ -1105,14 +1272,15 @@ delete_duplicate_fields (fields)
/* Change the access of FDECL to ACCESS in T.
Return 1 if change was legit, otherwise return 0. */
+
static int
alter_access (t, fdecl, access)
tree t;
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 && TREE_VALUE (elem) != access)
{
if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)
{
@@ -1124,66 +1292,29 @@ alter_access (t, fdecl, access)
}
else if (TREE_PRIVATE (fdecl))
{
- if (access != access_private)
+ if (access != access_private_node)
cp_error_at ("cannot make private `%D' non-private", fdecl);
goto alter;
}
else if (TREE_PROTECTED (fdecl))
{
- if (access != access_protected)
+ if (access != access_protected_node)
cp_error_at ("cannot make protected `%D' non-protected", fdecl);
goto alter;
}
/* 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)
+ else if (access != access_public_node)
cp_error_at ("cannot reduce access of public member `%D'", fdecl);
else if (elem == NULL_TREE)
{
alter:
- DECL_ACCESS (fdecl) = tree_cons (t, (tree)access,
- DECL_ACCESS (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));
-}
-
-/* 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);
-}
-
/* If FOR_TYPE needs to reinitialize virtual function table pointers
for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
Returns BASE_INIT_LIST appropriately modified. */
@@ -1202,7 +1333,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);
@@ -1350,12 +1481,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.
@@ -1409,13 +1538,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 +1556,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);
@@ -1449,14 +1568,6 @@ finish_base_struct (t, b, t_binfo)
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);
@@ -1491,9 +1602,10 @@ finish_base_struct (t, b, t_binfo)
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))
@@ -1593,8 +1705,6 @@ finish_base_struct (t, b, t_binfo)
{
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;
}
}
{
@@ -1608,8 +1718,6 @@ finish_base_struct (t, b, t_binfo)
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,6 +1738,11 @@ finish_base_struct (t, b, t_binfo)
if (b->vfield == 0)
/* If all virtual functions come only from virtual baseclasses. */
return -1;
+
+ /* 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;
}
@@ -1645,13 +1758,13 @@ typecode_p (type, code)
/* 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 +1783,8 @@ 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);
variants = TYPE_NEXT_VARIANT (variants);
}
@@ -1688,7 +1803,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);
@@ -1720,12 +1835,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 +1854,34 @@ 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 (*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))
+ {
+ tree *p;
+ for (p = testp; *p; )
+ p = &DECL_CHAIN (*p);
+ *p = fndecl;
}
else
{
- obstack_ptr_grow (&class_obstack, fn);
+ obstack_ptr_grow (&class_obstack, fndecl);
*method_vec_ptr = (tree)obstack_base (&class_obstack);
}
}
@@ -1812,36 +1909,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 +1948,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,9 +1966,18 @@ 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. */
+ DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 1);
+ TREE_VEC_ELT (method_vec, 1) = fn_fields;
+ }
+ else
+ {
+ /* Constructors go in slot 0. */
+ DECL_CHAIN (fn_fields) = TREE_VEC_ELT (method_vec, 0);
+ TREE_VEC_ELT (method_vec, 0) = fn_fields;
+ }
}
else if (IDENTIFIER_TYPENAME_P (fn_name))
{
@@ -1887,26 +1992,15 @@ finish_struct_methods (t, fn_fields, nonprivate_method)
grow_method (fn_fields, &method_vec);
}
- else
- {
- lastp = fn_fields;
- continue;
- }
-
- TREE_CHAIN (lastp) = TREE_CHAIN (fn_fields);
- TREE_CHAIN (fn_fields) = NULL_TREE;
}
- 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 +2016,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 +2025,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,57 +2035,40 @@ 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)));
@@ -2005,46 +2081,57 @@ 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))
+ /* Now, figure out what any member template specializations were
+ specializing. */
+ for (i = 0; i < TREE_VEC_LENGTH (method_vec); ++i)
+ {
+ tree fn;
+ for (fn = TREE_VEC_ELT (method_vec, i);
+ fn != NULL_TREE;
+ fn = DECL_CHAIN (fn))
+ if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
- /* Let's avoid being circular about this. */
- if (x == DECL_CHAIN (x))
- break;
- TREE_CHAIN (x) = DECL_CHAIN (x);
- x = DECL_CHAIN (x);
+ tree f;
+ tree spec_args;
+
+ /* If there is a template, and t uses template parms, we
+ are dealing with a specialization of a member
+ template in a template class, and we must grab the
+ template, rather than the function. */
+ if (DECL_TI_TEMPLATE (fn) && uses_template_parms (t))
+ f = DECL_TI_TEMPLATE (fn);
+ else
+ f = fn;
+
+ /* We want the specialization arguments, which will be the
+ innermost ones. */
+ if (DECL_TI_ARGS (f)
+ && TREE_CODE (DECL_TI_ARGS (f)) == TREE_VEC)
+ spec_args
+ = TREE_VEC_ELT (DECL_TI_ARGS (f), 0);
+ else
+ spec_args = DECL_TI_ARGS (f);
+
+ check_explicit_specialization
+ (lookup_template_function (DECL_NAME (f), spec_args),
+ f, 0, 1);
+
+ /* Now, the assembler name will be correct for fn, so we
+ make its RTL. */
+ DECL_RTL (f) = 0;
+ make_decl_rtl (f, NULL_PTR, 1);
+ if (f != fn)
+ {
+ DECL_RTL (fn) = 0;
+ make_decl_rtl (fn, NULL_PTR, 1);
+ }
}
- 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 +2145,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);
+ unchain = DECL_CHAIN (unchain);
}
}
}
@@ -2106,11 +2192,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 +2226,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 +2238,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 +2315,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 +2341,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 +2349,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 +2378,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 */
@@ -2369,11 +2459,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 +2479,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;
@@ -2469,10 +2562,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 +2575,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 +2587,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 +2607,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 +2623,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 +2631,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 +2656,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 +2666,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 +2681,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,7 +2739,7 @@ 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. */
+ /* Make sure we search for it later. */
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
@@ -2648,7 +2747,7 @@ override_one_vtable (binfo, old, t)
TREE_CONSTANT (vfn) = 1;
/* We can use integer_zero_node, as we will will core dump
- if this is used anyway. */
+ if this is used anyway. */
TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, vfn);
}
}
@@ -2656,7 +2755,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 +2766,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 +2787,250 @@ 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 fndecl = TREE_VEC_ELT (method_vec, i);
+
+ tree base_fndecls = NULL_TREE;
+ tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
+ int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
+ 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);
+ }
+
+ if (TREE_CHAIN (fndecl)
+ && DECL_NAME (TREE_CHAIN (fndecl)) == DECL_NAME (fndecl))
+ fndecl = TREE_CHAIN (fndecl);
+ 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);
+
+ if (TREE_CHAIN (fndecl)
+ && DECL_NAME (TREE_CHAIN (fndecl)) == DECL_NAME (fndecl))
+ fndecl = TREE_CHAIN (fndecl);
+ 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,14 +3100,11 @@ 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;
@@ -2777,8 +3114,6 @@ finish_struct_1 (t, warn_anon)
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
@@ -2793,6 +3128,8 @@ finish_struct_1 (t, warn_anon)
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,
@@ -2863,19 +3194,17 @@ finish_struct_1 (t, warn_anon)
fields = chainon (vf, fields);
first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo);
- /* Remember where we got our vfield from */
+ /* 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;
}
@@ -2886,13 +3215,11 @@ finish_struct_1 (t, warn_anon)
max_has_virtual = has_virtual;
vfield = NULL_TREE;
vfields = NULL_TREE;
+ CLASSTYPE_RTTI (t) = NULL_TREE;
last_x = 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
@@ -2920,7 +3247,7 @@ finish_struct_1 (t, warn_anon)
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,6 +3266,10 @@ 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)
@@ -2948,8 +3279,11 @@ finish_struct_1 (t, warn_anon)
&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
}
}
@@ -2957,20 +3291,44 @@ finish_struct_1 (t, warn_anon)
{
GNU_xref_member (current_class_name, x);
+ if (TREE_CODE (x) == FIELD_DECL)
+ {
+ DECL_PACKED (x) |= TYPE_PACKED (t);
+ empty = 0;
+ }
+
/* Handle access declarations. */
- if (DECL_NAME (x) && TREE_CODE (DECL_NAME (x)) == SCOPE_REF)
+ if (TREE_CODE (x) == USING_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;
+ tree ctype = DECL_INITIAL (x);
+ tree sname = DECL_NAME (x);
+ tree access
+ = TREE_PRIVATE (x) ? access_private_node
+ : TREE_PROTECTED (x) ? access_protected_node
+ : access_public_node;
+ tree fdecl, binfo;
if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x);
else
fields = TREE_CHAIN (x);
- access_decls = tree_cons ((tree) access, fdecl, access_decls);
+ binfo = binfo_or_else (ctype, t);
+ if (! binfo)
+ continue;
+
+ if (sname == constructor_name (ctype)
+ || sname == constructor_name_full (ctype))
+ cp_error_at ("using-declaration for constructor", x);
+
+ fdecl = lookup_field (binfo, sname, 0, 0);
+ if (! fdecl)
+ fdecl = lookup_fnfields (binfo, sname, 0);
+
+ if (fdecl)
+ access_decls = scratch_tree_cons (access, fdecl, access_decls);
+ else
+ cp_error_at ("no members matching `%D' in `%#T'", x, ctype);
continue;
}
@@ -2980,7 +3338,7 @@ finish_struct_1 (t, warn_anon)
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 +3367,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 +3407,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 +3419,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 +3433,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 +3479,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;
+
+ /* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
+ STRIP_NOPS (w);
- if (width < 0)
+ /* 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 (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);
@@ -3154,23 +3532,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 +3550,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 +3560,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)
@@ -3233,18 +3596,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,23 +3649,19 @@ 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);
@@ -3318,17 +3669,30 @@ finish_struct_1 (t, warn_anon)
}
}
+ /* 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 +3710,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))
{
/* ARM 12.18: You get either X(X&) or X(const X&), but
not both. --Chip */
@@ -3362,8 +3725,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))
{
tree default_fn = cons_up_default_function (t, name,
5 + no_const_asn_ref);
@@ -3373,11 +3735,12 @@ 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;
@@ -3415,8 +3778,8 @@ finish_struct_1 (t, warn_anon)
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 access = TREE_PURPOSE (access_decls);
+ int i = 2;
tree tmp;
if (TREE_CODE (fdecl) == TREE_LIST)
@@ -3477,23 +3840,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 +3867,8 @@ finish_struct_1 (t, warn_anon)
}
else
fields = vfield;
+#endif
+ empty = 0;
vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
}
@@ -3534,7 +3902,11 @@ 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)
{
@@ -3551,10 +3923,6 @@ 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)
{
@@ -3567,77 +3935,34 @@ finish_struct_1 (t, warn_anon)
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. */
+ /* Don't re-use old size. */
DECL_SIZE (base_layout_decl) = NULL_TREE;
}
+ else 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) = TYPE_FIELDS (t);
+ TYPE_FIELDS (t) = decl;
+ }
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);
- }
+ finish_struct_anon (t);
- DECL_FIELD_BITPOS (field) = integer_zero_node;
- }
- }
- }
-
- if (n_baseclasses)
+ if (n_baseclasses || empty)
TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t));
- /* C++: do not let empty structures exist. */
- if (integer_zerop (TYPE_SIZE (t)))
- TYPE_SIZE (t) = TYPE_SIZE (char_type_node);
-
/* 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 (TYPE_USES_VIRTUAL_BASECLASSES (t))
@@ -3648,17 +3973,6 @@ finish_struct_1 (t, warn_anon)
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 +3995,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 +4037,52 @@ 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, size_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 +4192,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 +4211,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 +4218,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 +4237,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 +4251,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 +4270,13 @@ 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_CONTEXT (TYPE_MAIN_DECL (t))
+ && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (TYPE_MAIN_DECL (t)))) == '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 +4284,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 +4295,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 +4317,16 @@ 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 name = TYPE_NAME (t);
tree x, last_x = NULL_TREE;
- enum access_type access;
+ tree access;
+ tree dummy = NULL_TREE;
if (TREE_CODE (name) == TYPE_DECL)
{
@@ -4071,34 +4348,41 @@ 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))
{
- TREE_PRIVATE (x) = access == access_private;
- TREE_PROTECTED (x) = access == access_protected;
+ TREE_PRIVATE (x) = access == access_private_node;
+ TREE_PROTECTED (x) = access == access_protected_node;
/* 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) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
{
tree name = DECL_NAME (x);
@@ -4126,28 +4410,20 @@ finish_struct (t, list_of_fieldlists, warn_anon)
}
}
- 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. */
+ /* 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 +4442,68 @@ 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_MAIN_DECL (TREE_VALUE (x));
+
+ TREE_NONLOCAL_FLAG (TREE_VALUE (x)) = 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 (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
- return finish_struct_1 (t, warn_anon);
+ t = finish_struct_1 (t, warn_anon);
+
+ TYPE_BEING_DEFINED (t) = 0;
+
+ if (current_class_type)
+ popclass (0);
+ else
+ error ("trying to finish struct, but kicked out due to previous parse errors.");
+
+ return t;
}
/* Return non-zero if the effective type of INSTANCE is static.
@@ -4185,6 +4512,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;
@@ -4249,10 +4577,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 +4586,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 +4597,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 +4629,15 @@ 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_private_virtual_node = build_int_2 (6, 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);
@@ -4359,9 +4690,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 +4713,11 @@ pushclass (type, modify)
pushlevel_class ();
+#if 0
+ if (CLASSTYPE_TEMPLATE_INFO (type))
+ overload_template_name (type);
+#endif
+
if (modify)
{
tree tags;
@@ -4394,15 +4730,11 @@ 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)
{
build_mi_matrix (type);
push_class_decls (type);
free_mi_matrix ();
- if (current_class_depth == 1)
- previous_class_type = type;
}
else
{
@@ -4423,9 +4755,6 @@ 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;
@@ -4436,22 +4765,17 @@ pushclass (type, modify)
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 +4806,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 +4816,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;
@@ -4520,10 +4842,11 @@ push_nested_class (type, modify)
{
tree context;
- if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type))
+ if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == TEMPLATE_TYPE_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 +4859,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,9 +4876,9 @@ 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;
}
@@ -4572,44 +4895,39 @@ 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)
strict_prototype = strict_prototypes_lang_cplusplus;
else if (current_lang_name == lang_name_c)
strict_prototype = strict_prototypes_lang_c;
}
-
-int
-root_lang_context_p ()
-{
- return current_lang_stack == current_lang_base;
-}
/* 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;
+
if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
{
if (complain)
@@ -4620,6 +4938,8 @@ instantiate_type (lhstype, rhs, complain)
if (TREE_TYPE (rhs) != NULL_TREE && ! (type_unknown_p (rhs)))
return rhs;
+ 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
arithmetic operation which is not supported on pointers
@@ -4637,14 +4957,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,6 +4995,7 @@ instantiate_type (lhstype, rhs, complain)
return error_mark_node;
return build_vfn_ref (&base_ptr, base, DECL_VINDEX (function));
}
+ mark_used (function);
return function;
}
@@ -4687,6 +5012,7 @@ instantiate_type (lhstype, rhs, complain)
if (field)
{
TREE_OPERAND (rhs, 1) = field;
+ mark_used (field);
return rhs;
}
@@ -4716,17 +5042,18 @@ instantiate_type (lhstype, rhs, complain)
return rhs;
}
+ case TEMPLATE_ID_EXPR:
+ {
+ explicit_targs = TREE_OPERAND (rhs, 1);
+ rhs = TREE_OPERAND (rhs, 0);
+ }
+ /* fall through */
+
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
-
/* First look for an exact match. Search either overloaded
functions or member functions. May have to undo what
`default_conversion' might do to lhstype. */
@@ -4756,11 +5083,17 @@ instantiate_type (lhstype, rhs, complain)
if (globals > 0)
{
elem = get_first_fn (rhs);
- while (elem)
- if (! comptypes (lhstype, TREE_TYPE (elem), 1))
- elem = DECL_CHAIN (elem);
- else
- return elem;
+ /* If there are explicit_targs, only a template function
+ can match. */
+ if (explicit_targs == NULL_TREE)
+ while (elem)
+ if (! comptypes (lhstype, TREE_TYPE (elem), 1))
+ elem = DECL_CHAIN (elem);
+ else
+ {
+ mark_used (elem);
+ return elem;
+ }
/* No exact match found, look for a compatible template. */
{
@@ -4768,12 +5101,14 @@ instantiate_type (lhstype, rhs, complain)
for (elem = get_first_fn (rhs); elem; elem = DECL_CHAIN (elem))
if (TREE_CODE (elem) == TEMPLATE_DECL)
{
- int n = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (elem));
- tree *t = (tree *) alloca (sizeof (tree) * n);
+ int n = DECL_NTPARMS (elem);
+ tree t = make_scratch_vec (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);
+ i = type_unification
+ (DECL_INNERMOST_TEMPLATE_PARMS (elem),
+ &TREE_VEC_ELT (t, 0), TYPE_ARG_TYPES (TREE_TYPE (elem)),
+ TYPE_ARG_TYPES (lhstype), explicit_targs, &d,
+ 1, 1);
if (i == 0)
{
if (save_elem)
@@ -4789,40 +5124,53 @@ instantiate_type (lhstype, rhs, complain)
}
}
if (save_elem)
- return 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)
+ /* If there are explicit_targs, only a template function
+ can match. */
+ if (explicit_targs == NULL_TREE)
{
- tree save_elem = elem;
- elem = DECL_CHAIN (elem);
+ /* No match found, look for a compatible function. */
+ elem = get_first_fn (rhs);
while (elem && comp_target_types (lhstype,
- TREE_TYPE (elem), 0) <= 0)
+ TREE_TYPE (elem), 1) <= 0)
elem = DECL_CHAIN (elem);
if (elem)
{
- if (complain)
+ 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)
{
- 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);
+ if (complain)
+ {
+ cp_error
+ ("cannot resolve overload to target type `%#T'",
+ lhstype);
+ cp_error_at (" ambiguity between `%#D'",
+ save_elem);
+ cp_error_at (" and `%#D', at least", elem);
+ }
+ return error_mark_node;
}
- return error_mark_node;
+ mark_used (save_elem);
+ return 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));
+ cp_error
+ (" because no suitable overload of function `%D' exists",
+ TREE_PURPOSE (rhs));
}
return error_mark_node;
}
@@ -4848,7 +5196,10 @@ instantiate_type (lhstype, rhs, complain)
elem = TREE_VALUE (baselink);
while (elem)
if (comptypes (lhstype, TREE_TYPE (elem), 1))
- return elem;
+ {
+ mark_used (elem);
+ return elem;
+ }
else
elem = DECL_CHAIN (elem);
}
@@ -4874,6 +5225,7 @@ instantiate_type (lhstype, rhs, 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));
@@ -5006,15 +5358,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 +5393,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 +5407,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 +5435,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 +5443,24 @@ 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;
+}
diff --git a/gnu/usr.bin/gcc/cp/class.h b/gnu/usr.bin/gcc/cp/class.h
index f2c21735cc4..12e45f78415 100644
--- a/gnu/usr.bin/gcc/cp/class.h
+++ b/gnu/usr.bin/gcc/cp/class.h
@@ -80,7 +80,7 @@ struct candidate
int h_len; /* The length of the harshness vector. */
tree function; /* A FUNCTION_DECL */
- tree basetypes; /* The path to function. */
+ tree basetypes; /* The path to function. */
tree arg; /* first parm to function. */
/* Indexed by argument number, encodes evil, user, d_to_b, and easy
@@ -103,7 +103,7 @@ struct candidate
-5 if contravariance violation. */
} u;
};
-int rank_for_overload ();
+int rank_for_overload PROTO ((struct candidate *, struct candidate *));
/* Variables shared between class.c and call.c. */
diff --git a/gnu/usr.bin/gcc/cp/config-lang.in b/gnu/usr.bin/gcc/cp/config-lang.in
index 7a9a5c558c7..4ba5cdffe32 100644
--- a/gnu/usr.bin/gcc/cp/config-lang.in
+++ b/gnu/usr.bin/gcc/cp/config-lang.in
@@ -33,3 +33,9 @@ compilers="cc1plus\$(exeext)"
stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
diff_excludes="-x cp/parse.c -x cp/parse.h"
+
+headers='$(CXX_EXTRA_HEADERS)'
+
+lib2funcs=cplib2.txt
+
+outputs=cp/Makefile
diff --git a/gnu/usr.bin/gcc/cp/cp-tree.h b/gnu/usr.bin/gcc/cp/cp-tree.h
index fe9855d8ca0..06a8c647103 100644
--- a/gnu/usr.bin/gcc/cp/cp-tree.h
+++ b/gnu/usr.bin/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,17 +22,7 @@ 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"
/* Language-dependent contents of an identifier. */
@@ -51,6 +41,12 @@ struct lang_id2
tree type_desc, as_list, error_locus;
};
+typedef struct
+{
+ tree t;
+ int new_type_flag;
+} flagged_type_tree;
+
/* To identify to the debug emitters if it should pay attention to the
flag `-Wtemplate-debugging'. */
#define HAVE_TEMPLATES 1
@@ -139,6 +135,12 @@ 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;
@@ -202,10 +204,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 +217,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 +230,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'. */
@@ -266,7 +279,7 @@ extern int write_virtuals;
/* True for more efficient but incompatible (not 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,10 +298,10 @@ extern int flag_elide_constructors;
extern int flag_ansi;
-/* Nonzero means recognize and handle ansi-style exception handling
- constructs. */
+/* Nonzero means do argument matching for overloading according to the
+ ANSI rules, rather than what g++ used to believe to be correct. */
-extern int flag_handle_exceptions;
+extern int flag_ansi_overloading;
/* Nonzero means recognize and handle signature language constructs. */
@@ -299,23 +312,23 @@ 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;
-extern int flag_cadillac;
/* 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 };
/* Macros to make error reporting functions' lives easier. */
@@ -327,27 +340,25 @@ 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. */
-
#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 +374,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)
@@ -427,9 +429,9 @@ struct lang_type
unsigned marked4 : 1;
unsigned marked5 : 1;
unsigned marked6 : 1;
+ unsigned debug_requested : 1;
unsigned use_template : 2;
- unsigned debug_requested : 1;
unsigned has_method_call_overloaded : 1;
unsigned private_attr : 1;
unsigned got_semicolon : 1;
@@ -438,16 +440,14 @@ struct lang_type
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;
unsigned has_real_assignment : 1;
unsigned has_real_assign_ref : 1;
-
unsigned has_const_init_ref : 1;
unsigned has_complex_init_ref : 1;
+
unsigned has_complex_assign_ref : 1;
unsigned has_abstract_assign_ref : 1;
unsigned non_aggregate : 1;
@@ -455,7 +455,7 @@ 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 dummy : 21;
unsigned n_vancestors : 16;
} type_flags;
@@ -475,7 +475,7 @@ struct lang_type
union tree_node *tags;
char *memoized_table_entry;
- char *search_slot;
+ union tree_node *search_slot;
#ifdef ONLY_INT_FIELDS
unsigned int mode : 8;
@@ -507,6 +507,8 @@ struct lang_type
union tree_node *signature_pointer_to;
union tree_node *signature_reference_to;
+ union tree_node *template_info;
+
int linenum;
};
@@ -599,12 +601,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 +632,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 +652,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
@@ -701,7 +693,7 @@ struct lang_type
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. */
@@ -838,9 +830,6 @@ 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. */
@@ -923,8 +912,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,25 +940,24 @@ 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 dummy : 5;
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;
};
@@ -977,6 +965,14 @@ struct lang_decl
#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)
@@ -997,7 +993,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)
@@ -1060,19 +1056,16 @@ struct lang_decl
? 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. */
+ with the same name is found. We now use TREE_CHAIN to
+ walk through the methods in order of declaration. */
#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)
-
/* 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 +1076,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,8 +1089,27 @@ 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)
+/* 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)
+#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 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)
/* Nonzero in INT_CST means that this int is negative by dint of
using a twos-complement negated operand. */
@@ -1112,15 +1124,17 @@ struct lang_decl
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.
@@ -1147,7 +1161,7 @@ struct lang_decl
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
@@ -1207,10 +1221,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))
@@ -1250,21 +1266,36 @@ 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. */
+ 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. */
@@ -1299,22 +1330,10 @@ 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. */
#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 +1344,35 @@ 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)
#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)
+
+#define DECL_FUNCTION_TEMPLATE_P(NODE) \
+ (TREE_CODE (NODE) == TEMPLATE_DECL \
+ && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
+
+#define PRIMARY_TEMPLATE_P(NODE) \
+ (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (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, int);
- 3=explicit template instantiation, e.g. template int min<int> (int, int);
- */
+ 3=explicit template instantiation, e.g. template int min<int> (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 +1400,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 +1417,8 @@ 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))
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
@@ -1401,6 +1426,13 @@ 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_LENGTH(NODE) IDENTIFIER_LENGTH(NODE)
+#define DEFARG_POINTER(NODE) IDENTIFIER_POINTER(NODE)
+
+#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
+ define_function (NAME, TYPE, CODE, (void (*) PROTO((tree)))pushdecl, LIBNAME)
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types { record_type, class_type, union_type, enum_type,
signature_type };
@@ -1443,13 +1475,13 @@ 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 *));
+extern char *get_directive_line PROTO((FILE *));
/* 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));
@@ -1461,7 +1493,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,73 +1504,63 @@ 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;
+
+extern tree current_template_parms;
+extern HOST_WIDE_INT processing_template_decl;
/* 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;
+
/* 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 tree current_lang_name, lang_name_cplusplus, lang_name_c;
@@ -1544,13 +1568,10 @@ extern tree current_lang_name, lang_name_cplusplus, lang_name_c;
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 +1692,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"
@@ -1731,18 +1754,14 @@ extern int current_function_parms_stored;
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_private_virtual_node; /* 6 */
/* Things for handling inline functions. */
@@ -1757,7 +1776,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 +1802,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,18 +1823,18 @@ 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 if we're done parsing and into end-of-file activities. */
-extern int current_function_obstack_usage;
+extern int at_eof;
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
-extern tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
-
/* The following two can be derived from the previous one */
extern tree current_class_name; /* IDENTIFIER_NODE: name of current class */
extern tree current_class_type; /* _TYPE: the type of the current class */
@@ -1837,32 +1851,36 @@ 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. */
#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)
/* These flags are used by the conversion code.
CONV_IMPLICIT : Perform implicit conversions (standard and user-defined).
@@ -1870,7 +1888,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 +1896,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 \
@@ -1906,15 +1923,14 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#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)
+#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TYPE_FIELDS (NODE))
+#define TEMPLATE_TYPE_LEVEL(NODE) TREE_INT_CST_HIGH (TYPE_FIELDS (NODE))
+#define TEMPLATE_TYPE_SET_INFO(NODE,I,L) \
+ (TYPE_FIELDS (NODE) = build_int_2 (I, L))
+#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_LOW(NODE))
+#define TEMPLATE_CONST_LEVEL(NODE) (TREE_INT_CST_HIGH(NODE))
+#define TEMPLATE_CONST_SET_INFO(NODE,I,L) \
+ (TEMPLATE_CONST_IDX (NODE) = I, TEMPLATE_CONST_LEVEL (NODE) = L)
/* in lex.c */
/* Indexed by TREE_CODE, these tables give C-looking names to
@@ -1922,36 +1938,38 @@ 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 struct candidate *ansi_c_filler;
+extern int get_arglist_len_in_bytes PROTO((tree));
extern int rank_for_overload PROTO((struct candidate *, struct candidate *));
extern void compute_conversion_costs PROTO((tree, tree, struct candidate *, int));
-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 tree build_overload_call PROTO((tree, tree, int));
+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, tree));
+extern tree build_new_op PROTO((enum tree_code, int, tree, tree, tree));
+extern int can_convert PROTO((tree, tree));
+extern int can_convert_arg PROTO((tree, tree, 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 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 void pushclass PROTO((tree, int));
@@ -1960,21 +1978,22 @@ 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));
@@ -1982,103 +2001,130 @@ extern int build_default_binary_type_conversion PROTO((enum tree_code, tree *, t
extern tree type_promotes_to PROTO((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 void set_identifier_type_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));
+#if 0
+extern void pushdecl_nonclass_level PROTO((tree));
+#endif
+extern void push_class_level_binding PROTO((tree, tree));
extern int overloaded_globals_p PROTO((tree));
-extern tree push_overloaded_decl PROTO((tree, int));
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 lookup_namespace_name PROTO((tree, tree));
+extern tree make_typename_type PROTO((tree, tree));
+extern tree lookup_name_nonclass PROTO((tree));
+extern tree lookup_name PROTO((tree, int));
extern tree lookup_name_current_level PROTO((tree));
+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));
+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 int start_function PROTO((tree, tree, tree, int));
+extern void store_after_parms PROTO((struct rtx_def *));
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 tree strip_attrs PROTO((tree));
/* in decl2.c */
+extern int flag_assume_nonnull_objects;
extern int lang_decode_option PROTO((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 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 +2138,255 @@ 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_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 tree do_class_using_decl PROTO((tree));
-extern tree current_namespace_id PROTO((tree));
extern tree get_namespace_id PROTO((void));
+extern tree current_namespace_id PROTO((tree));
+extern void do_namespace_alias PROTO((tree, tree));
+extern void do_toplevel_using_decl PROTO((tree));
+extern tree do_class_using_decl PROTO((tree));
+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));
-/* 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 *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));
/* 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 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 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));
+#endif
extern void init_lex PROTO((void));
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));
+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 void report_type_mismatch PROTO((struct candidate *, tree, char *));
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_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 tsubst PROTO ((tree, tree, int, tree));
+extern tree tsubst_expr PROTO ((tree, tree, int, tree));
+extern tree tsubst_copy PROTO ((tree, tree, int, tree));
+extern tree tsubst_chain PROTO((tree, tree));
+extern void begin_member_template_processing PROTO((tree));
+extern void end_member_template_processing PROTO((void));
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 tree determine_explicit_specialization PROTO((tree, tree, tree *, int, int));
+extern int 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 void end_template_decl PROTO((void));
+extern tree current_template_args PROTO((void));
+extern void push_template_decl PROTO((tree));
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 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, int));
+extern int type_unification PROTO((tree, tree *, tree, tree, tree, int *, int, 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));
+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));
+/* CONT ... */
+extern void add_tree PROTO((tree));
+extern void add_maybe_template PROTO((tree, tree));
+extern void pop_tinst_level PROTO((void));
+extern tree most_specialized PROTO((tree, tree));
+extern tree most_specialized_class PROTO((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 processing_specialization;
+
+/* 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 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_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 +2396,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,24 +2404,30 @@ 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 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 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 break_out_cleanups PROTO((tree));
extern tree break_out_calls PROTO((tree));
extern tree build_cplus_method_type PROTO((tree, tree, tree));
@@ -2361,74 +2436,82 @@ 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 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 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_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 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));
+#define scratchalloc expralloc
+#define scratch_tree_cons expr_tree_cons
+#define build_scratch_list build_expr_list
+#define make_scratch_vec make_temp_vec
/* 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 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 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 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 +2531,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 +2540,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,13 +2561,15 @@ 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 *));
diff --git a/gnu/usr.bin/gcc/cp/cvt.c b/gnu/usr.bin/gcc/cp/cvt.c
index 56508c1cd30..29964928005 100644
--- a/gnu/usr.bin/gcc/cp/cvt.c
+++ b/gnu/usr.bin/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, 93, 94, 95, 1996 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -26,14 +26,26 @@ Boston, MA 02111-1307, USA. */
but what kind of conversions it does will depend on the language. */
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "flags.h"
#include "cp-tree.h"
#include "class.h"
#include "convert.h"
-#undef NULL
-#define NULL (char *)0
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+extern tree static_aggregates;
+
+static tree build_thunk PROTO((tree, tree));
+static tree convert_fn_ptr PROTO((tree, tree));
+static tree cp_convert_to_pointer PROTO((tree, tree));
+static tree convert_to_pointer_force PROTO((tree, tree));
+static tree build_up_reference PROTO((tree, tree, int, int));
+static tree build_type_conversion_1 PROTO((tree, tree, tree, tree,
+ int));
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
@@ -61,6 +73,7 @@ Boston, MA 02111-1307, USA. */
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;
@@ -78,10 +91,12 @@ build_thunk (offset, real_addr)
/* 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 0 /* We don't use thunks for pmfs. */
if (flag_vtable_thunks)
{
tree intype = TREE_TYPE (expr);
@@ -94,7 +109,7 @@ convert_fn_ptr (type, expr)
}
if (binfo == NULL_TREE)
{
- /* ARM 4.8 restriction. */
+ /* ARM 4.8 restriction. */
error ("invalid pointer to member conversion");
return error_mark_node;
}
@@ -104,6 +119,7 @@ convert_fn_ptr (type, expr)
return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr));
}
else
+#endif
return build_ptrmemfunc (type, expr, 1);
}
@@ -113,6 +129,7 @@ convert_fn_ptr (type, expr)
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;
@@ -120,8 +137,74 @@ cp_convert_to_pointer (type, expr)
register tree intype = TREE_TYPE (expr);
register enum tree_code form;
+ if (IS_AGGR_TYPE (intype))
+ {
+ tree rval;
+
+ 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 +216,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;
@@ -198,23 +283,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;
@@ -224,7 +296,7 @@ cp_convert_to_pointer (type, expr)
{
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 +314,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 +324,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 +344,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 +355,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 +374,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 +384,60 @@ 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);
+ }
+
+ /* 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 +472,11 @@ 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);
+ if (flag_ansi_overloading)
+ rval_as_conversion
+ = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
+ else
+ rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1);
if (rval_as_conversion && rval_as_conversion != error_mark_node
&& real_lvalue_p (rval_as_conversion))
@@ -708,15 +502,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))
@@ -753,7 +546,19 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (rval != error_mark_node)
rval = build1 (NOP_EXPR, reftype, rval);
}
- else if (decl)
+ else if (flag_ansi_overloading)
+ {
+ 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",
+ reftype, intype);
+ }
+ else
{
tree rval_as_ctor = NULL_TREE;
@@ -773,8 +578,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
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),
+ (NULL_TREE, ctor_identifier,
+ build_expr_list (NULL_TREE, expr), TYPE_BINFO (type),
LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY
| LOOKUP_ONLYCONVERTING)))
{
@@ -782,10 +587,9 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
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),
+ init = build_method_call (t, ctor_identifier,
+ build_expr_list (NULL_TREE, expr),
TYPE_BINFO (type),
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
| LOOKUP_ONLYCONVERTING);
@@ -799,8 +603,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
}
else
{
- init = build_method_call (NULL_TREE, constructor_name_full (type),
- build_tree_list (NULL_TREE, expr),
+ init = build_method_call (NULL_TREE, ctor_identifier,
+ build_expr_list (NULL_TREE, expr),
TYPE_BINFO (type),
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
|LOOKUP_ONLYCONVERTING);
@@ -808,7 +612,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (init == error_mark_node)
return error_mark_node;
- rval = build_cplus_new (type, init, 1);
+ rval = build_cplus_new (type, init);
rval = build_up_reference (reftype, rval, flags, 1);
}
rval_as_ctor = rval;
@@ -826,7 +630,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
rval = rval_as_conversion;
else if (! IS_AGGR_TYPE (type) && ! IS_AGGR_TYPE (intype))
{
- rval = convert (type, expr);
+ rval = cp_convert (type, expr);
if (rval == error_mark_node)
return error_mark_node;
@@ -840,7 +644,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 +660,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;
@@ -878,6 +683,7 @@ convert_from_reference (val)
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;
@@ -887,8 +693,11 @@ convert_to_aggr (type, expr, msgp, protect)
tree basetype = type;
tree name = TYPE_IDENTIFIER (basetype);
tree function, fndecl, fntype, parmtypes, parmlist, result;
+#if 0
+ /* See code below that used this. */
tree method_name;
- enum access_type access;
+#endif
+ tree access;
int can_be_private, can_be_protected;
if (! TYPE_HAS_CONSTRUCTOR (basetype))
@@ -898,70 +707,32 @@ convert_to_aggr (type, expr, msgp, protect)
return error_mark_node;
}
- access = access_public;
+ access = access_public_node;
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);
+ parmlist = build_expr_list (NULL_TREE, expr);
+ parmtypes = scratch_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);
+ parmtypes = expr_tree_cons (NULL_TREE, integer_type_node, parmtypes);
+ parmlist = scratch_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
+ parmlist = expr_tree_cons (NULL_TREE, integer_zero_node, parmlist);
+ parmtypes = scratch_tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);
/* 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 *candidates
+ = (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate));
struct candidate *cp = candidates;
while (fndecl)
@@ -978,20 +749,20 @@ convert_to_aggr (type, expr, msgp, protect)
if (protect)
{
if (TREE_PRIVATE (fndecl))
- access = access_private;
+ access = access_private_node;
else if (TREE_PROTECTED (fndecl))
- access = access_protected;
+ access = access_protected_node;
else
- access = access_public;
+ access = access_public_node;
}
else
- access = access_public;
+ access = access_public_node;
- if (access == access_private
+ if (access == access_private_node
? (basetype == current_class_type
|| is_friend (basetype, cp->function)
|| purpose_member (basetype, DECL_ACCESS (fndecl)))
- : access == access_protected
+ : access == access_protected_node
? (can_be_protected
|| purpose_member (basetype, DECL_ACCESS (fndecl)))
: 1)
@@ -1002,7 +773,7 @@ convert_to_aggr (type, expr, msgp, protect)
}
else
{
- if (access == access_private)
+ if (access == access_private_node)
saw_private = 1;
else
saw_protected = 1;
@@ -1021,7 +792,7 @@ convert_to_aggr (type, expr, msgp, protect)
qsort (candidates, /* char *base */
cp - candidates, /* int nel */
sizeof (struct candidate), /* int width */
- rank_for_overload); /* int (*compar)() */
+ (int (*) PROTO((const void *, const void *))) rank_for_overload); /* int (*compar)() */
--cp;
if (cp->h.code & EVIL_CODE)
@@ -1052,7 +823,7 @@ convert_to_aggr (type, expr, msgp, protect)
/* NOTREACHED */
found:
- if (access == access_private)
+ if (access == access_private_node)
if (! can_be_private)
{
if (msgp)
@@ -1061,7 +832,7 @@ convert_to_aggr (type, expr, msgp, protect)
: "conversion to type `%s' is from private base class";
return error_mark_node;
}
- if (access == access_protected)
+ if (access == access_protected_node)
if (! can_be_protected)
{
if (msgp)
@@ -1078,14 +849,11 @@ convert_to_aggr (type, expr, msgp, protect)
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;
+
+ parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
+ parmlist, NULL_TREE, LOOKUP_NORMAL);
+
+ result = build_call (function, TREE_TYPE (fntype), parmlist);
return result;
}
@@ -1095,6 +863,7 @@ convert_to_aggr (type, expr, msgp, protect)
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;
@@ -1115,7 +884,9 @@ 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;
@@ -1159,6 +930,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,20 +946,29 @@ 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))
@@ -1203,7 +984,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. */
@@ -1229,12 +1010,12 @@ cp_convert (type, expr, convtype, flags)
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 +1035,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 +1060,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
@@ -1317,48 +1107,70 @@ 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 (flag_ansi_overloading)
{
- if (flags & LOOKUP_COMPLAIN)
- error ("ambiguous pointer conversion");
- return conversion;
+ ctor = e;
+
+ if ((flags & LOOKUP_ONLYCONVERTING)
+ && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
+ {
+ ctor = build_user_type_conversion (type, ctor, flags);
+ flags |= LOOKUP_NO_CONVERSION;
+ }
+ 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);
}
+ else
+ {
+ if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype)
+ && TYPE_HAS_CONVERSION (dtype))
+ conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
- 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 (conversion == error_mark_node)
+ {
+ if (flags & LOOKUP_COMPLAIN)
+ error ("ambiguous pointer conversion");
+ return conversion;
+ }
- 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 (TYPE_HAS_CONSTRUCTOR (complete_type (type)))
+ ctor = build_method_call (NULL_TREE, ctor_identifier,
+ build_expr_list (NULL_TREE, e),
+ TYPE_BINFO (type),
+ (flags & LOOKUP_NORMAL)
+ | LOOKUP_SPECULATIVELY
+ | (flags & LOOKUP_ONLYCONVERTING)
+ | (flags & LOOKUP_NO_CONVERSION)
+ | (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;
+ 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);
+ return ctor;
+ }
}
}
@@ -1382,18 +1194,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,14 +1259,15 @@ 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);
+ return ocp_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;
@@ -1459,7 +1299,7 @@ build_type_conversion_1 (xtype, basetype, expr, typename, for_sure)
&& (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval)))
> TREE_READONLY (TREE_TYPE (xtype))))
warning ("user-defined conversion casting away `const'");
- return convert (xtype, rval);
+ return cp_convert (xtype, rval);
}
/* Convert an aggregate EXPR to type XTYPE. If a conversion
@@ -1491,6 +1331,10 @@ build_type_conversion (code, xtype, expr, for_sure)
tree conv;
tree winner = NULL_TREE;
+ if (flag_ansi_overloading)
+ return build_user_type_conversion
+ (xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
+
if (expr == error_mark_node)
return error_mark_node;
@@ -1513,10 +1357,12 @@ build_type_conversion (code, xtype, expr, 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))
+ tree cand = TREE_VALUE (conv);
+
+ if (winner && winner == cand)
continue;
- if (can_convert (xtype, TREE_VALUE (conv)))
+ if (can_convert (xtype, TREE_TYPE (TREE_TYPE (cand))))
{
if (winner)
{
@@ -1524,19 +1370,19 @@ build_type_conversion (code, xtype, expr, 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));
+ cp_error (" candidate conversions include `%D' and `%D'",
+ winner, cand);
}
return NULL_TREE;
}
else
- winner = conv;
+ winner = cand;
}
}
if (winner)
return build_type_conversion_1 (xtype, basetype, expr,
- TREE_PURPOSE (winner), for_sure);
+ DECL_NAME (winner), for_sure);
return NULL_TREE;
}
@@ -1568,7 +1414,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;
@@ -1594,11 +1440,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);
@@ -1623,19 +1470,24 @@ 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);
+ {
+ tree type = TREE_TYPE (TREE_TYPE (winner));
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ return build_type_conversion_1 (type, basetype, expr,
+ DECL_NAME (winner), 1);
+ }
return NULL_TREE;
}
@@ -1646,6 +1498,7 @@ build_expr_type_conversion (desires, expr, complain)
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;
@@ -1751,8 +1604,8 @@ build_default_binary_type_conversion (code, arg1, arg2)
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
- *arg1 = convert (boolean_type_node, *arg1);
- *arg2 = convert (boolean_type_node, *arg2);
+ *arg1 = cp_convert (boolean_type_node, *arg1);
+ *arg2 = cp_convert (boolean_type_node, *arg2);
break;
default:
@@ -1769,7 +1622,8 @@ build_default_binary_type_conversion (code, arg1, arg2)
return 0;
}
-/* 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 +1658,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;
diff --git a/gnu/usr.bin/gcc/cp/decl.c b/gnu/usr.bin/gcc/cp/decl.c
index 103cb0de2c5..7b3af601c29 100644
--- a/gnu/usr.bin/gcc/cp/decl.c
+++ b/gnu/usr.bin/gcc/cp/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, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -27,8 +27,8 @@ 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 <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "rtl.h"
#include "flags.h"
@@ -38,6 +38,17 @@ Boston, MA 02111-1307, USA. */
#include <sys/types.h>
#include <signal.h>
#include "obstack.h"
+#include "defaults.h"
+#include "output.h"
+#include "except.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free PROTO((void *));
+#endif
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
@@ -48,16 +59,16 @@ extern struct obstack permanent_obstack;
extern int current_class_depth;
-extern tree cleanups_this_call;
-
extern tree static_ctors, static_dtors;
+extern int static_labelno;
+
/* 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 +109,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,10 +136,47 @@ 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 void revert_static_member_fn PROTO((tree *, tree *, tree *));
+static tree push_overloaded_decl PROTO((tree, int));
+static void push_overloaded_decl_top_level 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 tree get_unique_name 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));
+static void warn_extern_redeclared_static PROTO((tree, tree));
+static void grok_reference_init PROTO((tree, tree, tree, tree *));
+static tree grokfndecl PROTO((tree, tree, tree, tree, int,
+ enum overload_flags,
+ tree, tree, tree, int, int, int, int, int, int));
+static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int));
+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 record_builtin_type PROTO((enum rid, char *, tree));
+static int member_function_or_else PROTO((tree, tree, char *));
+static void bad_specifiers PROTO((tree, char *, int, int, int, int,
+ int));
/* a node which has tree code ERROR_MARK, and whose type is itself.
All erroneous expressions are replaced with this node. All functions
@@ -168,6 +216,11 @@ 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;
@@ -185,7 +238,8 @@ tree void_zero_node;
/* Nodes for types `void *' and `const void *'. */
-tree ptr_type_node, const_ptr_type_node;
+tree ptr_type_node;
+static tree const_ptr_type_node;
/* Nodes for types `char *' and `const char *'. */
@@ -215,32 +269,27 @@ tree default_function_type;
/* 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;
@@ -257,16 +306,29 @@ 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;
+
/* 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, but before the start of the exception
+ specification. */
+
+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 +346,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,10 +355,21 @@ 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
@@ -305,11 +378,17 @@ tree vb_off_identifier, vt_off_identifier;
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 +404,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 +451,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 +496,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 +514,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 +522,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 +531,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 +551,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,19 +574,18 @@ 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;
/* For each level, a list of shadowed outer-level local definitions
@@ -554,7 +618,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 +638,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 +746,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 +758,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 +790,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 +802,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,14 +818,14 @@ 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. */
+ /* These are here because we cannot deal with shadows yet. */
sorry ("cannot resume a namespace inside class");
return;
#else
@@ -791,7 +836,7 @@ resume_binding_level (b)
else
{
#if 1
- /* These are here because we cannot deal with shadows yet. */
+ /* 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");
@@ -811,6 +856,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
@@ -832,6 +887,8 @@ toplevel_bindings_p ()
{
if (b == global_binding_level)
return 1;
+ if (b->pseudo_global)
+ return 1;
if (! b->namespace_p)
return 0;
b=b->level_chain;
@@ -840,7 +897,7 @@ toplevel_bindings_p ()
/* Nonzero if this is a namespace scope. */
-int
+static int
namespace_bindings_p ()
{
return current_binding_level->namespace_p;
@@ -873,24 +930,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 +984,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 +1045,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 +1056,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 +1106,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 +1145,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 +1194,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);
+ 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);
}
- 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))
- 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 +1276,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 +1315,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
@@ -1300,6 +1333,7 @@ poplevel (keep, reverse, functionbody)
}
/* Resume a binding level for a namespace. */
+
void
resume_level (b)
struct binding_level *b;
@@ -1315,8 +1349,11 @@ resume_level (b)
for (link = decls; link; link = TREE_CHAIN (link))
{
- if (DECL_NAME (link) != NULL_TREE)
- IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = link;
+ /* If it doesn't have a name, there is nothing left to do with it. */
+ if (DECL_NAME (link) == NULL_TREE)
+ continue;
+
+ 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)
@@ -1362,6 +1399,7 @@ insert_block (block)
}
/* Add BLOCK to the current list of blocks for this binding contour. */
+
void
add_block_current_level (block)
tree block;
@@ -1381,6 +1419,7 @@ set_block (block)
}
/* Do a pushlevel for class declarations. */
+
void
pushlevel_class ()
{
@@ -1398,8 +1437,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 +1461,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,7 +1488,10 @@ 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))
@@ -1458,8 +1500,7 @@ poplevel_class (force)
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;
@@ -1476,8 +1517,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 +1543,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),"<built-in>")))
+ && (TREE_CODE (t) == TYPE_DECL)
+ && (!strcmp (DECL_SOURCE_FILE (t),"<built-in>")))
continue;
/* Function decls tend to have longer names. */
@@ -1521,7 +1562,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 +1626,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");
}
@@ -1647,6 +1678,7 @@ extern char * first_global_object_name;
/* 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 ()
{
@@ -1672,15 +1704,10 @@ get_unique_name ()
{
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... */
+#ifndef NO_DOT_IN_LABEL /* this for `.'; unlikely, but... */
|| *p == '.'
#endif
|| (*p >= 'A' && *p <= 'Z')
@@ -1693,14 +1720,22 @@ get_unique_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. */
+
void
push_namespace (name)
tree name;
{
+#if 1
+ static int warned;
+ if (! warned)
+ sorry ("namespace");
+
+ warned = 1;
+#else
extern tree current_namespace;
tree old_id = get_namespace_id ();
char *buf;
- tree d = make_node (NAMESPACE_DECL);
+ tree d;
if (! name)
{
@@ -1708,12 +1743,11 @@ push_namespace (name)
name = get_unique_name ();
}
- 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;
+ d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
+
/* Mark them as external, so redeclaration_error_message doesn't think
- they are duplicates. */
+ they are duplicates. */
+
DECL_EXTERNAL (d) = 1;
d = pushdecl (d);
@@ -1722,31 +1756,32 @@ push_namespace (name)
/* This is new for this compilation unit. */
pushlevel (0);
declare_namespace_level ();
- NAMESPACE_LEVEL (d) = (tree)current_binding_level;
+ NAMESPACE_LEVEL (d) = current_binding_level;
}
else
- {
- resume_level ((struct binding_level*)NAMESPACE_LEVEL (d));
- }
+ resume_level (NAMESPACE_LEVEL (d));
- /* This code is just is bit old now... */
+ /* 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);
+#endif
}
/* Pop from the scope of the current namespace. */
+
void
pop_namespace ()
{
+#if 0
extern tree current_namespace;
tree decls, link;
current_namespace = TREE_CHAIN (current_namespace);
- /* Just in case we get out of sync. */
+ /* Just in case we get out of sync. */
if (! namespace_bindings_p ())
poplevel (0, 0, 0);
@@ -1785,6 +1820,7 @@ pop_namespace ()
/* suspend a level. */
suspend_binding_level ();
+#endif
}
/* Subroutines for reverting temporarily to top-level for instantiation
@@ -1797,105 +1833,141 @@ struct saved_scope {
tree old_bindings;
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;
};
static struct saved_scope *current_saved_scope;
-extern tree prev_class_type;
+
+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;
+
+ 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:
+ ;
+ }
+ 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);
+ 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->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;
+
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;
+ minimal_parse_mode = 0;
+ previous_class_type = previous_class_values = NULL_TREE;
+ if (!pseudo)
+ {
+ current_template_parms = NULL_TREE;
+ processing_template_decl = 0;
+ }
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,8 +1977,14 @@ 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;
@@ -1922,11 +2000,8 @@ pop_from_top_level ()
}
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 +2011,17 @@ 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;
free (s);
+
+ if (current_function_decl)
+ pop_cp_function_context (NULL_TREE);
}
/* Push a definition of struct, union or enum tag "name".
@@ -1948,7 +2031,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
@@ -1969,7 +2052,7 @@ set_identifier_type_value_with_scope (id, type, b)
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
-/* As set_identifier_type_value_with_scope, but using inner_binding_level. */
+/* As set_identifier_type_value_with_scope, but using inner_binding_level. */
void
set_identifier_type_value (id, type)
@@ -1979,59 +2062,10 @@ 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;
-{
- char *buf;
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 136);
-
- /* No need to do this for anonymous names, since they're unique. */
- if (ANON_AGGRNAME_P (name))
- {
- DECL_NESTED_TYPENAME (decl) = name;
- return;
- }
-
- if (classname == NULL_TREE)
- classname = get_identifier ("");
-
- 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;
-
- /* 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);
- }
-}
-
/* 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 +2084,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,
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)
@@ -2114,12 +2117,6 @@ pushtag (name, type, globalize)
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
-
/* Do C++ gratuitous typedefing. */
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
@@ -2134,39 +2131,22 @@ pushtag (name, type, globalize)
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);
+ d = TYPE_MAIN_DECL (d);
TYPE_NAME (type) = d;
+ DECL_CONTEXT (d) = context;
+ if (! globalize && processing_template_decl && IS_AGGR_TYPE (type))
+ push_template_decl (d);
- /* 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->parm_flag == 2)
+ d = pushdecl_class_level (d);
+ else
+ d = pushdecl_with_scope (d, b);
}
else
{
@@ -2174,51 +2154,20 @@ pushtag (name, type, globalize)
newdecl = 1;
d = build_decl (TYPE_DECL, name, type);
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 */
-
- TYPE_MAIN_DECL (type) = d;
+ TYPE_NAME (type) = d;
+ DECL_CONTEXT (d) = context;
+ if (! globalize && processing_template_decl && IS_AGGR_TYPE (type))
+ push_template_decl (d);
- /* 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 (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);
+ if (ANON_AGGRNAME_P (name))
+ DECL_IGNORED_P (d) = 1;
- 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 +2193,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 +2216,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 +2251,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;
@@ -2366,27 +2315,41 @@ decls_match (newdecl, olddecl)
{
tree newargs = DECL_TEMPLATE_PARMS (newdecl);
tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
- int i, len = TREE_VEC_LENGTH (newargs);
+ int i;
- if (TREE_VEC_LENGTH (oldargs) != len)
- return 0;
-
- for (i = 0; i < len; i++)
+ /* Run through all the levels of template parameters, checking
+ that they match. */
+ while (newargs && oldargs)
{
- 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))
+ int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs));
+
+ if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (oldargs)) != len)
return 0;
+
+ for (i = 0; i < len; i++)
+ {
+ tree newarg =
+ TREE_VALUE (TREE_VEC_ELT
+ (INNERMOST_TEMPLATE_PARMS (newargs), i));
+ tree oldarg =
+ TREE_VALUE (TREE_VEC_ELT
+ (INNERMOST_TEMPLATE_PARMS (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;
+ }
+ newargs = TREE_CHAIN (newargs);
+ oldargs = TREE_CHAIN (oldargs);
}
- if (DECL_TEMPLATE_IS_CLASS (newdecl)
- != DECL_TEMPLATE_IS_CLASS (olddecl))
- types_match = 0;
- else if (DECL_TEMPLATE_IS_CLASS (newdecl))
+ if ((newargs == NULL_TREE) != (oldargs == NULL_TREE))
+ /* One declaration has more levels that the other. */
+ return 0;
+
+ if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = 1;
else
types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
@@ -2400,8 +2363,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 +2389,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 +2403,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,13 +2435,15 @@ 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;
+
+ if (newdecl == olddecl)
+ return 1;
if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
DECL_MACHINE_ATTRIBUTES (newdecl) = DECL_MACHINE_ATTRIBUTES (olddecl);
@@ -2485,25 +2458,18 @@ duplicate_decls (newdecl, olddecl)
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))
+ 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)))
+ 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)))
{
@@ -2540,11 +2506,9 @@ duplicate_decls (newdecl, olddecl)
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
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);
@@ -2563,14 +2527,22 @@ 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))
+ {
+ cp_error ("new declaration `%#D'", newdecl);
+ cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+ }
return 0;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -2600,6 +2572,20 @@ duplicate_decls (newdecl, olddecl)
cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
+ else if ((TREE_CODE (olddecl) == FUNCTION_DECL
+ && DECL_TEMPLATE_SPECIALIZATION (olddecl)
+ && (!DECL_TEMPLATE_SPECIALIZATION (newdecl)
+ || (DECL_TI_TEMPLATE (newdecl)
+ != DECL_TI_TEMPLATE (olddecl))))
+ || (TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_TEMPLATE_SPECIALIZATION (newdecl)
+ && (!DECL_TEMPLATE_SPECIALIZATION (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. */
+ return 0;
else
{
char *errmsg = redeclaration_error_message (newdecl, olddecl);
@@ -2638,7 +2624,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 +2654,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 +2681,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
@@ -2722,8 +2696,6 @@ duplicate_decls (newdecl, 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);
@@ -2737,8 +2709,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,18 +2716,6 @@ 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. */
@@ -2779,6 +2737,17 @@ duplicate_decls (newdecl, olddecl)
/* Copy all the DECL_... slots specified in the new decl
except for any that we copy here from the old type. */
+ if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+ {
+ if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE)
+ {
+ TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
+ DECL_TEMPLATE_RESULT (olddecl) = DECL_TEMPLATE_RESULT (newdecl);
+ DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
+ }
+ return 1;
+ }
+
if (types_match)
{
/* Automatically handles default parameters. */
@@ -2805,32 +2774,34 @@ 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))
+ && 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)
+ && 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 +2852,23 @@ 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_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);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
+ if (DECL_TEMPLATE_INSTANTIATION (olddecl) &&
+ !DECL_TEMPLATE_INSTANTIATION (newdecl))
+ DECL_USE_TEMPLATE (olddecl) = DECL_USE_TEMPLATE (newdecl);
DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
/* If either decl says `inline', this fn is inline, unless its
@@ -2907,9 +2881,13 @@ duplicate_decls (newdecl, olddecl)
{
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (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);
- DECL_RTL (olddecl) = DECL_RTL (newdecl);
}
if (new_defines_function)
/* If defining a function declared with other language
@@ -2950,15 +2928,12 @@ duplicate_decls (newdecl, 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);
@@ -2972,6 +2947,11 @@ duplicate_decls (newdecl, 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 (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
+ {
+ DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+ DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
+ }
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3001,19 +2981,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. */;
}
}
}
@@ -3045,23 +3029,9 @@ 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
/* Don't change DECL_CONTEXT of virtual methods. */
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
@@ -3071,27 +3041,22 @@ pushdecl (x)
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
/* 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)
name = DECL_NAME (x);
-#endif
if (name)
{
+#if 0
+ /* Not needed...see below. */
char *file;
int line;
-
+#endif
+ if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+ name = TREE_OPERAND (name, 0);
+
t = lookup_name_current_level (name);
if (t == error_mark_node)
{
@@ -3102,19 +3067,24 @@ 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))
+ || DECL_FUNCTION_TEMPLATE_P (x))
+ && is_overloaded_fn (t))
/* don't do anything just yet */;
else if (t == wchar_decl_node)
{
@@ -3126,8 +3096,15 @@ 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)))
+ if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
+ && TREE_CODE (x) != TYPE_DECL
+ && ! (TREE_CODE (x) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (x)) == TYPE_DECL))
+ || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
+ && TREE_CODE (t) != TYPE_DECL
+ && ! (TREE_CODE (t) == TEMPLATE_DECL
+ && (TREE_CODE (DECL_TEMPLATE_RESULT (t))
+ == TYPE_DECL))))
{
/* We do nothing special here, because C++ does such nasty
things with TYPE_DECLs. Instead, just let the TYPE_DECL
@@ -3186,7 +3163,7 @@ 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_CONTEXT (x) == NULL_TREE)
return push_overloaded_decl (x, 0);
/* If declaring a type as a typedef, and the type has no known
@@ -3204,28 +3181,8 @@ pushdecl (x)
if (global_bindings_p ())
TYPE_NAME (type) = x;
}
- else
- {
- tree tname = DECL_NAME (name);
-
- /* 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);
- /* 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);
-
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
@@ -3259,12 +3216,6 @@ 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)
@@ -3273,7 +3224,7 @@ pushdecl (x)
/* 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 (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
/* Don't install an artificial TYPE_DECL if we already have
@@ -3379,7 +3330,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,7 +3349,7 @@ 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)
@@ -3435,7 +3386,8 @@ 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)
@@ -3443,15 +3395,19 @@ pushdecl_with_scope (x, level)
struct binding_level *level;
{
register struct binding_level *b = current_binding_level;
+ tree function_decl = current_function_decl;
+ current_function_decl = NULL_TREE;
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,
if appropriate. */
+
tree
pushdecl_top_level (x)
tree x;
@@ -3487,13 +3443,6 @@ 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;
}
}
@@ -3502,7 +3451,8 @@ pushdecl_top_level (x)
/* Like push_overloaded_decl, only it places X in GLOBAL_BINDING_LEVEL,
if appropriate. */
-void
+
+static void
push_overloaded_decl_top_level (x, forget)
tree x;
int forget;
@@ -3515,6 +3465,7 @@ push_overloaded_decl_top_level (x, forget)
}
/* Make the declaration of X appear in CLASS scope. */
+
tree
pushdecl_class_level (x)
tree x;
@@ -3532,7 +3483,7 @@ pushdecl_class_level (x)
members are checked in finish_struct. */
tree icv = IDENTIFIER_CLASS_VALUE (name);
- if (icv
+ if (icv && icv != x
/* Don't complain about inherited names. */
&& id_in_current_class (name)
/* Or shadowed tags. */
@@ -3549,49 +3500,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;
@@ -3607,6 +3556,7 @@ push_class_level_binding (name, x)
/* Tell caller how to interpret a TREE_LIST which contains
chains of FUNCTION_DECLS. */
+
int
overloaded_globals_p (list)
tree list;
@@ -3616,11 +3566,11 @@ overloaded_globals_p (list)
/* 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;
+ if (TREE_CODE (TREE_VALUE (list)) == TREE_LIST)
+ return 0;
+ /* Do commit caller to seeing them as globals. */
+ return 1;
}
/* DECL is a FUNCTION_DECL which may have other definitions already in
@@ -3635,15 +3585,15 @@ 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 = (global_bindings_p () || ! forgettable);
if (doing_global)
{
@@ -3671,18 +3621,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;
}
@@ -3738,7 +3682,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 +3694,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);
@@ -3813,11 +3756,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 +3804,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 +3832,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 +3848,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;
}
@@ -3929,7 +3887,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 +3924,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 +3933,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 +3956,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 +4017,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 +4123,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;
@@ -4165,20 +4149,27 @@ 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 (level->pseudo_global)
+ {
+ tree t = IDENTIFIER_GLOBAL_VALUE (name);
+ if (t && TREE_CODE (t) == TEMPLATE_DECL
+ && TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
+ return TREE_TYPE (t);
+ }
+ return NULL_TREE;
+ }
if (current_class_type && level->level_chain == global_binding_level)
{
/* Try looking in this class's tags before heading into
@@ -4208,6 +4199,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 +4210,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 +4227,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 +4265,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,24 +4309,79 @@ 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;
+ tree x = NULL_TREE;
- for (x = NULL_TREE; b && !x; b = b->level_chain)
+#if 1
+ /* This searches just one level. */
+ if (b)
{
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;
}
+#else
+ /* This searches all levels. */
+ for (; b && !x; b = b->level_chain)
+ {
+ for (x = b->names; x; x = TREE_CHAIN (x))
+ if (DECL_NAME (x) == name || DECL_ASSEMBLER_NAME (x) == name)
+ break;
+ }
+#endif
return x;
}
+tree
+make_typename_type (context, name)
+ tree context, name;
+{
+ tree t, d;
+
+ if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+ name = TYPE_IDENTIFIER (name);
+ else if (TREE_CODE (name) == TYPE_DECL)
+ name = DECL_NAME (name);
+ else if (TREE_CODE (name) != IDENTIFIER_NODE)
+ my_friendly_abort (2000);
+
+ if (! uses_template_parms (context)
+ || context == current_class_type)
+ {
+ 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);
+ d = build_decl (TYPE_DECL, name, t);
+ if (processing_template_decl)
+ pop_obstacks ();
+
+ TYPE_CONTEXT (t) = context;
+ TYPE_NAME (TREE_TYPE (d)) = d;
+ TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+ DECL_CONTEXT (d) = context;
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+
+ return t;
+}
+
/* 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
@@ -4369,7 +4392,7 @@ lookup_namespace_name (namespace, name)
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs. */
-tree
+static tree
lookup_name_real (name, prefer_type, nonclass)
tree name;
int prefer_type, nonclass;
@@ -4377,15 +4400,20 @@ lookup_name_real (name, prefer_type, nonclass)
register tree val;
int yylex = 0;
tree from_obj = NULL_TREE;
+ tree locval, classval;
if (prefer_type == -2)
{
extern int looking_for_typename;
- tree type;
+ tree type = NULL_TREE;
yylex = 1;
prefer_type = looking_for_typename;
+ /* std:: becomes :: for now. */
+ if (got_scope == std_node)
+ got_scope = void_type_node;
+
if (got_scope)
type = got_scope;
else if (got_object != error_mark_node)
@@ -4395,23 +4423,21 @@ lookup_name_real (name, prefer_type, nonclass)
{
if (type == error_mark_node)
return error_mark_node;
- else if (type == void_type_node)
+ if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
+ type = TREE_TYPE (type);
+
+ type = complete_type (type);
+
+ 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. */
+ else if (! IS_AGGR_TYPE (type)
+ || TREE_CODE (type) == TEMPLATE_TYPE_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))
{
@@ -4430,8 +4456,7 @@ lookup_name_real (name, prefer_type, nonclass)
}
}
}
- if (val == NULL_TREE
- && CLASSTYPE_LOCAL_TYPEDECLS (type))
+ if (val == NULL_TREE)
val = lookup_field (type, name, 0, 1);
}
else if (type == current_class_type)
@@ -4442,54 +4467,116 @@ lookup_name_real (name, prefer_type, nonclass)
else
val = NULL_TREE;
+ /* Add implicit 'typename' to scoped types from other classes. */
+ if (got_scope && processing_template_decl
+ && got_scope != current_class_type
+ && uses_template_parms (got_scope)
+ && val && TREE_CODE (val) == TYPE_DECL
+ && ! DECL_ARTIFICIAL (val))
+ {
+ tree t = make_typename_type (got_scope, DECL_NAME (val));
+ TREE_TYPE (t) = TREE_TYPE (val);
+ val = TYPE_MAIN_DECL (t);
+ }
+
if (got_scope)
goto done;
-
- /* This special lookup only applies to types. */
- else if (got_object && val && TREE_CODE (val) == TYPE_DECL)
+ else if (got_object && val)
from_obj = val;
}
-
+
+ locval = classval = NULL_TREE;
+
if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name))
- val = IDENTIFIER_LOCAL_VALUE (name);
+ locval = IDENTIFIER_LOCAL_VALUE (name);
+
/* 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);
/* 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);
+ /* Add implicit 'typename' to types from base classes. */
+ if (processing_template_decl
+ && classval && TREE_CODE (classval) == TYPE_DECL
+ && DECL_CONTEXT (classval) != current_class_type
+ && uses_template_parms (DECL_CONTEXT (classval))
+ && ! DECL_ARTIFICIAL (classval))
+ {
+ tree t = make_typename_type (DECL_CONTEXT (classval),
+ DECL_NAME (classval));
+ TREE_TYPE (t) = TREE_TYPE (classval);
+ classval = TYPE_MAIN_DECL (t);
+ }
+ }
+
+ 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);
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));
+ }
+
+ val = from_obj;
+ }
if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
|| TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
;
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;
}
@@ -4577,10 +4664,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
@@ -4605,11 +4695,7 @@ 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;
@@ -4623,66 +4709,15 @@ record_builtin_type (rid_index, name, type)
}
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));
- }
- }
-}
-
-static void
-output_builtin_tdesc_entries ()
-{
- 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 ();
}
/* 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 +4725,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)));
}
@@ -4715,20 +4748,20 @@ 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;
+ /* 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++");
@@ -4747,19 +4780,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 +4806,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);
@@ -4793,6 +4829,8 @@ init_decl_processing ()
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 +4851,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,14 +4876,17 @@ init_decl_processing ()
record_builtin_type (RID_MAX, "long long unsigned",
long_long_unsigned_type_node);
+ 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.
- 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)));
@@ -4857,12 +4898,8 @@ init_decl_processing ()
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);
+ TREE_TYPE (TYPE_SIZE (short_integer_type_node)) = sizetype;
+ TREE_TYPE (TYPE_SIZE (short_unsigned_type_node)) = sizetype;
/* Define both `signed char' and `unsigned char'. */
signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
@@ -4906,6 +4943,30 @@ 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);
+
integer_zero_node = build_int_2 (0, 0);
TREE_TYPE (integer_zero_node) = integer_type_node;
integer_one_node = build_int_2 (1, 0);
@@ -4927,6 +4988,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 +5000,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.
@@ -4968,20 +5034,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 +5086,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 +5094,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 +5101,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 +5108,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 +5160,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)));
+ ptr_ftype_sizetype);
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,13 +5213,26 @@ 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)
{
@@ -5195,32 +5241,38 @@ init_decl_processing ()
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 +5282,45 @@ 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);
/* 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 +5329,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 +5350,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,6 +5428,10 @@ init_decl_processing ()
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
+ std_node = build_decl (NAMESPACE_DECL, get_identifier ("std"),
+ void_type_node);
+ pushdecl (std_node);
+
#if 0
if (flag_rtti)
{
@@ -5405,12 +5456,15 @@ init_decl_processing ()
__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);
+ __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);
@@ -5492,76 +5546,51 @@ init_decl_processing ()
finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7,
integer_type_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*/
/* 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)),
+ auto_function (ansi_opname[(int) NEW_EXPR], ptr_ftype_sizetype,
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)),
+ auto_function (ansi_opname[(int) VEC_NEW_EXPR], ptr_ftype_sizetype,
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)),
+ auto_function (ansi_opname[(int) DELETE_EXPR], void_ftype_ptr,
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)),
+ auto_function (ansi_opname[(int) VEC_DELETE_EXPR], void_ftype_ptr,
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 ();
+ 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 ();
+
+ /* Show we use EH for cleanups. */
+ using_eh_for_cleanups ();
}
-/* initialize type descriptor type node of various rtti type. */
+/* initialize type descriptor type node of various rtti type. */
int
init_type_desc()
@@ -5571,8 +5600,10 @@ init_type_desc()
tdecl = lookup_name (get_identifier ("type_info"), 0);
if (tdecl == NULL_TREE)
return 0;
- __t_desc_type_node = TREE_TYPE(tdecl);
+ __t_desc_type_node = TREE_TYPE (tdecl);
+#if 0
__tp_desc_type_node = build_pointer_type (__t_desc_type_node);
+#endif
#if 0
tdecl = lookup_name (get_identifier ("__baselist_type_info"), 0);
@@ -5642,7 +5673,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);
@@ -5693,10 +5724,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 +5765,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
{
@@ -5770,7 +5833,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 +5856,9 @@ groktypename (typename)
int debug_temp_inits = 1;
tree
-start_decl (declarator, declspecs, initialized, raises)
+start_decl (declarator, declspecs, initialized)
tree declarator, declspecs;
int initialized;
- tree raises;
{
register tree decl;
register tree type, tem;
@@ -5804,9 +5866,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,7 +5879,7 @@ 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)
return NULL_TREE;
@@ -5822,8 +5887,8 @@ start_decl (declarator, declspecs, initialized, raises)
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,61 +5906,11 @@ 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)
- {
- 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;
- }
-
- /* 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
@@ -5919,51 +5934,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 +5965,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,19 +5974,24 @@ 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));
+ 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;
}
@@ -6022,88 +6021,38 @@ start_decl (declarator, declspecs, initialized, raises)
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)
+ push_template_decl (tem);
+ else if (minimal_parse_mode)
+ DECL_VINDEX (decl)
+ = 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 +6063,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,77 +6073,105 @@ 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;
+ }
+ 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)). */
+ TREE_TYPE (decl) = error_mark_node;
+ type = 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. */
+ 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)
tree decl, type, init;
@@ -6224,6 +6202,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 +6220,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 +6275,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;
@@ -6362,6 +6321,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
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)
@@ -6391,8 +6351,20 @@ 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);
+ 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 +6383,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)
@@ -6620,7 +6578,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)
@@ -6659,21 +6617,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 +6640,50 @@ 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 ();
+ /* Extern inline function static data has external 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)
+ && current_function_decl
+ && DECL_CONTEXT (decl) == current_function_decl
+ && DECL_THIS_INLINE (current_function_decl)
+ && TREE_PUBLIC (current_function_decl))
+ {
+ if (DECL_INTERFACE_KNOWN (current_function_decl))
+ {
+ TREE_PUBLIC (decl) = 1;
+ DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
+ }
+ /* We can only do this if we can use common or weak, and we
+ can't if it has been initialized and we don't support weak. */
+ else if (DECL_INITIAL (decl) == NULL_TREE
+ || DECL_INITIAL (decl) == error_mark_node)
+ {
+ TREE_PUBLIC (decl) = 1;
+ DECL_COMMON (decl) = 1;
+ }
+ else if (flag_weak)
+ make_decl_one_only (decl);
+
+ 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);
+ }
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
make_decl_rtl (decl, NULL_PTR, toplev);
@@ -6751,7 +6726,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 +6747,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 +6779,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 +6821,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 +6829,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 +6894,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
+ 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 +6935,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 +6950,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 +6975,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 +6993,6 @@ expand_static_init (decl, init)
tree init;
{
tree oldstatic = value_member (decl, static_aggregates);
- tree old_cleanups;
if (oldstatic)
{
@@ -6973,7 +7004,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 +7012,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 +7025,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 +7069,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 +7168,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 +7186,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 +7217,22 @@ 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)
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 cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
+ tree t;
if (ctype)
cname = TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
@@ -7169,24 +7243,22 @@ 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 */
if (TYPE_VOLATILE (type))
- TREE_THIS_VOLATILE (decl) = 1;
+ TREE_THIS_VOLATILE (decl) = 1;
/* 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"))
{
@@ -7198,8 +7270,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 +7291,29 @@ 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;
+ }
+
/* Caller will do the rest of this. */
+ check_explicit_specialization (orig_declarator, decl,
+ template_count,
+ funcdef_flag ? 2 :
+ (friendp ? 3 : 0));
+
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,16 +7325,25 @@ 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);
+ {
+ 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);
+ tmp = IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl));
if (tmp == NULL_TREE)
IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (decl)) = decl;
else if (TREE_CODE (tmp) != TREE_CODE (decl))
@@ -7265,7 +7369,29 @@ grokfndecl (ctype, type, declarator, virtualp, flags, quals,
grokclassfn (ctype, cname, decl, flags, quals);
if (ctype != NULL_TREE && check)
- check_classfn (ctype, cname, decl);
+ {
+ 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;
@@ -7295,95 +7421,29 @@ 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)
tree type;
tree declarator;
- RID_BIT_TYPE specbits;
+ RID_BIT_TYPE *specbits_in;
int initialized;
int constp;
{
tree decl;
+ RID_BIT_TYPE specbits;
+
+ specbits = *specbits_in;
if (TREE_CODE (type) == OFFSET_TYPE)
{
@@ -7397,7 +7457,7 @@ grokvardecl (type, declarator, specbits, initialized, constp)
DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
}
else
- decl = build_decl (VAR_DECL, declarator, type);
+ decl = build_decl (VAR_DECL, declarator, complete_type (type));
DECL_ASSEMBLER_NAME (decl) = current_namespace_id (DECL_ASSEMBLER_NAME (decl));
@@ -7433,7 +7493,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,7 +7522,7 @@ 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. */
IS_AGGR_TYPE (t) = 0;
@@ -7482,7 +7542,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 +7606,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 +7623,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 +7631,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 +7649,8 @@ 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;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
@@ -7595,228 +7660,256 @@ 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;
+ tree *next = &declarator;
+ register tree decl;
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! */
+ while (next && *next)
+ {
+ decl = *next;
+ switch (TREE_CODE (decl))
{
- 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 COND_EXPR:
+ ctype = NULL_TREE;
+ next = &TREE_OPERAND (decl, 0);
+ break;
- case CALL_EXPR:
- if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
+ case BIT_NOT_EXPR: /* for C++ destructors! */
{
- /* 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);
+ 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
- declarator = TREE_OPERAND (decl, 0);
-
- init = TREE_OPERAND (decl, 1);
-
- 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))
- {
- return_type = return_ctor;
- ctor_return_type = ctype;
- }
- ctype = NULL_TREE;
- break;
-
- case IDENTIFIER_NODE:
- dname = decl;
- decl = NULL_TREE;
+ {
+ 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) : "<nameless>";
- 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);
+ /* 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 (really_overloaded_fn (fns))
+ dname = DECL_NAME (get_first_fn (fns));
else
- {
- ctype = IDENTIFIER_TYPE_VALUE (cname);
- TREE_OPERAND (decl, 0) = ctype;
- }
+ dname = DECL_NAME (fns);
}
+ /* 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 (! 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)
+ {
+ 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 +7942,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 +8005,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)
@@ -7929,7 +8023,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
{
if (pedantic && ! in_system_header)
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 +8035,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
}
}
+ /* C++ aggregate types. */
+ else if (TREE_CODE (id) == TYPE_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 +8059,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 +8075,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 +8089,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 +8103,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,8 +8121,8 @@ 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))
+ else if (declspecs == NULL_TREE
+ && (innermost_code != CALL_EXPR || pedantic))
cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type or storage class",
dname);
type = integer_type_node;
@@ -8044,13 +8149,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 +8195,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 +8215,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,6 +8257,31 @@ 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);
+ }
+
/* Set CONSTP if this declaration is `const', whether by
explicit specification or via a typedef.
Likewise for VOLATILEP. */
@@ -8162,13 +8290,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type);
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 +8319,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'. */
@@ -8256,8 +8363,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
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 +8407,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 +8425,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 +8474,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 +8507,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 +8523,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;
@@ -8579,10 +8602,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
&& 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 +8649,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 +8738,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
@@ -8736,7 +8789,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;
@@ -8757,15 +8810,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
{
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 +8854,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. */
@@ -8842,10 +8885,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
}
- /* 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;
@@ -8990,6 +9043,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);
@@ -8999,8 +9054,27 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
multiple times. */ ;
else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
/* 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<T>::type' in
+ 'B<typename B<T>::type> B<T>::f () { }'. */
+ if (current_template_parms
+ && uses_template_parms (type)
+ && uses_template_parms (current_class_type))
+ {
+ tree args = current_template_args ();
+ type = tsubst (type, args,
+ TREE_VEC_LENGTH (TREE_VEC_ELT
+ (args, 0)),
+ 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 +9096,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
ctype = TREE_OPERAND (declarator, 0);
+ t = ctype;
+ while (t != NULL_TREE)
+ {
+ if (CLASSTYPE_TEMPLATE_INFO (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 +9141,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.
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 +9159,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 +9238,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;
@@ -9201,6 +9247,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
if (constp || volatilep)
type = cp_build_type_variant (type, constp, volatilep);
+ 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
+ decl = build_decl (TYPE_DECL, declarator, type);
+
/* 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.
@@ -9212,33 +9270,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
{
/* 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);
-
- 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));
}
-#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 +9307,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;
}
@@ -9322,11 +9369,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);
@@ -9359,12 +9402,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
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 +9428,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;
@@ -9405,7 +9443,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
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);
@@ -9439,6 +9477,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
{
int publicp = 0;
+ /* 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)
{
if (ctype == NULL_TREE)
@@ -9478,15 +9525,21 @@ 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,
+ publicp = (! friendp || ! staticp);
+ 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);
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 +9550,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);
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 +9570,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 +9600,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;
@@ -9622,12 +9678,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 +9698,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,6 +9717,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
}
if (current_lang_name == lang_name_cplusplus
+ && ! processing_template_decl
&& ! (IDENTIFIER_LENGTH (original_name) == 4
&& IDENTIFIER_POINTER (original_name)[0] == 'm'
&& strcmp (IDENTIFIER_POINTER (original_name), "main") == 0)
@@ -9665,28 +9726,32 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
&& 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);
+ friendp ? 2 : 1, friendp,
+ publicp, inlinep, funcdef_flag,
+ template_count);
if (decl == NULL_TREE)
return NULL_TREE;
- if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c)
+ if (ctype == NULL_TREE && DECL_LANGUAGE (decl) != lang_c
+ && (!DECL_TEMPLATE_SPECIALIZATION (decl) ||
+ name_mangling_version < 1))
DECL_ASSEMBLER_NAME (decl) = current_namespace_id (declarator);
-
+
if (staticp == 1)
{
int illegal_static = 0;
@@ -9730,7 +9795,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 +9808,7 @@ 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);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
@@ -9804,6 +9870,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 +9897,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",
@@ -9935,7 +10006,7 @@ grokparms (first_parm, funcdef_flag)
/* 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)
{
@@ -9954,8 +10025,7 @@ grokparms (first_parm, funcdef_flag)
{
/* 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;
@@ -9963,11 +10033,10 @@ grokparms (first_parm, funcdef_flag)
if (decl != void_type_node)
{
- /* @@ 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);
@@ -9976,10 +10045,10 @@ grokparms (first_parm, funcdef_flag)
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 +10057,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);
@@ -10023,7 +10092,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 +10113,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 +10127,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 +10136,12 @@ 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
+ && 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 +10156,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 +10192,37 @@ 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 (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 +10230,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;
@@ -10168,7 +10269,7 @@ grok_ctor_properties (ctype, decl)
if (TREE_CHAIN (parmtypes) != NULL_TREE
&& TREE_CHAIN (parmtypes) == void_list_node)
{
- cp_error ("invalid constructor; you probably meant `%T (%T&)'",
+ cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
@@ -10185,6 +10286,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 +10300,7 @@ ambi_op_p (name)
}
/* An operator with this name can only be unary. */
+
static int
unary_op_p (name)
tree name;
@@ -10209,7 +10312,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 +10356,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 +10370,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));
@@ -10325,7 +10429,7 @@ grok_op_properties (decl, virtualp, friendp)
|| name == ansi_opname[(int) METHOD_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 +10443,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 +10473,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 +10490,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 +10509,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 +10554,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 +10611,9 @@ 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;
tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
switch (tag_code)
@@ -10489,18 +10635,32 @@ 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)
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)
+ {
+ 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
{
@@ -10539,6 +10699,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 +10718,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,9 +10742,6 @@ 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
@@ -10594,31 +10751,6 @@ xref_tag (code_type_node, name, binfo, globalize)
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)
- {
- 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 ();
- }
-#endif
}
if (binfo)
@@ -10644,6 +10776,25 @@ xref_tag (code_type_node, name, binfo, globalize)
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,17 +10823,17 @@ 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;
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_public_virtual_node
+ || TREE_PURPOSE (binfo) == access_default_virtual_node);
+ tree basetype = TREE_VALUE (binfo);
tree base_binfo;
GNU_xref_hier (IDENTIFIER_POINTER (name),
@@ -10691,7 +10842,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
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))
{
cp_error ("base type `%T' fails to be a struct or class type",
TREE_VALUE (binfo));
@@ -10699,7 +10853,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
}
#if 1
/* This code replaces similar code in layout_basetypes. */
- else if (TYPE_INCOMPLETE (basetype))
+ else 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;
@@ -10735,17 +10890,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))
@@ -10783,7 +10928,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 +10943,9 @@ start_enum (name)
register tree enumtype = NULL_TREE;
struct binding_level *b = inner_binding_level;
+ if (processing_template_decl && current_function_decl)
+ 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 +10954,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);
@@ -10858,29 +10993,45 @@ finish_enum (enumtype, 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 +11049,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 +11060,6 @@ finish_enum (enumtype, values)
layout_type (enumtype);
}
- if (flag_cadillac)
- cadillac_finish_enum (enumtype);
-
{
register tree tem;
@@ -10931,12 +11079,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, global_bindings_p ());
return enumtype;
}
@@ -10951,61 +11094,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,18 +11160,19 @@ 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;
@@ -11070,6 +11204,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 +11228,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;
@@ -11108,7 +11244,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
my_friendly_assert (TREE_VALUE (void_list_node) == void_type_node, 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 +11254,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);
@@ -11142,8 +11276,8 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
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)))))
+ && TYPE_IDENTIFIER (DECL_CONTEXT (decl1))
+ && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1))))
{
cp_error ("redeclaration of `%#D'", decl1);
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)))
@@ -11152,18 +11286,6 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
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);
- }
-
- 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 +11306,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 +11334,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,
@@ -11234,7 +11356,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
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 +11370,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));
- if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
- && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
- abstract_virtuals_error (decl1, 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 (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_TYPE (fntype) == void_type_node)
+ 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,14 +11429,16 @@ 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)
+ if (processing_template_decl)
+ push_template_decl (decl1);
+ else if (pre_parsed_p == 0)
{
- current_function_decl = decl1 = pushdecl (decl1);
+ decl1 = pushdecl (decl1);
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
- else
- current_function_decl = decl1;
+
+ current_function_decl = decl1;
if (DECL_INTERFACE_KNOWN (decl1))
{
@@ -11320,9 +11448,12 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
/* If this function belongs to an interface, it is public.
If it belongs to someone else's interface, it is also external.
It doesn't matter whether it's inline or not. */
- 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 +11468,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 +11483,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 +11494,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 +11512,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 +11529,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 +11558,20 @@ 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. */
+ temporary_allocation ();
+
+ if (processing_template_decl)
+ {
+ extern tree last_tree;
+ ++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 +11585,48 @@ 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;
}
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)
+store_after_parms (insns)
rtx insns;
{
- rtx last_parm_insn;
+ rtx x;
+
+ for (x = get_insns (); x; x = next_insn (x))
+ {
+ if (GET_CODE (x) == NOTE && NOTE_LINE_NUMBER (x) == NOTE_INSN_FUNCTION_BEG)
+ {
+ emit_insns_after (insns, x);
+ return;
+ }
+ }
+#if 0
+ /* This doesn't work, because the inline output routine doesn't reset
+ last_parm_insn correctly for get_first_nonparm_insn () to work. */
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));
+ emit_insns_before (insns, last_parm_insn);
+#endif
+}
+
+void
+expand_start_early_try_stmts ()
+{
+ rtx insns;
+ start_sequence ();
+ expand_start_try_stmts ();
+ insns = get_insns ();
+ end_sequence ();
+#if 1
+ emit_insns_after (insns, get_insns ());
+#else
+ store_after_parms (insns);
+#endif
}
/* Store the parameter declarations into the current function declaration.
@@ -11498,6 +11641,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,20 +11678,16 @@ 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)
cp_error ("parameter `%D' declared void", parm);
@@ -11572,13 +11712,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,26 +11750,11 @@ store_parm_decls ()
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = NULL_RTX;
- expand_function_start (fndecl, parms_have_cleanups);
-
- /* Create a binding contour which can be used to catch
- cleanup-generated temporaries. Also, if the return value needs or
- has initialization, deal with that now. */
- if (parms_have_cleanups)
- {
- pushlevel (0);
- expand_start_bindings (0);
- }
+ if (! processing_template_decl)
+ expand_function_start (fndecl, parms_have_cleanups);
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)
@@ -11637,40 +11763,45 @@ store_parm_decls ()
&& 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)
+ /* 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)
{
- rtx insns;
- start_sequence ();
+ 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));
+ }
+ }
- /* Mark the start of a stack unwinder if we need one. */
- start_eh_unwinder ();
+ /* Create a binding contour which can be used to catch
+ cleanup-generated temporaries. Also, if the return value needs or
+ has initialization, deal with that now. */
+ if (parms_have_cleanups)
+ {
+ pushlevel (0);
+ expand_start_bindings (0);
+ }
+ if (! processing_template_decl && flag_exceptions)
+ {
/* 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 +11822,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 +11846,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 +11866,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 +11889,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,204 +11905,299 @@ 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)
{
- ttype = target_type (TREE_TYPE (parmdecl));
+ 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*/)
+ {
+ 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))
+ /* 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)))
{
- 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)
+ 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 ();
}
+
+ do_pending_stack_adjust ();
+ if (cond != integer_one_node)
+ expand_end_cond ();
+ }
+
+ TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
+
+ virtual_size = c_sizeof (current_class_type);
+
+ /* At the end, call delete if that's what's requested. */
+ 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],
+ expr_tree_cons (NULL_TREE, current_class_ptr,
+ build_expr_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_ptr, 0,
+ virtual_size);
+ else
+ exprstmt = NULL_TREE;
+
+ 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 ();
}
- do_pending_stack_adjust ();
- if (cond != integer_one_node)
+ /* 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);
+
+ 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);
+ }
+
+ insns = get_insns ();
+ end_sequence ();
+
+ 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);
+
+ emit_insns_after (insns, last_parm_insn);
+
+ 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. */
- 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;
+ if (DECL_CONSTRUCTOR_P (current_function_decl))
+ {
+ end_protect_partials ();
+ expand_label (ctor_label);
+ ctor_label = NULL_TREE;
- 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 ();
+ if (call_poplevel)
+ {
+ decls = getdecls ();
+ expand_end_bindings (decls, decls != NULL_TREE, 0);
+ poplevel (decls != NULL_TREE, 0, 0);
+ }
+ c_expand_return (current_class_ptr);
+ }
+ 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);
+
+ current_function_assigns_this = 0;
+ current_function_just_assigned_this = 0;
+ base_init_expr = NULL_TREE;
}
+ else if (DECL_CONSTRUCTOR_P (fndecl))
+ {
+ 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;
- /* End of destructor. */
- expand_end_bindings (NULL_TREE, getdecls() != NULL_TREE, 0);
- poplevel (2, 0, 0); /* XXX change to 1 */
+ DECL_RETURNS_FIRST_ARG (fndecl) = 1;
- /* Back to the top of destructor. */
- /* Dont execute destructor code if `this' is NULL. */
+ 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));
+ }
- start_sequence ();
+ CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
- /* 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);
- }
+ start_sequence ();
- insns = get_insns ();
- end_sequence ();
+ if (flag_this_is_variable > 0)
+ {
+ expand_start_cond (cond, 0);
+ expand_expr_stmt (thenclause);
+ expand_end_cond ();
+ }
- 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);
+ /* 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;
+ }
- 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. */
+ /* This is where the body of the constructor begins. */
+
+ emit_insns_after (insns, last_parm_cleanup_insn);
- if (DECL_CONSTRUCTOR_P (current_function_decl))
- {
end_protect_partials ();
+
+ /* This is where the body of the constructor ends. */
expand_label (ctor_label);
ctor_label = NULL_TREE;
@@ -11969,176 +12205,89 @@ finish_function (lineno, call_poplevel, nested)
{
decls = getdecls ();
expand_end_bindings (decls, decls != NULL_TREE, 0);
- poplevel (decls != NULL_TREE, 0, 0);
+ poplevel (decls != NULL_TREE, 1, 0);
}
- c_expand_return (current_class_decl);
- }
- 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);
- 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;
+ c_expand_return (current_class_ptr);
- DECL_RETURNS_FIRST_ARG (fndecl) = 1;
-
- 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;
}
-
- CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
-
- start_sequence ();
-
- if (flag_this_is_variable > 0)
+ else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
+ && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
+ && DECL_CONTEXT (fndecl) == NULL_TREE)
{
- expand_start_cond (cond, 0);
- expand_expr_stmt (thenclause);
- expand_end_cond ();
+ /* Make it so that `main' always returns 0 by default. */
+#ifdef VMS
+ c_expand_return (integer_one_node);
+#else
+ 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 0
- if (DECL_NAME (fndecl) == NULL_TREE
- && TREE_CHAIN (DECL_ARGUMENTS (fndecl)) != NULL_TREE)
- build_default_constructor (fndecl);
-#endif
+ if (flag_exceptions)
+ expand_exception_blocks ();
- /* Emit insns from `emit_base_init' which sets up virtual
- function table pointer(s). */
- if (base_init_expr)
+ /* 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)
{
- expand_expr_stmt (base_init_expr);
- base_init_expr = NULL_TREE;
+ 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);
}
- insns = get_insns ();
- end_sequence ();
-
- /* 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.
-
- 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);
+ 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_insns_after (insns, last_parm_insn);
+ /* Emit label at beginning of cleanup code for parameters. */
+ emit_label (cleanup_label);
+ }
- end_protect_partials ();
+ /* 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);
- /* This is where the body of the constructor ends. */
- expand_label (ctor_label);
- ctor_label = NULL_TREE;
-
- if (call_poplevel)
+ /* 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)
{
- decls = getdecls ();
- expand_end_bindings (decls, decls != NULL_TREE, 0);
- poplevel (decls != NULL_TREE, 1, 0);
+ /* 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);
}
- c_expand_return (current_class_decl);
-
- current_function_assigns_this = 0;
- current_function_just_assigned_this = 0;
+ /* Generate rtl for function exit. */
+ expand_function_end (input_filename, lineno, 1);
}
- 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. */
-#ifdef VMS
- c_expand_return (integer_one_node);
-#else
- 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 ();
-
- /* 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 (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)
- /* 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);
-
- /* 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);
-
- 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
@@ -12161,79 +12310,101 @@ 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)
+ {
+ /* 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);
+ /* Run the optimizers and output the assembler code for this
+ function. */
- 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 (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);
+ 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
+ && TYPE_MAIN_VARIANT (TREE_TYPE (fntype)) != void_type_node)
+ {
+ /* 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 +12420,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 +12447,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. */
@@ -12295,11 +12468,7 @@ 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))
{
@@ -12317,11 +12486,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 && ! current_function_decl)
+ 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
@@ -12423,8 +12589,7 @@ finish_method (decl)
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);
@@ -12479,7 +12644,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 +12655,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 +12687,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 +12728,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 +12752,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 +12763,16 @@ 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));
+ /* 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 +12800,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
@@ -12630,7 +12809,7 @@ finish_stmt ()
(TREE_TYPE (decl)) to ARGTYPES, as doing so will corrupt the types of
other decls. Either pass the addresses of local variables or NULL. */
-void
+static void
revert_static_member_fn (decl, fn, argtypes)
tree *decl, *fn, *argtypes;
{
@@ -12679,18 +12858,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 +12898,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 +12928,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 +12940,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,80 +12950,20 @@ 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;
+int
+in_function_p ()
{
- 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;
+ return function_depth != 0;
}
+/* FSF LOCAL dje prefix attributes */
/* 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.
diff --git a/gnu/usr.bin/gcc/cp/decl.h b/gnu/usr.bin/gcc/cp/decl.h
index 0824c13d673..f55dca55ea7 100644
--- a/gnu/usr.bin/gcc/cp/decl.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/cp/errfn.c b/gnu/usr.bin/gcc/cp/errfn.c
index f36b0e1e1f9..b5ab8f7b676 100644
--- a/gnu/usr.bin/gcc/cp/errfn.c
+++ b/gnu/usr.bin/gcc/cp/errfn.c
@@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "tree.h"
+#include <stdio.h>
#include <ctype.h>
/* cp_printer is the type of a function which converts an argument into
@@ -43,11 +44,12 @@ 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]
+#define NARGS 5
+#define arglist a1, a2, a3, a4, a5
+#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4, a5;
+#define ARGSINIT \
+ args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4; args[4] = a5;
+#define ARGSLIST args[0], args[1], args[2], args[3], args[4]
static void
cp_thing (errfn, atarg1, format, arglist)
@@ -195,8 +197,7 @@ cp_sprintf (format, arglist)
char *format;
arglist_dcl
{
- extern errorfn sprintf;
- cp_thing (sprintf, 0, format, arglist);
+ cp_thing ((errorfn *) sprintf, 0, format, arglist);
}
void
diff --git a/gnu/usr.bin/gcc/cp/error.c b/gnu/usr.bin/gcc/cp/error.c
index 4eb196e3add..d6c6586b9dd 100644
--- a/gnu/usr.bin/gcc/cp/error.c
+++ b/gnu/usr.bin/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, 1994, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "cp-tree.h"
#include "obstack.h"
@@ -34,6 +35,7 @@ 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
@@ -46,7 +48,7 @@ cp_printer * cp_printers[256] =
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
_, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
- P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
+ P, Q, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
};
@@ -56,6 +58,7 @@ cp_printer * cp_printers[256] =
#undef L
#undef O
#undef P
+#undef Q
#undef T
#undef V
#undef _
@@ -83,10 +86,24 @@ static char *scratch_firstobj;
# 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_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));
+static void dump_type_prefix PROTO((tree, int));
+static void dump_type_suffix PROTO((tree, 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 +112,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,7 +134,8 @@ 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)
tree t;
@@ -150,7 +166,7 @@ dump_type (t, v)
if (TREE_PURPOSE (t) && v)
{
OB_PUTS (" = ");
- dump_expr (TREE_PURPOSE (t));
+ dump_expr (TREE_PURPOSE (t), 0);
}
if (TREE_CHAIN (t))
{
@@ -179,7 +195,7 @@ 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_readonly_or_volatile (t, after);
dump_type (SIGNATURE_TYPE (t), v);
if (IS_SIGNATURE_POINTER (t))
OB_PUTC ('*');
@@ -194,6 +210,11 @@ dump_type (t, v)
dump_decl (t, v);
break;
+ case COMPLEX_TYPE:
+ OB_PUTS ("complex ");
+ dump_type (TREE_TYPE (t), v);
+ break;
+
case INTEGER_TYPE:
if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t))
OB_PUTS ("unsigned ");
@@ -209,12 +230,11 @@ dump_type (t, v)
break;
case TEMPLATE_TYPE_PARM:
- OB_PUTID (TYPE_IDENTIFIER (t));
- break;
-
- case UNINSTANTIATED_P_TYPE:
- OB_PUTID (DECL_NAME (UPT_TEMPLATE (t)));
- OB_PUTS ("<...>");
+ 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
@@ -230,6 +250,13 @@ dump_type (t, v)
dump_type_suffix (t, v);
break;
+ case TYPENAME_TYPE:
+ OB_PUTS ("typename ");
+ dump_type (TYPE_CONTEXT (t), 0);
+ OB_PUTS ("::");
+ OB_PUTID (TYPE_IDENTIFIER (t));
+ break;
+
default:
sorry ("`%s' not supported by dump_type",
tree_code_name[(int) TREE_CODE (t)]);
@@ -252,7 +279,8 @@ aggr_variety (t)
return "struct";
}
-/* Print out a class declaration, in the form `class foo'. */
+/* Print out a class declaration, in the form `class foo'. */
+
static void
dump_aggr_type (t, v)
tree t;
@@ -422,10 +450,11 @@ dump_type_prefix (t, v)
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:
dump_type (t, v);
break;
@@ -478,7 +507,16 @@ dump_type_suffix (t, v)
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);
break;
@@ -494,10 +532,11 @@ dump_type_suffix (t, v)
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 +547,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 +578,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;
{
@@ -576,12 +616,9 @@ 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);
+ dump_type (TREE_TYPE (t), v);
break;
}
}
@@ -646,7 +683,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 +714,55 @@ 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)
+ {
+ OB_PUTS ("class ");
+ OB_PUTID (DECL_NAME (arg));
+ }
+ else
+ dump_decl (arg, 1);
- OB_PUTC2 (',', ' ');
+ if (defval)
+ {
+ OB_PUTS (" = ");
+ dump_decl (defval, 1);
+ }
+
+ 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:
@@ -734,10 +781,21 @@ dump_decl (t, v)
break;
case CONST_DECL:
- if (NEXT_CODE (t) == ENUMERAL_TYPE)
+ if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
+ || (DECL_INITIAL (t) &&
+ TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_CONST_PARM))
goto general;
- else
+ 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 +813,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);
@@ -825,6 +890,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 +924,77 @@ dump_function_name (t)
}
else
dump_decl (name, 0);
+
+ if ((DECL_TEMPLATE_SPECIALIZATION (t) || DECL_IMPLICIT_INSTANTIATION (t))
+ && (DECL_CLASS_CONTEXT (t) == NULL_TREE || is_member_template (t)))
+ {
+ tree args = DECL_TEMPLATE_INFO (t)
+ ? DECL_TI_ARGS (t) : NULL_TREE;
+
+ 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')
+ 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, 0);
+
+ 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')
+ 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)
{
@@ -908,6 +1040,7 @@ dump_char (c)
}
/* Print out a list of initializers (subr of dump_expr) */
+
static void
dump_expr_list (l)
tree l;
@@ -922,6 +1055,7 @@ dump_expr_list (l)
}
/* Print out an expression */
+
static void
dump_expr (t, nop)
tree t;
@@ -934,6 +1068,7 @@ dump_expr (t, nop)
case FIELD_DECL:
case CONST_DECL:
case FUNCTION_DECL:
+ case TEMPLATE_DECL:
dump_decl (t, -1);
break;
@@ -950,12 +1085,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)
{
@@ -1047,7 +1182,8 @@ dump_expr (t, nop)
case NEW_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 +1195,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,18 +1212,12 @@ 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);
- break;
-
case TARGET_EXPR:
/* Note that this only works for G++ target exprs. If somebody
builds a general TARGET_EXPR, there's no way to represent that
@@ -1188,7 +1318,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 +1346,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 +1371,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 +1424,90 @@ 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_CONST_PARM:
+ {
+ int l = current_template_parms ?
+ list_length (current_template_parms) : 0;
+
+ if (l >= TEMPLATE_CONST_LEVEL (t))
+ {
+ int i;
+ tree parms = current_template_parms;
+ tree r;
+
+ for (i = 0; i < l - TEMPLATE_CONST_LEVEL (t); ++i)
+ {
+ parms = TREE_CHAIN (parms);
+ my_friendly_assert (parms != NULL_TREE, 0);
+ }
+
+ r = TREE_VEC_ELT (TREE_VALUE (parms),
+ TEMPLATE_CONST_IDX (t));
+ dump_decl (TREE_VALUE (r), -1);
+ }
+ else
+ {
+ OB_PUTS ("<tparm ");
+ OB_PUTI (TEMPLATE_CONST_IDX (t));
+ OB_PUTS (">");
+ }
+ }
+ 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 SIZEOF_EXPR:
+ OB_PUTS ("sizeof (");
+ 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 TREE_LIST:
if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
{
@@ -1311,8 +1558,8 @@ 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);
@@ -1321,6 +1568,7 @@ fndecl_as_string (cname, fndecl, print_ret_type_p)
/* Same, but handtype a _TYPE.
Called from convert_to_reference, mangle_class_name_for_template,
build_unary_op, and GNU_xref_decl. */
+
char *
type_as_string (typ, v)
tree typ;
@@ -1351,6 +1599,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,6 +1614,41 @@ 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_CONTEXT (decl)
+ && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
+ {
+ 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;
@@ -1372,7 +1656,7 @@ cp_file_of (t)
if (TREE_CODE (t) == PARM_DECL)
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);
}
@@ -1388,12 +1672,7 @@ cp_line_of (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);
@@ -1431,6 +1710,7 @@ 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;
@@ -1457,14 +1737,42 @@ op_as_string (p, v)
}
char *
+assop_as_string (p, v)
+ enum tree_code p;
+ int v;
+{
+ 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 "";
- return type_as_string (p, v);
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (p))) == 't')
+ 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 *
diff --git a/gnu/usr.bin/gcc/cp/except.c b/gnu/usr.bin/gcc/cp/except.c
index 51577f85afa..a1a96f28337 100644
--- a/gnu/usr.bin/gcc/cp/except.c
+++ b/gnu/usr.bin/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-96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann <tiemann@cygnus.com>
Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
initial re-implementation courtesy Tad Hunt.
@@ -22,82 +22,38 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* High-level class interface. */
-
#include "config.h"
+#include <stdio.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"
-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 () */
+/* Used to cache a call to __builtin_return_address. */
static tree BuiltinReturnAddress;
-
-#include <stdio.h>
-
-/* XXX - Tad: for EH */
-/* output an exception table entry */
+static void easy_expand_asm PROTO((char *));
+static void push_eh_cleanup PROTO((void));
+static void do_unwind PROTO((rtx));
+static rtx do_function_call PROTO((tree, tree, tree));
+static tree build_eh_type_type PROTO((tree));
+static tree build_eh_type PROTO((tree));
+static void expand_end_eh_spec PROTO((tree));
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;
{
@@ -106,7 +62,7 @@ easy_expand_asm (str)
#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
@@ -115,8 +71,8 @@ easy_expand_asm (str)
#ifdef EXCEPT_SECTION_ASM_OP
typedef struct {
- void *start_protect;
- void *end_protect;
+ void *start_region;
+ void *end_region;
void *exception_handler;
} exception_table;
#endif /* EXCEPT_SECTION_ASM_OP */
@@ -145,45 +101,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 <stdio.h> */
-#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 +114,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
+ is the 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 +151,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 +164,25 @@ 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", "unexpected", "set_terminate", and
+ "set_unexpected" after default_conversion. (lib-except.c) */
+static tree Terminate, Unexpected, SetTerminate, SetUnexpected, 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 ()". */
+/* 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;
-};
/* ========================================================================= */
@@ -314,225 +193,16 @@ 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;
-
-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;
-/* ========================================================================= */
+static tree saved_pc;
-/* 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));
+extern int throw_used;
+extern rtx catch_clauses;
+/* ========================================================================= */
-
-/* All my cheesy stack/queue/misc data structure handling routines
-
- ========================================================================= */
-
-static void
-push_label_entry (labelstack, label)
- struct labelNode **labelstack;
- rtx label;
-{
- struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));
-
- newnode->label = label;
- newnode->chain = *labelstack;
- *labelstack = newnode;
-}
-
-static rtx
-pop_label_entry (labelstack)
- struct labelNode **labelstack;
-{
- rtx label;
- struct labelNode *tempnode;
-
- if (! *labelstack) return NULL_RTX;
-
- tempnode = *labelstack;
- label = tempnode->label;
- *labelstack = (*labelstack)->chain;
- free (tempnode);
-
- return label;
-}
-
-static rtx
-top_label_entry (labelstack)
- struct labelNode **labelstack;
-{
- if (! *labelstack) return NULL_RTX;
-
- return (*labelstack)->label;
-}
-
-/* Push to permanent obstack for rtl generation.
- One level only! */
-static struct obstack *saved_rtl_obstack;
-void
-push_rtl_perm ()
-{
- extern struct obstack permanent_obstack;
- extern struct obstack *rtl_obstack;
-
- saved_rtl_obstack = rtl_obstack;
- rtl_obstack = &permanent_obstack;
-}
-
-/* Pop back to normal rtl handling. */
-static void
-pop_rtl_from_perm ()
-{
- extern struct obstack permanent_obstack;
- extern struct obstack *rtl_obstack;
-
- rtl_obstack = saved_rtl_obstack;
-}
+/* Cheesyness to save some typing. Returns the return value rtx. */
static rtx
-push_eh_entry (stack)
- struct ehStack *stack;
-{
- struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
- struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
-
- if (stack == NULL) {
- free (node);
- free (entry);
- return NULL_RTX;
- }
-
- /* 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 ();
-
- LABEL_PRESERVE_P (entry->start_label) = 1;
- LABEL_PRESERVE_P (entry->end_label) = 1;
- LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
-
- entry->finalization = NULL_TREE;
- entry->context = current_function_decl;
-
- node->entry = entry;
- node->chain = stack->top;
- stack->top = node;
-
- enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
-
- return entry->start_label;
-}
-
-static struct ehEntry *
-pop_eh_entry (stack)
- struct ehStack *stack;
-{
- struct ehNode *tempnode;
- struct ehEntry *tempentry;
-
- if (stack && (tempnode = stack->top)) {
- tempentry = tempnode->entry;
- stack->top = stack->top->chain;
- free (tempnode);
-
- return tempentry;
- }
-
- return NULL;
-}
-
-static struct ehEntry *
-copy_eh_entry (entry)
- struct ehEntry *entry;
-{
- struct ehEntry *newentry;
-
- newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
- memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry));
-
- return newentry;
-}
-
-static void
-enqueue_eh_entry (queue, entry)
- struct ehQueue *queue;
- struct ehEntry *entry;
-{
- struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
-
- node->entry = entry;
- node->chain = NULL;
-
- if (queue->head == NULL)
- {
- queue->head = node;
- }
- else
- {
- queue->tail->chain = node;
- }
- queue->tail = node;
-}
-
-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;
-}
-
-static void
-new_eh_queue (queue)
- struct ehQueue *queue;
-{
- queue->head = queue->tail = NULL;
-}
-
-static void
-new_eh_stack (stack)
- struct ehStack *stack;
-{
- stack->top = NULL;
-}
-
-/* cheesyness to save some typing. returns the return value rtx */
-rtx
do_function_call (func, params, return_type)
tree func, params, return_type;
{
@@ -544,49 +214,17 @@ do_function_call (func, params, return_type)
return NULL_RTX;
}
-static void
-expand_internal_throw (pc)
- rtx pc;
-{
- tree params;
-
- emit_move_insn (DECL_RTL (saved_pc), pc);
-#ifdef JUMP_TO_THROW
- emit_indirect_jump (gen_rtx (SYMBOL_REF, Pmode, "__throw"));
-#else
- do_function_call (Throw, NULL_TREE, NULL_TREE);
-#endif
- throw_used = 1;
-}
-
/* ========================================================================= */
-void
-lang_interim_eh (finalization)
- tree finalization;
-{
- if (finalization)
- end_protect (finalization);
- else
- start_protect ();
-}
-
-extern tree auto_function PROTO((tree, tree, enum built_in_function));
-
/* 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
- - Initializing the ehqueue
- - Initializing the eh_table_output_queue
- - Initializing the ehstack
-*/
+ - Setting up all the function call trees. */
void
init_exception_processing ()
{
- extern tree define_function ();
tree unexpected_fndecl, terminate_fndecl;
tree set_unexpected_fndecl, set_terminate_fndecl;
tree catch_match_fndecl;
@@ -595,20 +233,19 @@ init_exception_processing ()
tree declspecs;
tree d;
+ /* void vtype () */
+ tree vtype = build_function_type (void_type_node, void_list_node);
+
/* void (*)() */
- tree PFV = build_pointer_type (build_function_type
- (void_type_node, void_list_node));
+ tree PFV = build_pointer_type (vtype);
- /* arg list for the build_function_type call for set_terminate () and
- set_unexpected () */
+ /* Arg list for the build_function_type call for set_terminate and
+ set_unexpected. */
tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
/* void (*pfvtype (void (*) ()))() */
tree pfvtype = build_function_type (PFV, pfvlist);
- /* void vtype () */
- tree vtype = build_function_type (void_type_node, void_list_node);
-
set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
pfvtype, NOT_BUILT_IN);
set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
@@ -617,47 +254,32 @@ init_exception_processing ()
vtype, NOT_BUILT_IN);
terminate_fndecl = auto_function (get_identifier ("terminate"),
vtype, NOT_BUILT_IN);
-
- interim_eh_hook = lang_interim_eh;
+ TREE_THIS_VOLATILE (terminate_fndecl) = 1;
push_lang_context (lang_name_c);
- catch_match_fndecl =
- define_function (flag_rtti
- ? "__throw_type_match_rtti"
- : "__throw_type_match",
- build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node)))),
- NOT_BUILT_IN,
- pushdecl,
- 0);
- find_first_exception_match_fndecl =
- define_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,
- pushdecl,
- 0);
- unwind_fndecl =
- define_function ("__unwind_function",
- build_function_type (void_type_node,
- tree_cons (NULL_TREE, ptr_type_node,
- void_list_node)),
- NOT_BUILT_IN,
- pushdecl,
- 0);
- throw_fndecl =
- define_function ("__throw",
- build_function_type (void_type_node, void_list_node),
- NOT_BUILT_IN,
- pushdecl,
- 0);
- DECL_EXTERNAL (throw_fndecl) = 0;
- TREE_PUBLIC (throw_fndecl) = 0;
+ catch_match_fndecl
+ = builtin_function (flag_rtti
+ ? "__throw_type_match_rtti"
+ : "__throw_type_match",
+ build_function_type (ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ void_list_node)))),
+ NOT_BUILT_IN, NULL_PTR);
+ find_first_exception_match_fndecl
+ = 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_fndecl
+ = 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);
Unexpected = default_conversion (unexpected_fndecl);
Terminate = default_conversion (terminate_fndecl);
@@ -666,183 +288,149 @@ init_exception_processing ()
CatchMatch = default_conversion (catch_match_fndecl);
FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
Unwind = default_conversion (unwind_fndecl);
- Throw = default_conversion (throw_fndecl);
BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
pop_lang_context ();
- new_eh_queue (&ehqueue);
- new_eh_queue (&eh_table_output_queue);
- new_eh_stack (&ehstack);
-
- declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
- d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc"));
- d = start_decl (d, declspecs, 0, NULL_TREE);
- DECL_COMMON (d) = 1;
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
- saved_pc = lookup_name (get_identifier ("__eh_pc"), 0);
-
- declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
- d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type"));
- d = start_decl (d, declspecs, 0, NULL_TREE);
- DECL_COMMON (d) = 1;
+ d = build_decl (VAR_DECL, get_identifier ("__eh_pc"), ptr_type_node);
+ TREE_PUBLIC (d) = 1;
+ DECL_EXTERNAL (d) = 1;
+ DECL_ARTIFICIAL (d) = 1;
cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
- saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0);
+ saved_pc = d;
- declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
- d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value"));
- d = start_decl (d, declspecs, 0, NULL_TREE);
- DECL_COMMON (d) = 1;
- cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
- saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);
+ /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
+ be protected with __terminate. */
+ protect_cleanup_actions_with_terminate = 1;
}
-/* call this to begin a block of unwind protection (ie: when an object is
- constructed) */
-void
-start_protect ()
-{
- if (! doing_eh (0))
- return;
+/* Retrieve a pointer to the cp_eh_info node for the current exception. */
- emit_label (push_eh_entry (&ehstack));
-}
-
-/* call this to end a block of unwind protection. the finalization tree is
- the finalization which needs to be run in order to cleanly unwind through
- this level of protection. (ie: call this when a scope is exited)*/
-void
-end_protect (finalization)
- tree finalization;
+static tree
+call_eh_info ()
{
- struct ehEntry *entry;
-
- if (! doing_eh (0))
- return;
-
- entry = pop_eh_entry (&ehstack);
-
- emit_label (entry->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;
+ tree fn;
- enqueue_eh_entry (&ehqueue, entry);
+ fn = get_identifier ("__cp_exception_info");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ tree t, fields[6];
+
+ /* Declare cp_eh_info * __cp_exception_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. */
+ t = make_lang_type (RECORD_TYPE);
+ fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"),
+ ptr_type_node);
+ fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
+ ptr_type_node);
+ fields[2] = 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[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"),
+ boolean_type_node);
+ fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
+ build_pointer_type (t));
+ fields[5] = 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, 5, 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);
}
-/* call this on start of a try block. */
-void
-expand_start_try_stmts ()
-{
- if (! doing_eh (1))
- return;
+/* Retrieve a pointer to the cp_eh_info node for the current exception
+ and save it in the current binding level. */
- start_protect ();
-}
-
-void
-expand_end_try_stmts ()
+static void
+push_eh_info ()
{
- end_protect (integer_zero_node);
+ 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);
}
+/* Returns a reference to the cp_eh_info node for the current exception. */
-/* call this to start processing of all the catch blocks. */
-void
-expand_start_all_catch ()
+static tree
+get_eh_info ()
{
- struct ehEntry *entry;
- rtx label;
-
- if (! doing_eh (1))
- return;
-
- emit_line_note (input_filename, lineno);
- label = gen_label_rtx ();
+ /* 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);
+}
- /* 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 ());
+/* Returns a reference to the current exception object. */
- push_label_entry (&caught_return_label_stack, label);
+static tree
+get_eh_value ()
+{
+ return build_component_ref (get_eh_info (), get_identifier ("value"),
+ NULL_TREE, 0);
+}
- /* 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 ();
+/* Returns a reference to the current exception type. */
- while (1)
- {
- 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);
- }
+static tree
+get_eh_type ()
+{
+ return build_component_ref (get_eh_info (), get_identifier ("type"),
+ NULL_TREE, 0);
}
-/* call this to end processing of all the catch blocks. */
-void
-expand_end_all_catch ()
-{
- rtx new_catch_clause;
+/* Returns a reference to whether or not the current exception
+ has been caught. */
- if (! doing_eh (1))
- return;
-
- /* 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)));
+static tree
+get_eh_caught ()
+{
+ return build_component_ref (get_eh_info (), get_identifier ("caught"),
+ NULL_TREE, 0);
+}
- /* 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);
+/* Returns a reference to whether or not the current exception
+ has been caught. */
- /* 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. */
+static tree
+get_eh_handlers ()
+{
+ return build_component_ref (get_eh_info (), get_identifier ("handlers"),
+ NULL_TREE, 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;
@@ -853,11 +441,11 @@ build_eh_type_type (type)
if (type == error_mark_node)
return error_mark_node;
- /* peel back references, so they match. */
+ /* peel back references, so they match. */
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- /* Peel off cv qualifiers. */
+ /* Peel off cv qualifiers. */
type = TYPE_MAIN_VARIANT (type);
if (flag_rtti)
@@ -872,6 +460,7 @@ build_eh_type_type (type)
/* 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;
@@ -884,61 +473,151 @@ build_eh_type (exp)
return build_eh_type_type (TREE_TYPE (exp));
}
+/* Build up a call to __cp_pop_exception, to destroy the exception object
+ for the current catch block. HANDLER is either true or false, telling
+ the library whether or not it is being called from an exception handler;
+ if it is, it avoids destroying the object on rethrow. */
+
+static tree
+do_pop_exception (handler)
+ tree handler;
+{
+ tree fn, cleanup;
+ fn = get_identifier ("__cp_pop_exception");
+ if (IDENTIFIER_GLOBAL_VALUE (fn))
+ fn = IDENTIFIER_GLOBAL_VALUE (fn);
+ else
+ {
+ /* Declare void __cp_pop_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, tree_cons
+ (NULL_TREE, ptr_type_node, tree_cons
+ (NULL_TREE, boolean_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 ();
+ }
+
+ /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
+ cleanup = lookup_name (get_identifier ("__exception_info"), 0);
+ cleanup = build_function_call (fn, expr_tree_cons
+ (NULL_TREE, cleanup, expr_tree_cons
+ (NULL_TREE, handler, NULL_TREE)));
+ return cleanup;
+}
+
+/* This routine creates the cleanup for the current exception. */
+
+static void
+push_eh_cleanup ()
+{
+ /* All cleanups must last longer than normal. */
+ int yes = suspend_momentary ();
+ expand_decl_cleanup_no_eh (NULL_TREE, do_pop_exception (boolean_false_node));
+ resume_momentary (yes);
+
+ expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* We don't destroy the exception object on rethrow, so we can't use
+ the normal cleanup mechanism for it. */
+ expand_eh_region_start ();
+}
+
/* 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)
tree declspecs, declarator;
{
rtx false_label_rtx;
- rtx protect_label_rtx;
tree decl = NULL_TREE;
tree init;
+ 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;
+ }
+
if (! doing_eh (1))
return;
- /* Create a binding level for the parm. */
+ /* If we are not doing setjmp/longjmp EH, because we are reordered
+ out of line, we arrange to rethrow in the outer context so as to
+ skip through the terminate region we are nested in, should we
+ encounter an exception in the catch handler. We also need to do
+ this because we are not physically within the try block, if any,
+ that contains this catch block.
+
+ Matches the end in expand_end_catch_block. */
+ if (! exceptions_via_longjmp)
+ expand_eh_region_start ();
+
+ /* 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);
+ push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
+
+ emit_line_note (input_filename, lineno);
+
+ push_eh_info ();
if (declspecs)
{
+ decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
+
+ if (decl == NULL_TREE)
+ error ("invalid catch parameter");
+ }
+
+ if (decl)
+ {
tree exp;
rtx call_rtx, return_value_rtx;
tree init_type;
- decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1,
- NULL_TREE, NULL_TREE);
-
- if (decl == NULL_TREE)
- {
- error ("invalid catch parameter");
- return;
- }
+ /* Make sure we mark the catch param as used, otherwise we'll get
+ a warning about an unused ((anonymous)). */
+ TREE_USED (decl) = 1;
- /* Figure out the type that the initializer is. */
+ /* 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,
+ exp = get_eh_value ();
+ exp = expr_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)));
+ 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);
assemble_external (TREE_OPERAND (CatchMatch, 0));
@@ -952,152 +631,136 @@ expand_start_catch_block (declspecs, declarator)
/* if it returned FALSE, jump over the catch block, else fall into it */
emit_jump_insn (gen_beq (false_label_rtx));
- init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
+ push_eh_cleanup ();
+
+ /* Create a binding level for the parm. */
+ pushlevel (0);
+ expand_start_bindings (0);
+
+ init = convert_from_reference (make_tree (init_type, call_rtx));
+
+ /* If the constructor for the catch parm exits via an exception, we
+ must call terminate. See eh23.C. */
+ if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ {
+ /* Generate the copy constructor call directly so we can wrap it.
+ See also expand_default_init. */
+ init = ocp_convert (TREE_TYPE (decl), init,
+ CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
+ init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
+ TerminateFunctionCall);
+ }
- /* 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);
+/* 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. */
- expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
+void
+expand_end_catch_block ()
+{
+ if (! doing_eh (1))
+ return;
- /* 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));
+ /* Cleanup the EH parameter. */
+ expand_end_bindings (getdecls (), kept_level_p (), 0);
+ poplevel (kept_level_p (), 1, 0);
+
+ /* Matches push_eh_cleanup. */
+ expand_eh_region_end (do_pop_exception (boolean_true_node));
- /* leftover try block, opps. */
- if (entry->finalization == integer_zero_node)
- abort ();
+ /* Cleanup the EH object. */
+ expand_end_bindings (getdecls (), kept_level_p (), 0);
+ poplevel (kept_level_p (), 1, 0);
- free (entry);
- }
+ if (! exceptions_via_longjmp)
+ {
+ /* If we are not doing setjmp/longjmp EH, we need an extra
+ region around the whole catch block to skip through the
+ terminate region we are nested in. */
- return first_label;
-}
+ tree t = make_node (RTL_EXPR);
+ TREE_TYPE (t) = void_type_node;
+ RTL_EXPR_RTL (t) = const0_rtx;
+ TREE_SIDE_EFFECTS (t) = 1;
+ do_pending_stack_adjust ();
+ start_sequence_for_rtl_expr (t);
-/* 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;
+ expand_internal_throw (outer_context_label_stack->u.rlabel);
- if (! doing_eh (1))
- return;
+ do_pending_stack_adjust ();
+ RTL_EXPR_SEQUENCE (t) = get_insns ();
+ end_sequence ();
- /* fall to outside the try statement when done executing handler and
+ /* For the rethrow region. */
+ expand_eh_region_end (t);
+ }
+
+ /* 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. */
+ expand_leftover_cleanups ();
+
+ /* 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));
-
- /* 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;
-
- LABEL_PRESERVE_P (entry.start_label) = 1;
- LABEL_PRESERVE_P (entry.end_label) = 1;
- LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
-
- /* 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));
}
-/* unwind the stack. */
+/* unwind the stack. */
+
static void
do_unwind (inner_throw_label)
rtx inner_throw_label;
{
-#if defined(SPARC_STACK_ALIGN) /* was sparc */
+#if defined (SPARC_STACK_ALIGN) /* was sparc */
+ /* This doesn't work for the flat model sparc, nor does it need to
+ as the default unwinder is only used to unwind non-flat frames. */
tree fcall;
tree params;
- rtx return_val_rtx;
+ rtx next_pc;
rtx temp;
- /* call to __builtin_return_address () */
- params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+ /* Call to __builtin_return_address. */
+ params = expr_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);
+ next_pc = 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));
+ emit_move_insn (next_pc, plus_constant (temp, -8));
+ emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
easy_expand_asm ("ret");
easy_expand_asm ("restore");
emit_barrier ();
#endif
-#if defined(ARM_FRAME_RTX) /* was __arm */
+#if defined (ARM_FRAME_RTX) /* was __arm */
if (flag_omit_frame_pointer)
sorry ("this implementation of exception handling requires a frame pointer");
@@ -1106,7 +769,7 @@ do_unwind (inner_throw_label)
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 */
+#if defined (TARGET_88000) /* was m88k */
rtx temp_frame = frame_pointer_rtx;
temp_frame = memory_address (Pmode, temp_frame);
@@ -1129,21 +792,22 @@ do_unwind (inner_throw_label)
(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
#endif
#endif
-#if !defined(TARGET_88000) && !defined(ARM_FRAME_RTX) && !defined(SPARC_STACK_ALIGN)
+#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
tree fcall;
tree params;
- rtx return_val_rtx;
+ rtx next_pc;
- /* 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. */
+ /* I would like to do this here, but the move below doesn't seem to work. */
+ /* Call to __builtin_return_address. */
+ params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+ fcall = build_function_call (BuiltinReturnAddress, params);
+ next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
+
+ emit_move_insn (next_pc, inner_throw_label);
+ /* So, for now, just pass throw label to stack unwinder. */
#endif
- params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
+ params = expr_tree_cons (NULL_TREE, make_tree (ptr_type_node,
inner_throw_label), NULL_TREE);
do_function_call (Unwind, params, NULL_TREE);
@@ -1153,7 +817,7 @@ do_unwind (inner_throw_label)
}
-/* is called from expand_exception_blocks () to generate the code in a 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.
expands "throw" as the following pseudo code:
@@ -1166,22 +830,23 @@ do_unwind (inner_throw_label)
gotta_rethrow_it:
saved_pc = __builtin_return_address (0);
pop_to_previous_level ();
- goto throw;
+ goto throw; */
- */
void
expand_builtin_throw ()
{
+#ifndef DWARF2_UNWIND_INFO
tree fcall;
tree params;
- rtx return_val_rtx;
+ rtx handler;
+ rtx saved_pcnthrow;
+ rtx next_pc;
rtx gotta_rethrow_it;
rtx gotta_call_terminate;
- rtx unwind_and_throw;
- rtx goto_unwind_and_throw;
+ rtx after_unwind;
rtx top_of_loop;
- rtx unwind_first;
tree t;
+ rtx x;
if (! doing_eh (0))
return;
@@ -1190,10 +855,14 @@ expand_builtin_throw ()
return;
params = void_list_node;
- t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE);
- start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
- void_list_node),
- t, NULL_TREE, NULL_TREE, 0);
+ t = make_call_declarator (get_identifier ("__throw"), params, NULL_TREE,
+ NULL_TREE);
+ start_function (decl_tree_cons (NULL_TREE,
+ get_identifier ("void"),
+ decl_tree_cons (NULL_TREE,
+ get_identifier ("static"),
+ NULL_TREE)),
+ t, NULL_TREE, 0);
store_parm_decls ();
pushlevel (0);
clear_last_expr ();
@@ -1202,76 +871,119 @@ expand_builtin_throw ()
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);
+ /* These two can be frontend specific. If wanted, they can go in
+ expand_throw. */
+ /* Do we have a valid object we are throwing? */
+ t = call_eh_info ();
+ emit_cmp_insn (expand_expr (t, NULL_RTX, Pmode, 0),
+ const0_rtx, EQ, NULL_RTX,
+ GET_MODE (DECL_RTL (t)), 0, 0);
+ emit_jump_insn (gen_beq (gotta_call_terminate));
/* 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);
+ handler = do_function_call (FirstExceptionMatch,
+ expr_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);
+ emit_cmp_insn (handler, const0_rtx, EQ, NULL_RTX,
+ GET_MODE (handler), 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);
+ {
+ rtx ret_val, x;
+ ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
+ 0, hard_frame_pointer_rtx);
- /* code to deal with unwinding and looking for it again */
- emit_label (gotta_rethrow_it);
+ /* Set it up so that we continue at the handler. */
+ emit_move_insn (ret_val, handler);
+#ifdef RETURN_ADDR_OFFSET
+ x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
+ if (x != ret_val)
+ emit_move_insn (ret_val, x);
+#endif
- /* 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)));
+ expand_null_return ();
+ }
+
+ top_of_loop = gen_label_rtx ();
+ emit_label (top_of_loop);
+
+#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
+ if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
+ {
+ saved_pcnthrow = gen_reg_rtx (Pmode);
+ emit_move_insn (saved_pcnthrow, hard_function_value (ptr_type_node,
+ NULL_TREE));
+ }
+#endif
+
+ /* Call to __builtin_return_address. */
+#if defined (ARM_FRAME_RTX) /* was __arm */
+ /* This should be moved into arm.h:RETURN_ADDR_RTX */
+ /* This replaces a 'call' to __builtin_return_address */
+ next_pc = gen_reg_rtx (Pmode);
+ emit_move_insn (next_pc,
+ gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
#else
- params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+ params = expr_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);
+ next_pc = 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);
+ /* Did __builtin_return_address return a valid address? */
+ emit_cmp_insn (next_pc, const0_rtx, EQ, NULL_RTX,
+ GET_MODE (next_pc), 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);
+ next_pc = eh_outer_context (next_pc);
+
+ /* Yes it did. */
+#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
+ if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
+ {
+ rtx x;
+
+ x = validize_mem (gen_rtx (MEM, Pmode, saved_pcnthrow));
+ emit_move_insn (validize_mem (gen_rtx (MEM, Pmode, x)),
+ next_pc);
+#ifdef FUNCTION_OUTGOING_VALUE
+ emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
+ validize_mem (gen_rtx (MEM, Pmode,
+ plus_constant (saved_pcnthrow,
+ GET_MODE_SIZE (Pmode)))));
+ emit_insn (gen_rtx (USE, VOIDmode,
+ FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
#endif
+ }
+ else
#endif
+ emit_move_insn (eh_saved_pc_rtx, next_pc);
- /* 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);
+ after_unwind = gen_label_rtx ();
+ do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
- do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop));
- emit_jump (top_of_loop);
+ emit_label (after_unwind);
+
+#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
+ if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
+ {
+ t = build_function_type (void_type_node, void_list_node);
+ t = make_tree (build_pointer_type (t),
+ hard_function_value (ptr_type_node,
+ NULL_TREE));
+ t = build_function_call (t, NULL_TREE);
+ expand_expr (t, const0_rtx, VOIDmode, 0);
+ }
+ else
+#endif
+ emit_throw ();
/* no it didn't --> therefore we need to call terminate */
emit_label (gotta_call_terminate);
@@ -1279,37 +991,58 @@ expand_builtin_throw ()
assemble_external (TREE_OPERAND (Terminate, 0));
{
- rtx ret_val, return_val_rtx;
- emit_label (unwind_first);
+ rtx ret_val, x;
+ /* code to deal with unwinding and looking for it again */
+ emit_label (gotta_rethrow_it);
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);
+#ifdef RETURN_ADDR_OFFSET
+ x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
+ if (x != ret_val)
+ emit_move_insn (ret_val, x);
+#endif
+
+#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
+ if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
+ {
+ rtx x = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode,
+ "__eh_pcnthrow"),
+ NULL_RTX, 1,
+ Pmode, 0);
+ /* This is to get a version of throw that will throw properly. */
+ emit_move_insn (validize_mem (gen_rtx (MEM, Pmode,
+ plus_constant (x, GET_MODE_SIZE (Pmode)))),
+ throw_libfunc);
+#ifdef FUNCTION_OUTGOING_VALUE
+ emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
+ x);
+ emit_insn (gen_rtx (USE, VOIDmode, FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
+#endif
+ }
#endif
- /* Fall into epilogue to unwind prologue. */
+ /* Fall into epilogue to unwind prologue. */
}
- expand_end_bindings (getdecls(), 1, 0);
+ expand_end_bindings (getdecls (), 1, 0);
poplevel (1, 0, 0);
pop_momentary ();
finish_function (lineno, 0, 0);
+#endif /* DWARF2_UNWIND_INFO */
}
void
expand_start_eh_spec ()
{
- start_protect ();
+ expand_eh_region_start ();
}
-void
+static void
expand_end_eh_spec (raises)
tree raises;
{
@@ -1324,6 +1057,7 @@ expand_end_eh_spec (raises)
TREE_TYPE (expr) = void_type_node;
RTL_EXPR_RTL (expr) = const0_rtx;
TREE_SIDE_EFFECTS (expr) = 1;
+ do_pending_stack_adjust ();
start_sequence_for_rtl_expr (expr);
cont = gen_label_rtx ();
emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
@@ -1333,6 +1067,7 @@ expand_end_eh_spec (raises)
do_function_call (Terminate, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Terminate, 0));
emit_barrier ();
+ do_pending_stack_adjust ();
RTL_EXPR_SEQUENCE (expr) = get_insns ();
end_sequence ();
@@ -1342,6 +1077,7 @@ expand_end_eh_spec (raises)
TREE_TYPE (expr) = void_type_node;
RTL_EXPR_RTL (expr) = const0_rtx;
TREE_SIDE_EFFECTS (expr) = 1;
+ do_pending_stack_adjust ();
start_sequence_for_rtl_expr (expr);
cont = gen_label_rtx ();
@@ -1349,15 +1085,19 @@ expand_end_eh_spec (raises)
emit_jump (check);
emit_label (cont);
jumpif (make_tree (integer_type_node, flag), end);
- start_protect ();
+ expand_eh_region_start ();
do_function_call (Unexpected, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Unexpected, 0));
emit_barrier ();
- end_protect (second_try);
+
+ expand_eh_region_end (second_try);
emit_label (check);
emit_move_insn (flag, const1_rtx);
cont = gen_label_rtx ();
+
+ push_eh_info ();
+
while (raises)
{
tree exp;
@@ -1366,12 +1106,12 @@ expand_end_eh_spec (raises)
if (match_type)
{
/* check TREE_VALUE (raises) here */
- exp = saved_throw_value;
- exp = tree_cons (NULL_TREE,
+ exp = get_eh_value ();
+ exp = expr_tree_cons (NULL_TREE,
build_eh_type_type (match_type),
- tree_cons (NULL_TREE,
- saved_throw_type,
- tree_cons (NULL_TREE, exp, NULL_TREE)));
+ expr_tree_cons (NULL_TREE,
+ get_eh_type (),
+ expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
exp = build_function_call (CatchMatch, exp);
assemble_external (TREE_OPERAND (CatchMatch, 0));
@@ -1385,110 +1125,123 @@ expand_end_eh_spec (raises)
emit_indirect_jump (ret);
emit_label (end);
+ do_pending_stack_adjust ();
RTL_EXPR_SEQUENCE (expr) = get_insns ();
end_sequence ();
- end_protect (expr);
+ expand_eh_region_end (expr);
}
/* 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 rtx funcend;
- rtx insns;
+ do_pending_stack_adjust ();
+ push_to_sequence (catch_clauses);
+ expand_leftover_cleanups ();
+ do_pending_stack_adjust ();
+ catch_clauses = get_insns ();
+ end_sequence ();
- start_sequence ();
+ /* 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 ();
+ }
- funcend = gen_label_rtx ();
- emit_jump (funcend);
- /* expand_null_return (); */
+ if (catch_clauses)
+ {
+ rtx funcend = gen_label_rtx ();
+ emit_jump (funcend);
- start_sequence ();
+ /* 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)
+ {
+ /* Is this necessary? */
+ assemble_external (TREE_OPERAND (Terminate, 0));
- /* Add all the catch clauses here. */
- emit_insns (catch_clauses);
- catch_clauses = NULL_RTX;
+ expand_eh_region_start ();
+ }
- expand_leftover_cleanups ();
+ emit_insns (catch_clauses);
+ catch_clauses = NULL_RTX;
- 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);
+ if (exceptions_via_longjmp == 0)
+ expand_eh_region_end (TerminateFunctionCall);
- /* Now expand any new ones. */
expand_leftover_cleanups ();
- insns = get_insns ();
- end_sequence ();
+ emit_label (funcend);
}
+}
- if (insns)
- {
- 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 ();
- }
+tree
+start_anon_func ()
+{
+ static int counter = 0;
+ int old_interface_unknown = interface_unknown;
+ char name[32];
+ tree params;
+ tree t;
- {
- /* 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);
- }
- }
+ push_cp_function_context (NULL_TREE);
+ push_to_top_level ();
- emit_label (funcend);
+ /* No need to mangle this. */
+ push_lang_context (lang_name_c);
- /* 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 ();
+ interface_unknown = 1;
+
+ params = void_list_node;
+ /* 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, 0);
+ store_parm_decls ();
+ pushlevel (0);
+ clear_last_expr ();
+ push_momentary ();
+ expand_start_bindings (0);
+ emit_line_note (input_filename, lineno);
+
+ interface_unknown = old_interface_unknown;
+
+ pop_lang_context ();
- emit_insns (insns);
+ return current_function_decl;
}
+void
+end_anon_func ()
+{
+ expand_end_bindings (getdecls (), 1, 0);
+ poplevel (1, 0, 0);
+ pop_momentary ();
+
+ finish_function (lineno, 0, 0);
-/* call this to expand a throw statement. This follows the following
+ pop_from_top_level ();
+ pop_cp_function_context (NULL_TREE);
+}
+
+/* Expand a throw statement. This follows the following
algorithm:
1. Allocate space to save the current PC onto the stack.
@@ -1497,30 +1250,41 @@ 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 +1292,125 @@ expand_throw (exp)
}
else
{
+ tree object;
+
/* 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),
+ build_expr_list (NULL_TREE, exp),
0);
if (exp == error_mark_node)
error (" in thrown expression");
- throw_type = build_eh_type (build_indirect_ref (exp, NULL_PTR));
+ object = build_indirect_ref (exp, NULL_PTR);
+ throw_type = build_eh_type (object);
+
+ if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
+ {
+ cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
+ dtor_identifier, 0);
+ cleanup = TREE_VALUE (cleanup);
+ mark_addressable (cleanup);
+ /* Pretend it's a normal function. */
+ cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
+ }
}
- 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);
+ if (cleanup == NULL_TREE)
+ {
+ cleanup = build_int_2 (0, 0);
+ TREE_TYPE (cleanup) = cleanup_type;
+ }
+
+ 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 ();
+ }
+
+ /* The throw expression is a full-expression. */
+ exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+ 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
{
- /* rethrow current exception */
- /* This part is easy, as we don't have to do anything else. */
- }
+ /* rethrow current exception; note that it's no longer caught. */
- expand_internal_throw (gen_rtx (LABEL_REF, Pmode, label));
-}
+ 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 ();
+ }
-void
-end_protect_partials () {
- while (protect_list)
- {
- end_protect (TREE_VALUE (protect_list));
- protect_list = TREE_CHAIN (protect_list);
+ exp = build_function_call (fn, NULL_TREE);
+ expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
-}
-
-int
-might_have_exceptions_p ()
-{
- if (eh_table_output_queue.head)
- return 1;
- return 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;
-
- if (! doing_eh (0))
- return;
- exception_section ();
-
- /* 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);
-
- while (entry = dequeue_eh_entry (&eh_table_output_queue))
- {
- tree context = entry->context;
-
- if (context && ! TREE_ASM_WRITTEN (context))
- continue;
-
- count++;
- output_exception_table_entry (asm_out_file,
- entry->start_label, entry->end_label,
- entry->exception_handler_label);
- }
-
- /* Ending marker for table. */
- assemble_label ("__EXCEPTION_END__");
- output_exception_table_entry (asm_out_file,
- constm1_rtx, constm1_rtx, constm1_rtx);
-}
+ if (exceptions_via_longjmp)
+ emit_throw ();
+ else
+ {
+ /* 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);
-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);
+ expand_internal_throw (label);
+ }
}
/* Build a throw expression. */
+
tree
build_throw (e)
tree e;
{
if (e != error_mark_node)
{
+ if (processing_template_decl)
+ return build_min (THROW_EXPR, void_type_node, e);
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;
TREE_USED (e) = 1;
}
return e;
}
-
-start_eh_unwinder ()
-{
- start_protect ();
-}
-
-end_eh_unwinder (end)
- rtx end;
-{
- tree expr;
- rtx return_val_rtx, ret_val, label;
-
- if (! doing_eh (0))
- return;
-
- 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
-
-#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);
-
-#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);
-}
diff --git a/gnu/usr.bin/gcc/cp/expr.c b/gnu/usr.bin/gcc/cp/expr.c
index 99a611e6971..2162b0d7cf0 100644
--- a/gnu/usr.bin/gcc/cp/expr.c
+++ b/gnu/usr.bin/gcc/cp/expr.c
@@ -21,18 +21,21 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "tree.h"
#include "flags.h"
#include "expr.h"
#include "cp-tree.h"
-#undef NULL
-#define NULL 0
+static tree extract_aggr_init PROTO((tree, tree));
+static tree extract_scalar_init PROTO((tree, tree));
+static rtx cplus_expand_expr PROTO((tree, rtx, enum machine_mode,
+ enum expand_modifier));
/* Hook used by expand_expr to expand language-specific tree codes. */
-rtx
+static rtx
cplus_expand_expr (exp, target, tmode, modifier)
tree exp;
rtx target;
@@ -42,11 +45,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.
@@ -110,7 +112,7 @@ 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);
@@ -137,9 +139,21 @@ cplus_expand_expr (exp, target, tmode, modifier)
result. The assumptions are true only if the address was
valid to begin with. */
call_target = validize_mem (call_target);
+
+ /* If this is a reference to a symbol, expand_inline_function
+ will do this transformation and return a different target
+ than the one we gave it, though functionally equivalent. Do
+ the transformation here to avoid confusion. */
+ if (! cse_not_expected && GET_CODE (call_target) == MEM
+ && GET_CODE (XEXP (call_target, 0)) == SYMBOL_REF)
+ {
+ call_target = gen_rtx
+ (MEM, mode, memory_address (mode, XEXP (call_target, 0)));
+ MEM_IN_STRUCT_P (call_target) = 1;
+ }
}
- 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)
@@ -165,7 +179,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
init = maybe_build_cleanup (convert_from_reference (init));
if (init != NULL_TREE)
- expand_expr (init, 0, 0, 0);
+ expand_expr (init, const0_rtx, VOIDmode, 0);
}
call_target = return_target = DECL_RTL (slot);
}
@@ -226,13 +240,13 @@ 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);
default:
break;
@@ -278,19 +292,6 @@ 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;
-}
-
/* Expand this initialization inline and see if it's simple enough that
it can be done at compile-time. */
@@ -333,8 +334,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);
@@ -358,6 +359,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 +371,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/gnu/usr.bin/gcc/cp/gxx.gperf b/gnu/usr.bin/gcc/cp/gxx.gperf
index e5465e89b48..d9cad4a6255 100644
--- a/gnu/usr.bin/gcc/cp/gxx.gperf
+++ b/gnu/usr.bin/gcc/cp/gxx.gperf
@@ -9,20 +9,27 @@ __asm, GCC_ASM_KEYWORD, NORID
__asm__, GCC_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/gnu/usr.bin/gcc/cp/gxxint.texi b/gnu/usr.bin/gcc/cp/gxxint.texi
index 015a33c002c..5f7346561c5 100644
--- a/gnu/usr.bin/gcc/cp/gxxint.texi
+++ b/gnu/usr.bin/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 Mike Stump @code{<mrs@@cygnus.com>}.
@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.
@@ -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.
@@ -1471,7 +1478,7 @@ 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.
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,266 @@ 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).
+
+@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 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}.
+
+@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 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, and an index indicating their position
+in the template parameter list declaration.
+
+@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<T>}.
+For example @code{java.lang.String[]} is encoded as
+@samp{Pt6JArray1ZPQ34java4lang6String}.
+
+@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 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 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 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 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/gnu/usr.bin/gcc/cp/hash.h b/gnu/usr.bin/gcc/cp/hash.h
index 4848aba4775..720890fd4c8 100644
--- a/gnu/usr.bin/gcc/cp/hash.h
+++ b/gnu/usr.bin/gcc/cp/hash.h
@@ -1,14 +1,13 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,7,$ ../../../devo/gcc/cp/gxx.gperf */
-/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf */
+/* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gxx.gperf */
struct resword { char *name; short token; enum rid rid;};
-#define TOTAL_KEYWORDS 97
+#define TOTAL_KEYWORDS 103
#define MIN_WORD_LENGTH 2
#define MAX_WORD_LENGTH 16
#define MIN_HASH_VALUE 4
-#define MAX_HASH_VALUE 219
-/* maximum key range = 216, duplicates = 0 */
+#define MAX_HASH_VALUE 195
+/* maximum key range = 192, duplicates = 0 */
#ifdef __GNUC__
inline
@@ -20,19 +19,19 @@ hash (str, len)
{
static unsigned char asso_values[] =
{
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 0, 220, 88, 16, 19,
- 52, 0, 9, 72, 1, 77, 220, 0, 0, 38,
- 13, 44, 38, 30, 27, 57, 1, 14, 0, 2,
- 2, 7, 220, 220, 220, 220, 220, 220,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
+ 196, 196, 196, 196, 196, 0, 196, 80, 26, 28,
+ 44, 0, 49, 38, 6, 81, 196, 2, 0, 41,
+ 16, 47, 4, 31, 32, 5, 6, 62, 20, 96,
+ 17, 25, 196, 196, 196, 196, 196, 196,
};
register int hval = len;
@@ -49,6 +48,7 @@ hash (str, len)
case 2:
case 1:
hval += asso_values[str[0]];
+ break;
}
return hval + asso_values[str[len - 1]];
}
@@ -65,144 +65,148 @@ is_reserved_word (str, len)
{
{"",}, {"",}, {"",}, {"",},
{"else", ELSE, NORID,},
+ {"",},
+ {"__real", REALPART, NORID},
+ {"",},
+ {"__real__", REALPART, NORID},
+ {"",},
{"true", CXX_TRUE, NORID,},
{"",},
- {"while", WHILE, NORID,},
- {"virtual", SCSPEC, RID_VIRTUAL,},
- {"",}, {"",},
- {"try", TRY, NORID,},
- {"",}, {"",}, {"",}, {"",},
- {"typeof", TYPEOF, NORID,},
- {"not", '!', NORID,},
- {"new", NEW, NORID,},
+ {"__asm__", GCC_ASM_KEYWORD, NORID},
+ {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"this", THIS, NORID,},
+ {"",},
{"extern", SCSPEC, RID_EXTERN,},
- {"bool", TYPESPEC, RID_BOOL,},
- {"",}, {"",},
- {"case", CASE, NORID,},
- {"__alignof__", ALIGNOF, NORID},
+ {"switch", SWITCH, NORID,},
+ {"template", TEMPLATE, RID_TEMPLATE,},
+ {"not", '!', NORID,},
{"",},
- {"typedef", SCSPEC, RID_TYPEDEF,},
+ {"__alignof__", ALIGNOF, NORID},
+ {"static_cast", STATIC_CAST, NORID,},
{"",},
- {"__extension__", EXTENSION, NORID},
+ {"bool", TYPESPEC, RID_BOOL,},
+ {"private", VISSPEC, RID_PRIVATE,},
+ {"case", CASE, NORID,},
+ {"virtual", SCSPEC, RID_VIRTUAL,},
+ {"try", TRY, NORID,},
{"",}, {"",},
- {"__alignof", ALIGNOF, NORID},
- {"xor", '^', NORID,},
+ {"compl", '~', NORID,},
+ {"public", VISSPEC, RID_PUBLIC,},
{"",},
{"__inline", SCSPEC, RID_INLINE},
{"",},
{"__inline__", SCSPEC, RID_INLINE},
+ {"class", AGGR, RID_CLASS,},
+ {"const", CV_QUALIFIER, RID_CONST,},
+ {"static", SCSPEC, RID_STATIC,},
+ {"__extension__", EXTENSION, NORID},
{"",},
+ {"short", TYPESPEC, RID_SHORT,},
+ {"__imag__", IMAGPART, NORID},
+ {"delete", DELETE, NORID,},
+ {"__asm", GCC_ASM_KEYWORD, NORID},
+ {"xor", '^', NORID,},
+ {"not_eq", EQCOMPARE, NORID,},
{"xor_eq", ASSIGN, NORID,},
- {"for", FOR, NORID,},
- {"",}, {"",},
- {"continue", CONTINUE, NORID,},
- {"",},
- {"catch", CATCH, NORID,},
- {"private", VISSPEC, RID_PRIVATE,},
- {"",},
{"typename", TYPENAME_KEYWORD, NORID,},
- {"template", TEMPLATE, RID_TEMPLATE,},
- {"not_eq", EQCOMPARE, NORID,},
- {"",}, {"",},
- {"throw", THROW, NORID,},
- {"__const", TYPE_QUAL, RID_CONST},
- {"__const__", TYPE_QUAL, RID_CONST},
- {"__volatile", TYPE_QUAL, RID_VOLATILE},
- {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,},
- {"__volatile__", TYPE_QUAL, RID_VOLATILE},
- {"delete", DELETE, NORID,},
{"typeid", TYPEID, NORID,},
- {"return", RETURN, NORID,},
- {"__typeof__", TYPEOF, NORID},
- {"compl", '~', NORID,},
- {"public", VISSPEC, RID_PUBLIC,},
- {"__asm__", GCC_ASM_KEYWORD, NORID},
- {"switch", SWITCH, NORID,},
- {"",},
- {"friend", SCSPEC, RID_FRIEND,},
- {"__typeof", TYPEOF, NORID},
{"",},
- {"static_cast", STATIC_CAST, NORID,},
+ {"__complex__", TYPESPEC, RID_COMPLEX},
{"false", CXX_FALSE, NORID,},
{"sizeof", SIZEOF, NORID,},
- {"or", OROR, NORID,},
+ {"typeof", TYPEOF, NORID,},
+ {"__const__", CV_QUALIFIER, RID_CONST},
+ {"__volatile", CV_QUALIFIER, RID_VOLATILE},
+ {"",},
+ {"__volatile__", CV_QUALIFIER, RID_VOLATILE},
+ {"__const", CV_QUALIFIER, RID_CONST},
+ {"catch", CATCH, NORID,},
+ {"__null", CONSTANT, RID_NULL},
+ {"protected", VISSPEC, RID_PROTECTED,},
+ {"",},
+ {"signed", TYPESPEC, RID_SIGNED,},
+ {"",},
+ {"__complex", TYPESPEC, RID_COMPLEX},
+ {"__alignof", ALIGNOF, NORID},
+ {"__wchar_t", TYPESPEC, RID_WCHAR /* Unique to ANSI C++ */,},
{"double", TYPESPEC, RID_DOUBLE,},
+ {"const_cast", CONST_CAST, NORID,},
{"",},
- {"union", AGGR, RID_UNION,},
- {"char", TYPESPEC, RID_CHAR,},
{"struct", AGGR, RID_RECORD,},
+ {"long", TYPESPEC, RID_LONG,},
+ {"or", OROR, NORID,},
+ {"__typeof__", TYPEOF, NORID},
{"or_eq", ASSIGN, NORID,},
+ {"for", FOR, NORID,},
+ {"__imag", IMAGPART, NORID},
{"enum", ENUM, NORID,},
+ {"",}, {"",},
+ {"__label__", LABEL, NORID},
{"int", TYPESPEC, RID_INT,},
- {"const", TYPE_QUAL, RID_CONST,},
- {"static", SCSPEC, RID_STATIC,},
- {"reinterpret_cast", REINTERPRET_CAST, NORID,},
- {"",},
- {"explicit", SCSPEC, RID_EXPLICIT,},
{"__signed__", TYPESPEC, RID_SIGNED},
- {"if", IF, NORID,},
- {"__attribute", ATTRIBUTE, NORID},
- {"short", TYPESPEC, RID_SHORT,},
- {"__attribute__", ATTRIBUTE, NORID},
- {"bitor", '|', NORID,},
{"signature", AGGR, RID_SIGNATURE /* Extension */,},
- {"",},
- {"__sigof__", SIGOF, NORID /* Extension */,},
- {"volatile", TYPE_QUAL, RID_VOLATILE,},
- {"__label__", LABEL, NORID},
{"do", DO, NORID,},
{"",},
- {"__asm", GCC_ASM_KEYWORD, NORID},
- {"protected", VISSPEC, RID_PROTECTED,},
+ {"explicit", SCSPEC, RID_EXPLICIT,},
+ {"char", TYPESPEC, RID_CHAR,},
{"",},
- {"float", TYPESPEC, RID_FLOAT,},
- {"using", USING, NORID,},
+ {"__attribute", ATTRIBUTE, NORID},
+ {"friend", SCSPEC, RID_FRIEND,},
+ {"__attribute__", ATTRIBUTE, NORID},
+ {"while", WHILE, NORID,},
+ {"reinterpret_cast", REINTERPRET_CAST, NORID,},
{"",},
- {"const_cast", CONST_CAST, NORID,},
+ {"continue", CONTINUE, NORID,},
+ {"namespace", NAMESPACE, NORID,},
+ {"sigof", SIGOF, NORID /* Extension */,},
+ {"",},
+ {"volatile", CV_QUALIFIER, RID_VOLATILE,},
{"",},
+ {"bitor", '|', NORID,},
+ {"typedef", SCSPEC, RID_TYPEDEF,},
{"void", TYPESPEC, RID_VOID,},
{"break", BREAK, NORID,},
- {"namespace", NAMESPACE, NORID,},
- {"",}, {"",}, {"",}, {"",},
- {"sigof", SIGOF, NORID /* Extension */,},
- {"",}, {"",}, {"",},
- {"this", THIS, NORID,},
- {"",}, {"",}, {"",}, {"",},
+ {"",},
+ {"new", NEW, NORID,},
+ {"return", RETURN, NORID,},
{"and_eq", ASSIGN, NORID,},
{"",}, {"",}, {"",},
- {"signed", TYPESPEC, RID_SIGNED,},
+ {"using", USING, NORID,},
+ {"",}, {"",},
{"asm", ASM_KEYWORD, NORID,},
- {"",}, {"",}, {"",},
+ {"",}, {"",},
+ {"and", ANDAND, NORID,},
{"mutable", SCSPEC, RID_MUTABLE,},
- {"",}, {"",}, {"",},
+ {"__typeof", TYPEOF, NORID},
+ {"union", AGGR, RID_UNION,},
+ {"",},
+ {"if", IF, NORID,},
{"__signed", TYPESPEC, RID_SIGNED},
- {"class", AGGR, RID_CLASS,},
- {"register", SCSPEC, RID_REGISTER,},
- {"",}, {"",}, {"",},
- {"and", ANDAND, NORID,},
- {"",}, {"",}, {"",}, {"",},
- {"long", TYPESPEC, RID_LONG,},
+ {"",}, {"",},
+ {"goto", GOTO, NORID,},
+ {"",}, {"",},
+ {"__sigof__", SIGOF, NORID /* Extension */,},
+ {"float", TYPESPEC, RID_FLOAT,},
+ {"",}, {"",},
{"default", DEFAULT, NORID,},
- {"operator", OPERATOR, NORID,},
- {"unsigned", TYPESPEC, RID_UNSIGNED,},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"inline", SCSPEC, RID_INLINE,},
+ {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"register", SCSPEC, RID_REGISTER,},
+ {"throw", THROW, NORID,},
{"",},
{"bitand", '&', NORID,},
+ {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"operator", OPERATOR, NORID,},
+ {"",},
+ {"inline", SCSPEC, RID_INLINE,},
{"",},
- {"goto", GOTO, NORID,},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"dynamic_cast", DYNAMIC_CAST, NORID,},
- {"",}, {"",}, {"",}, {"",}, {"",},
+ {"",}, {"",}, {"",},
{"__signature__", AGGR, RID_SIGNATURE /* Extension */,},
- {"",},
+ {"",}, {"",}, {"",},
{"auto", SCSPEC, RID_AUTO,},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",}, {"",},
- {"overload", OVERLOAD, NORID,},
+ {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
+ {"unsigned", TYPESPEC, RID_UNSIGNED,},
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/gnu/usr.bin/gcc/cp/init.c b/gnu/usr.bin/gcc/cp/init.c
index 9752a9bcd1d..ca23848abaf 100644
--- a/gnu/usr.bin/gcc/cp/init.c
+++ b/gnu/usr.bin/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,19 @@ 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 <stdio.h>
#include "tree.h"
#include "rtl.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
+#include "except.h"
+#include "expr.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 +44,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 +121,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 +135,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 +156,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
@@ -215,36 +221,43 @@ 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;
@@ -266,6 +279,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 +368,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 basetype = TREE_PURPOSE (x);
tree binfo;
- if (basename == NULL_TREE)
+ if (basetype == NULL_TREE)
{
/* Initializer for single base class. Must not
use multiple inheritance or this is ambiguous. */
@@ -375,9 +390,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 +417,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 +482,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 +517,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 +525,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 +556,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 +564,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 +571,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 +579,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 +641,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 +657,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 +703,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 +727,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 +744,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 +775,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;
@@ -792,6 +831,7 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list)
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;
@@ -811,15 +851,29 @@ do_member_init (s_id, name, init)
return;
}
- base = convert_pointer_to (binfo, current_class_decl);
+ base = convert_pointer_to (binfo, current_class_ptr);
expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
}
+/* Find the context in which this FIELD can be initialized. */
+
+static tree
+initializing_context (field)
+ tree field;
+{
+ tree t = DECL_CONTEXT (field);
+
+ /* Anonymous union members can be initialized in the first enclosing
+ non-anonymous union context. */
+ while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (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 +885,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,6 +916,7 @@ 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;
@@ -882,13 +926,18 @@ expand_member_init (exp, name, init)
tree basetype = NULL_TREE, field;
tree parm;
tree rval, type;
- tree actual_name;
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))
{
@@ -916,13 +965,13 @@ expand_member_init (exp, name, init)
if (init == void_type_node)
init = NULL_TREE;
- if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name))
+ if (name == NULL_TREE || basetype)
{
tree base_init;
if (name == NULL_TREE)
{
-/*
+#if 0
if (basetype)
name = TYPE_IDENTIFIER (basetype);
else
@@ -930,38 +979,38 @@ expand_member_init (exp, name, init)
error ("no base class to initialize");
return;
}
-*/
+#endif
}
- else
+ else if (basetype != type
+ && ! current_template_parms
+ && ! vec_binfo_member (basetype,
+ TYPE_BINFO_BASETYPES (type))
+ && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
{
- 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 (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;
}
- if (purpose_member (name, current_base_init_list))
+ if (purpose_member (basetype, current_base_init_list))
{
- error ("base class `%s' already initialized",
- IDENTIFIER_POINTER (name));
+ cp_error ("base class `%T' already initialized", basetype);
return;
}
- base_init = build_tree_list (name, init);
- TREE_TYPE (base_init) = basetype;
+ if (warn_reorder && current_member_init_list)
+ {
+ cp_warning ("base initializer for `%T'", basetype);
+ warning (" will be re-ordered to precede member initializations");
+ }
+
+ base_init = build_tree_list (basetype, init);
current_base_init_list = chainon (current_base_init_list, base_init);
}
else
@@ -976,12 +1025,11 @@ expand_member_init (exp, name, init)
if (purpose_member (name, current_member_init_list))
{
- error ("field `%s' already initialized", IDENTIFIER_POINTER (name));
+ cp_error ("field `%D' already initialized", field);
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);
}
return;
@@ -999,7 +1047,7 @@ expand_member_init (exp, name, init)
return;
/* now see if there is a constructor for this type
- which will take these args. */
+ which will take these args. */
if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
{
@@ -1012,14 +1060,10 @@ expand_member_init (exp, name, init)
TREE_USED (exp) = 1;
}
type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
- actual_name = TYPE_IDENTIFIER (type);
- parm = build_component_ref (exp, name, 0, 0);
+ parm = build_component_ref (exp, name, NULL_TREE, 0);
- /* Now get to the constructor. */
+ /* Now get to the constructors. */
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);
@@ -1043,7 +1087,8 @@ expand_member_init (exp, name, init)
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);
+ rval = build_method_call (NULL_TREE, ctor_identifier, init,
+ TYPE_BINFO (type), LOOKUP_NORMAL);
else
return;
@@ -1058,7 +1103,7 @@ expand_member_init (exp, name, init)
}
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
{
- parm = build_component_ref (exp, name, 0, 0);
+ parm = build_component_ref (exp, name, NULL_TREE, 0);
expand_aggr_init (parm, NULL_TREE, 0, 0);
rval = error_mark_node;
}
@@ -1083,8 +1128,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 +1150,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 +1231,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 +1249,37 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
tree rval;
tree parms;
+ if (flag_ansi_overloading && 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,7 +1287,8 @@ 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)
+ else if (! flag_ansi_overloading
+ && 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);
@@ -1219,17 +1297,25 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
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 (flag_ansi_overloading)
+ {
+ rval = build_method_call (exp, ctor_identifier,
+ parms, binfo, flags);
+ expand_expr_stmt (rval);
+ return;
+ }
+
if (init && TREE_CHAIN (parms) == NULL_TREE
&& TYPE_HAS_TRIVIAL_INIT_REF (type)
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
@@ -1242,7 +1328,7 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
{
if (flags & LOOKUP_ONLYCONVERTING)
flags |= LOOKUP_NO_CONVERSION;
- rval = build_method_call (exp, constructor_name_full (type),
+ rval = build_method_call (exp, ctor_identifier,
parms, binfo, flags);
/* Private, protected, or otherwise unavailable. */
@@ -1261,8 +1347,8 @@ expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)
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);
+ TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);
+ expand_assignment (current_class_ptr, rval, 0, 0);
}
else
expand_expr_stmt (rval);
@@ -1310,7 +1396,24 @@ 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)
+
+ if (init && TREE_CODE (exp) == VAR_DECL
+ && TREE_CODE (init) == CONSTRUCTOR
+ && TREE_HAS_CONSTRUCTOR (init))
+ {
+ 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);
+ return;
+ }
+
+ if (init && ! flag_ansi_overloading)
{
tree init_list = NULL_TREE;
@@ -1325,15 +1428,9 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
if (TREE_CODE (init) != TREE_LIST)
{
- if (TREE_CODE (init_type) == ERROR_MARK)
+ if (init_type == error_mark_node)
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
@@ -1347,37 +1444,18 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
/* 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);
+ DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL);
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
- )
+ if (init_type == type && TREE_CODE (init) == CALL_EXPR)
{
/* 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))
{
@@ -1405,7 +1483,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
if (exp == DECL_RESULT (current_function_decl))
DECL_INITIAL (exp) = init;
TREE_SIDE_EFFECTS (init) = 1;
- expand_expr (init, const0_rtx, VOIDmode, 0);
+ expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
free_temp_slots ();
return;
}
@@ -1416,7 +1494,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
{
tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
- if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
+ if (tmp && 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
@@ -1425,7 +1503,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
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_OPERAND (init, 0), TREE_OPERAND (init, 1), NULL_TREE);
TREE_SIDE_EFFECTS (init) = 1;
TREE_VALUE (TREE_OPERAND (init, 1))
= convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
@@ -1446,22 +1524,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
}
}
- if (TREE_CODE (exp) == VAR_DECL
- && TREE_CODE (init) == CONSTRUCTOR
- && TREE_HAS_CONSTRUCTOR (init))
- {
- 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);
- return;
- }
-
/* Handle this case: when calling a constructor: xyzzy foo(bar);
which really means: xyzzy foo = bar; Ugh!
@@ -1472,7 +1534,7 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
if (init_list && TREE_CHAIN (init_list))
{
warning ("initializer list being treated as compound expression");
- init = convert (type, build_compound_expr (init_list));
+ init = cp_convert (type, build_compound_expr (init_list));
if (init == error_mark_node)
return;
}
@@ -1481,26 +1543,26 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
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)
+
+ /* If this is copy-initialization, see whether we can go through a
+ type conversion operator. */
+ if (TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING))
{
tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
? TREE_TYPE (init_type) : init_type;
if (ttype != type && IS_AGGR_TYPE (ttype))
{
- tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0);
+ tree rval = build_type_conversion (CONVERT_EXPR, type, init, 1);
if (rval)
{
/* See if there is a constructor for``type'' that takes a
- ``ttype''-typed object. */
- tree parms = build_tree_list (NULL_TREE, init);
+ ``ttype''-typed object. */
+ tree parms = build_expr_list (NULL_TREE, init);
tree as_cons = NULL_TREE;
if (TYPE_HAS_CONSTRUCTOR (type))
- as_cons = build_method_call (exp, constructor_name_full (type),
+ as_cons = build_method_call (exp, ctor_identifier,
parms, binfo,
LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);
if (as_cons != NULL_TREE && as_cons != error_mark_node)
@@ -1508,159 +1570,22 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
cp_error ("ambiguity between conversion to `%T' and constructor",
type);
else
- expand_assignment (exp, rval, 0, 0);
+ if (rval != error_mark_node)
+ expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags);
return;
}
}
}
}
- /* 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 (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");
- }
- else
- expand_recursive_init (binfo, true_exp, exp, init,
- CLASSTYPE_BASE_INIT_LIST (type), alias_this);
-}
-
-/* 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;
-
-/* 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;
-{
- 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;
+ /* 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);
}
/* 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;
@@ -1690,7 +1615,29 @@ is_aggr_typedef (name, or_else)
return 1;
}
+/* Report an error if TYPE is not a user-defined, aggregate type. If
+ OR_ELSE is nonzero, give an error message. */
+
+int
+is_aggr_type (type, or_else)
+ tree type;
+ int or_else;
+{
+ if (type == error_mark_node)
+ return 0;
+
+ if (! IS_AGGR_TYPE (type)
+ && TREE_CODE (type) != TEMPLATE_TYPE_PARM)
+ {
+ if (or_else)
+ cp_error ("`%T' is not an aggregate type", type);
+ return 0;
+ }
+ return 1;
+}
+
/* Like is_aggr_typedef, but returns typedef if successful. */
+
tree
get_aggr_from_typedef (name, or_else)
tree name;
@@ -1737,40 +1684,47 @@ 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 (type == std_node)
+ return build_x_function_call (do_scoped_id (name, 0), 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 +1733,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 +1749,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)
{
@@ -1826,7 +1774,10 @@ build_member_call (cname, name, parmlist)
|| 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,
+ 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))))
@@ -1863,29 +1814,33 @@ 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 <typename>
@@ 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;
+ tree decl, fnfields, fields, t = error_mark_node;
+ tree basebinfo = NULL_TREE;
int dtor = 0;
- 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)
+ 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) == IDENTIFIER_NODE
+ && get_aggr_from_typedef (type, 0) == 0)
{
- tree ns = lookup_name (cname, 0);
+ tree ns = lookup_name (type, 0);
tree val;
if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
{
@@ -1897,20 +1852,24 @@ build_offset_ref (cname, name)
}
}
- 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) == BIT_NOT_EXPR)
{
dtor = 1;
name = TREE_OPERAND (name, 0);
}
- if (TYPE_SIZE (type) == 0)
+ if (name == constructor_name_full (type))
+ name = constructor_name (type);
+
+ 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 +1879,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 +1891,88 @@ 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 = current_class_ref;
+
+ if (constructor_name (BINFO_TYPE (basebinfo)) == name)
+ if (dtor)
+ name = dtor_identifier;
+ else
+ name = ctor_identifier;
else
- decl = C_C_D;
+ if (dtor)
+ my_friendly_abort (999);
- 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;
+ basebinfo = TREE_PURPOSE (fnfields);
/* Go from the TREE_BASELINK to the member function info. */
t = TREE_VALUE (fnfields);
- if (fields)
+ if (DECL_CHAIN (t) == NULL_TREE)
{
- if (DECL_FIELD_CONTEXT (fields) == DECL_FIELD_CONTEXT (t))
+ tree access;
+
+ /* unique functions are handled easily. */
+ 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 && global_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 +1992,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 +2003,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. */
@@ -2171,7 +2028,12 @@ resolve_offset_ref (exp)
if (TREE_CODE (exp) == TREE_LIST)
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 +2043,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 +2057,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,19 +2077,18 @@ 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)
{
@@ -2236,16 +2097,16 @@ resolve_offset_ref (exp)
}
addr = convert_pointer_to (basetype, base);
access = compute_access (basetype_path, member);
- if (access == access_public)
+ 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 +2115,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 +2176,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 +2194,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;
@@ -2853,9 +2248,10 @@ build_new (placement, decl, init, use_global_new)
{
tree type, true_type, size, rval;
tree nelts;
- tree alloc_expr, alloc_temp;
+ tree alloc_expr;
int has_array = 0;
enum tree_code code = NEW_EXPR;
+ int use_cookie, nothrow, check_new;
tree pending_sizes = NULL_TREE;
@@ -2903,9 +2299,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)
{
@@ -2945,7 +2346,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
{
@@ -2965,7 +2366,22 @@ build_new (placement, decl, init, use_global_new)
{
type = decl;
true_type = type;
- decl = TYPE_NAME (type);
+ decl = TYPE_MAIN_DECL (type);
+ }
+
+ if (processing_template_decl)
+ {
+ tree t;
+ 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
@@ -3004,6 +2420,13 @@ 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 (TYPE_SIZE (complete_type (true_type)) == 0)
+ {
+ incomplete_type_error (0, true_type);
+ return error_mark_node;
+ }
+
if (has_array)
size = fold (build_binary_op (MULT_EXPR, size_in_bytes (true_type),
nelts, 1));
@@ -3016,12 +2439,6 @@ build_new (placement, decl, init, use_global_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 +2452,32 @@ build_new (placement, decl, init, use_global_new)
return error_mark_node;
}
+ /* If the first placement arg is of type nothrow_t, it's allowed to
+ return 0 on allocation failure. */
+ nothrow = (placement && TREE_VALUE (placement)
+ && TREE_TYPE (TREE_VALUE (placement))
+ && IS_AGGR_TYPE (TREE_TYPE (TREE_VALUE (placement)))
+ && (TYPE_IDENTIFIER (TREE_TYPE (TREE_VALUE (placement)))
+ == get_identifier ("nothrow_t")));
+
+ check_new = flag_check_new || nothrow;
+
+#if 1
+ /* Get a little extra space to store a couple of things before the new'ed
+ array, if this isn't the default placement new. */
+
+ 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 (has_array && TYPE_VEC_NEW_USES_COOKIE (true_type))
+ 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,9 +2485,14 @@ build_new (placement, decl, init, use_global_new)
}
if (has_array)
- code = VEC_NEW_EXPR;
+ {
+ code = VEC_NEW_EXPR;
+
+ if (init && pedantic)
+ cp_pedwarn ("initialization in array new");
+ }
- /* Allocate the object. */
+ /* 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,
@@ -3056,7 +2501,7 @@ build_new (placement, decl, init, use_global_new)
{
rval = build_opfncall (code, LOOKUP_GLOBAL|LOOKUP_COMPLAIN,
ptr_type_node, size, placement);
- rval = convert (build_pointer_type (true_type), rval);
+ rval = cp_convert (build_pointer_type (true_type), rval);
}
else if (! has_array && flag_this_is_variable > 0
&& TYPE_NEEDS_CONSTRUCTING (true_type) && init != void_type_node)
@@ -3073,32 +2518,12 @@ build_new (placement, decl, init, use_global_new)
{
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
+ build_expr_list (NULL_TREE, size));
TREE_CALLS_NEW (rval) = 1;
}
- if (flag_check_new && 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;
- }
+ if (check_new && rval)
+ alloc_expr = rval = save_expr (rval);
else
alloc_expr = NULL_TREE;
@@ -3106,25 +2531,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 = cp_convert (ptr_type_node, rval); /* convert to void * first */
+ rval = cp_convert (string_type_node, rval); /* lets not add void* and ints */
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),
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);
+ rval = cp_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 = build_compound_expr (expr_tree_cons (NULL_TREE, exp1,
+ build_expr_list (NULL_TREE, rval)));
}
if (rval == error_mark_node)
@@ -3175,7 +2600,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,8 +2609,8 @@ 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)
{
@@ -3195,6 +2620,10 @@ build_new (placement, decl, init, use_global_new)
else
rval = error_mark_node;
}
+ else
+ rval = build (VEC_INIT_EXPR, TREE_TYPE (rval),
+ save_expr (rval), init, nelts);
+#if 0
else if (current_function_decl == NULL_TREE)
{
extern tree static_aggregates;
@@ -3231,7 +2660,7 @@ build_new (placement, decl, init, use_global_new)
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
- rtxval = expand_expr (alloc_expr, NULL, VOIDmode, 0);
+ rtxval = expand_expr (alloc_expr, NULL_RTX, VOIDmode, EXPAND_NORMAL);
do_pending_stack_adjust ();
TREE_SIDE_EFFECTS (xval) = 1;
RTL_EXPR_SEQUENCE (xval) = get_insns ();
@@ -3275,52 +2704,30 @@ build_new (placement, decl, init, use_global_new)
}
rval = xval;
}
+#endif
}
else if (TYPE_READONLY (true_type))
cp_error ("uninitialized const in `new' of `%#T'", true_type);
done:
- if (alloc_expr)
+ if (alloc_expr && rval != alloc_expr)
{
/* 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;
+ tree ifexp = build_binary_op (NE_EXPR, alloc_expr,
+ integer_zero_node, 1);
+ rval = build_conditional_expr (ifexp, rval, alloc_expr);
}
if (rval && TREE_TYPE (rval) != build_pointer_type (type))
{
/* The type of new int [3][3] is not int *, but int [3] * */
- rval = build_c_cast (build_pointer_type (type), rval, 0);
+ rval = build_c_cast (build_pointer_type (type), rval);
}
if (pending_sizes)
rval = build_compound_expr (chainon (pending_sizes,
- build_tree_list (NULL_TREE, rval)));
-
- if (flag_gc)
- {
- 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))));
- }
+ build_expr_list (NULL_TREE, rval)));
return rval;
}
@@ -3333,7 +2740,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. */
@@ -3373,22 +2780,22 @@ 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);
+ block = build_block (tbase, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE);
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 +2807,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 +2845,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 +2865,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 +2884,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 +2928,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 +2946,18 @@ 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) == TREE_LIST)
+ init = build_compound_expr (init);
+
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 +2985,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,7 +3007,7 @@ 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:
@@ -3629,7 +3040,7 @@ 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);
if (from_array)
@@ -3659,7 +3070,18 @@ expand_vec_init (decl, base, maxindex, init, from_array)
array_type_nelts (type), 0, 0);
}
else
- expand_aggr_init (build1 (INDIRECT_REF, type, base), init, 0, 0);
+ {
+ tree targ = build1 (INDIRECT_REF, type, base);
+ tree rhs;
+
+ if (init)
+ rhs = convert_for_initialization (targ, type, init, LOOKUP_NORMAL,
+ "initialization", NULL_TREE, 0);
+ else
+ rhs = NULL_TREE;
+
+ expand_aggr_init (targ, rhs, 0, 0);
+ }
expand_assignment (base,
build (PLUS_EXPR, build_pointer_type (type), base, size),
@@ -3669,7 +3091,7 @@ expand_vec_init (decl, base, maxindex, init, from_array)
build (PLUS_EXPR, build_pointer_type (type), base2, size), 0, 0);
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 +3100,33 @@ 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;
+ 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);
+ 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 +3151,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;
@@ -3725,7 +3168,7 @@ build_x_delete (type, addr, which_delete, virtual_size)
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));
+ build_expr_list (NULL_TREE, addr));
return rval;
}
@@ -3740,6 +3183,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 +3191,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,7 +3208,7 @@ 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)
+ if (TYPE_SIZE (complete_type (type)) == 0)
{
incomplete_type_error (0, type);
return error_mark_node;
@@ -3777,7 +3219,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
{
/* 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 +3227,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 +3239,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 +3256,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);
@@ -3842,26 +3277,24 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* 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));
}
- 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 +3307,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);
+ expr = build_method_call
+ (ref, dtor_identifier, build_expr_list (NULL_TREE, passed_auto_delete),
+ NULL_TREE, flags);
- 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;
- }
- }
-
- /* 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 +3337,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 +3367,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 +3381,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_scoped_method_call
+ (ref, base_binfo, dtor_identifier,
+ build_expr_list (NULL_TREE, integer_zero_node));
- expr = build_delete (build_pointer_type (BINFO_TYPE (base_binfo)), expr,
- integer_zero_node,
- flags, 0);
-
- 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 +3394,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 +3424,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 +3450,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 +3467,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 +3477,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 +3492,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/gnu/usr.bin/gcc/cp/input.c b/gnu/usr.bin/gcc/cp/input.c
index 77a64683f72..cb9dfa8b71f 100644
--- a/gnu/usr.bin/gcc/cp/input.c
+++ b/gnu/usr.bin/gcc/cp/input.c
@@ -30,21 +30,15 @@ Boston, MA 02111-1307, USA. */
inlining). */
#include <stdio.h>
-#include "obstack.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,17 @@ extern int lineno;
#define inline
#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 +83,6 @@ allocate_input ()
}
inp = (struct input_source *) xmalloc (sizeof (struct input_source));
inp->next = 0;
- inp->obstack = 0;
return inp;
}
@@ -86,9 +90,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 +103,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 +115,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 +128,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,30 +155,18 @@ 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);
}
diff --git a/gnu/usr.bin/gcc/cp/lang-options.h b/gnu/usr.bin/gcc/cp/lang-options.h
index d551357c09c..045584965f8 100644
--- a/gnu/usr.bin/gcc/cp/lang-options.h
+++ b/gnu/usr.bin/gcc/cp/lang-options.h
@@ -32,8 +32,6 @@ Boston, MA 02111-1307, USA. */
"-fno-alt-external-templates",
"-fansi-overloading",
"-fno-ansi-overloading",
- "-fcadillac",
- "-fno-cadillac",
"-fcheck-new",
"-fno-check-new",
"-fconserve-space",
@@ -50,8 +48,8 @@ Boston, MA 02111-1307, USA. */
"-fno-external-templates",
"-ffor-scope",
"-fno-for-scope",
- "-fgc",
- "-fno-gc",
+ "-fguiding-decls",
+ "-fno-guiding-decls",
"-fgnu-keywords",
"-fno-gnu-keywords",
"-fhandle-exceptions",
@@ -68,6 +66,7 @@ Boston, MA 02111-1307, USA. */
"-fno-labels-ok",
"-fmemoize-lookups",
"-fno-memoize-lookups",
+ "-fname-mangling-version-",
"-fnonnull-objects",
"-fno-nonnull-objects",
"-foperator-names",
@@ -76,16 +75,17 @@ Boston, MA 02111-1307, USA. */
"-fno-repo",
"-fsave-memoized",
"-fno-save-memoized",
- "-fshort-temps",
- "-fno-short-temps",
"-fstats",
"-fno-stats",
"-fstrict-prototype",
"-fno-strict-prototype",
+ "-ftemplate-depth-",
"-fthis-is-variable",
"-fno-this-is-variable",
"-fvtable-thunks",
"-fno-vtable-thunks",
+ "-fweak",
+ "-fno-weak",
"-fxref",
"-fno-xref",
@@ -105,3 +105,11 @@ Boston, MA 02111-1307, USA. */
"-Wno-reorder",
"-Wsynth",
"-Wno-synth",
+ "-Wpmf-conversions",
+ "-Wno-pmf-conversions",
+ "-Weffc++",
+ "-Wno-effc++",
+ "-Wsign-promo",
+ "-Wno-sign-promo",
+ "-Wold-style-cast",
+ "-Wno-old-style-cast",
diff --git a/gnu/usr.bin/gcc/cp/lang-specs.h b/gnu/usr.bin/gcc/cp/lang-specs.h
index fbb72c9ed97..381bec56ecb 100644
--- a/gnu/usr.bin/gcc/cp/lang-specs.h
+++ b/gnu/usr.bin/gcc/cp/lang-specs.h
@@ -22,6 +22,7 @@ Boston, MA 02111-1307, USA. */
g++. */
{".cc", "@c++"},
+ {".cp", "@c++"},
{".cxx", "@c++"},
{".cpp", "@c++"},
{".c++", "@c++"},
@@ -31,15 +32,15 @@ Boston, MA 02111-1307, USA. */
%{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}\
+ %c %{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\
%{!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\
@@ -50,7 +51,7 @@ Boston, MA 02111-1307, USA. */
{"@c++-cpp-output",
"%{!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\
diff --git a/gnu/usr.bin/gcc/cp/lex.h b/gnu/usr.bin/gcc/cp/lex.h
index 1cf5687df3f..8df6b76a270 100644
--- a/gnu/usr.bin/gcc/cp/lex.h
+++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/cp/method.c b/gnu/usr.bin/gcc/cp/method.c
index a0e15275140..dc57bc77a46 100644
--- a/gnu/usr.bin/gcc/cp/method.c
+++ b/gnu/usr.bin/gcc/cp/method.c
@@ -1,6 +1,6 @@
/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
- Copyright (C) 1987, 89, 92, 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.
@@ -26,8 +26,8 @@ Boston, MA 02111-1307, USA. */
#endif
/* Handle method declarations. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "cp-tree.h"
#include "class.h"
@@ -39,10 +39,18 @@ Boston, MA 02111-1307, USA. */
#include "hard-reg-set.h"
#include "flags.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+extern char *index ();
+#endif
+
/* 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 +58,24 @@ 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((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 char *thunk_printable_name PROTO((tree));
+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_parm_names PROTO((tree, tree));
+static void build_underscore_int PROTO((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 +88,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 +113,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)
@@ -147,6 +171,7 @@ do_inline_function_hair (type, 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;
@@ -178,8 +203,13 @@ report_type_mismatch (cp, parmtypes, name_kind)
/* 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);
+ if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))))
+ && ! TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (cp->function))))))
+ cp_error ("call to non-volatile %s `%#D' with volatile object",
+ name_kind, cp->function);
+ else
+ cp_error ("call to non-const %s `%#D' with const object",
+ name_kind, cp->function);
return;
}
@@ -250,34 +280,74 @@ static int nofold;
} while (0)
/* Code to concatenate an asciified integer to a string. */
+
static
#ifdef __GNUC__
__inline
#endif
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
@@ -309,7 +379,6 @@ flush_repeats (type)
}
static int numeric_output_need_bar;
-static void build_overload_identifier ();
static void
build_overload_nested_name (decl)
@@ -318,54 +387,74 @@ build_overload_nested_name (decl)
if (DECL_CONTEXT (decl))
{
tree context = DECL_CONTEXT (decl);
- if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
- context = TYPE_MAIN_DECL (context);
- build_overload_nested_name (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)
+ build_overload_name (context, 0, 0);
+ else
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+ 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 /* TYPE_DECL */
- {
- tree name = DECL_NAME (decl);
- build_overload_identifier (name);
- }
+ build_overload_identifier (decl);
+}
+
+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. */
+/* Encoding for an INTEGER_CST value. */
+
static void
-build_overload_int (value)
+build_overload_int (value, in_template)
tree value;
+ int in_template;
{
+ if (in_template && TREE_CODE (value) != INTEGER_CST)
+ /* 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);
+ return;
+ }
+
my_friendly_assert (TREE_CODE (value) == INTEGER_CST, 243);
- if (TYPE_PRECISION (value) == 2 * HOST_BITS_PER_WIDE_INT)
+ if (TYPE_PRECISION (TREE_TYPE (value)) == 2 * HOST_BITS_PER_WIDE_INT)
{
- if (tree_int_cst_lt (value, integer_zero_node))
- {
- OB_PUTC ('m');
- value = build_int_2 (~ TREE_INT_CST_LOW (value),
- - TREE_INT_CST_HIGH (value));
- }
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));
+ return;
}
/* else fall through to print in smaller mode */
}
@@ -374,8 +463,9 @@ build_overload_int (value)
}
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)
@@ -389,6 +479,14 @@ build_overload_value (type, value)
numeric_output_need_bar = 0;
}
+ if (TREE_CODE (value) == TEMPLATE_CONST_PARM)
+ {
+ OB_PUTC ('Y');
+ build_underscore_int (TEMPLATE_CONST_IDX (value));
+ build_underscore_int (TEMPLATE_CONST_LEVEL (value));
+ return;
+ }
+
if (TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
{
@@ -411,65 +509,83 @@ build_overload_value (type, value)
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
{
- build_overload_int (value);
+ build_overload_int (value, in_template);
numeric_output_need_bar = 1;
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 +595,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,7 +612,7 @@ build_overload_value (type, value)
else if (TREE_CODE (a3) == INTEGER_CST)
{
OB_PUTC ('i');
- build_overload_int (a3);
+ build_overload_int (a3, in_template);
numeric_output_need_bar = 1;
return;
}
@@ -505,9 +621,10 @@ build_overload_value (type, value)
sorry ("template instantiation with pointer to method that is too complex");
return;
}
- if (TREE_CODE (value) == INTEGER_CST)
+ if (TREE_CODE (value) == INTEGER_CST
+ || TREE_CODE (value) == TEMPLATE_CONST_PARM)
{
- build_overload_int (value);
+ build_overload_int (value, in_template);
numeric_output_need_bar = 1;
return;
}
@@ -515,13 +632,13 @@ build_overload_value (type, value)
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
@@ -535,46 +652,65 @@ build_overload_value (type, value)
}
}
+
+/* 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_overload_name (arg, 0, 0);
+ }
+ else
+ {
+ parm = tsubst (parm, arglist,
+ TREE_VEC_LENGTH (arglist), NULL_TREE);
+ /* It's a PARM_DECL. */
+ build_overload_name (TREE_TYPE (parm), 0, 0);
+ build_overload_value (parm, arg, uses_template_parms (arglist));
+ }
+ }
+ }
+
+
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 template, parmlist, arglist, tname;
- int i, nparms;
- template = IDENTIFIER_TEMPLATE (name);
+ template = CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (name));
arglist = TREE_VALUE (template);
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,6 +721,49 @@ build_overload_identifier (name)
}
}
+/* Given DECL, either a class TYPE, TYPE_DECL or FUNCTION_DECL, produce
+ the mangling for it. Used by build_overload_name and build_static_name. */
+
+static void
+build_qualified_name (decl)
+ tree decl;
+{
+ tree context;
+ int i = 1;
+
+ if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
+ decl = TYPE_NAME (decl);
+
+ /* If DECL_ASSEMBLER_NAME has been set properly, use it. */
+ if (TREE_CODE (decl) == TYPE_DECL
+ && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+ {
+ OB_PUTID (DECL_ASSEMBLER_NAME (decl));
+ return;
+ }
+
+ context = decl;
+ while (DECL_CONTEXT (context))
+ {
+ i += 1;
+ context = DECL_CONTEXT (context);
+ if (TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+ context = TYPE_NAME (context);
+ }
+
+ 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 (decl);
+}
+
/* 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.
@@ -636,7 +815,14 @@ build_overload_name (parmtypes, begin, end)
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 (parmtype);
+#endif
goto next;
}
@@ -804,6 +990,11 @@ build_overload_name (parmtypes, begin, end)
else my_friendly_abort (74);
break;
+ case COMPLEX_TYPE:
+ OB_PUTC ('J');
+ build_overload_name (TREE_TYPE (parmtype), 0, 0);
+ break;
+
case VOID_TYPE:
if (! just_one)
{
@@ -835,60 +1026,39 @@ build_overload_name (parmtypes, begin, end)
common:
{
tree name = TYPE_NAME (parmtype);
- int i = 1;
- if (TREE_CODE (name) == TYPE_DECL)
+ if (TREE_CODE (name) == IDENTIFIER_NODE)
{
- tree context = name;
-
- /* 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));
+ build_overload_identifier (TYPE_NAME (parmtype));
+ break;
}
- else
- build_overload_identifier (name);
+ my_friendly_assert (TREE_CODE (name) == TYPE_DECL, 248);
+
+ build_qualified_name (name);
break;
}
case UNKNOWN_TYPE:
- /* This will take some work. */
- OB_PUTC ('?');
+ /* We can get here if __null is defined to have type ({unkown
+ type}*), which it is if -ansi is not used. Treat this
+ like 'void*'. */
+ OB_PUTC ('v');
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);
- }
+ OB_PUTC ('X');
+ build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
+ build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
+ break;
+
+ case TYPENAME_TYPE:
+ /* When mangling the type of a function template whose
+ declaration looks like:
+
+ template <class T> void foo(typename T::U)
+
+ we have to mangle these. */
+ build_qualified_name (parmtype);
break;
default:
@@ -904,7 +1074,7 @@ build_overload_name (parmtypes, begin, end)
if (nrepeats)
flush_repeats (typevec[maxtype-1]);
- /* To get here, parms must end with `...'. */
+ /* To get here, parms must end with `...'. */
OB_PUTC ('e');
}
@@ -912,45 +1082,38 @@ build_overload_name (parmtypes, begin, end)
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;
+#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 ();
+
+ 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);
@@ -984,6 +1147,8 @@ build_decl_overload (dname, parms, for_method)
/* We can get away without doing this. */
OB_PUTC ('M');
#endif
+ if (tparms != NULL_TREE)
+ OB_PUTC ('H');
{
tree this_type = TREE_VALUE (parms);
@@ -995,13 +1160,21 @@ build_decl_overload (dname, parms, for_method)
TREE_CHAIN (parms));
}
}
+ else if (tparms)
+ OB_PUTC ('H');
else
OB_PUTC ('F');
+ if (tparms)
+ {
+ build_template_parm_names (tparms, targs);
+ OB_PUTC ('_');
+ }
+
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);
@@ -1014,14 +1187,23 @@ build_decl_overload (dname, parms, for_method)
TREE_USED (TREE_VALUE (parms)) = 1;
if (TREE_CHAIN (parms))
- build_overload_name (TREE_CHAIN (parms), 0, 1);
+ build_overload_name (TREE_CHAIN (parms), 0, 0);
else
- OB_PUTC2 ('e', '\0');
+ OB_PUTC ('e');
}
else
- build_overload_name (parms, 0, 1);
+ build_overload_name (parms, 0, 0);
DEALLOCATE_TYPEVEC (parms);
}
+
+ if (ret_type != NULL_TREE && for_method != 2)
+ {
+ /* Add the return type. */
+ OB_PUTC ('_');
+ build_overload_name (ret_type, 0, 0);
+ }
+
+ OB_FINISH ();
{
tree n = get_identifier (obstack_base (&scratch_obstack));
if (IDENTIFIER_OPNAME_P (dname))
@@ -1030,7 +1212,45 @@ build_decl_overload (dname, parms, for_method)
}
}
+/* 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)
+ tree dname;
+ tree parms;
+ int for_method;
+{
+ return build_decl_overload_real (dname, parms, NULL_TREE, NULL_TREE,
+ NULL_TREE, for_method);
+}
+
+
+/* Like build_decl_overload, but for template functions. */
+
+tree
+build_template_decl_overload (dname, parms, ret_type, tparms, targs,
+ for_method)
+ tree dname;
+ tree parms;
+ tree ret_type;
+ tree tparms;
+ tree targs;
+ int for_method;
+{
+ return build_decl_overload_real (dname, parms, ret_type, tparms, targs,
+ for_method);
+}
+
+
/* Build an overload name for the type expression TYPE. */
+
tree
build_typename_overload (type)
tree type;
@@ -1044,107 +1264,35 @@ build_typename_overload (type)
id = get_identifier (obstack_base (&scratch_obstack));
IDENTIFIER_OPNAME_P (id) = 1;
#if 0
- IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);
+ IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type);
#endif
TREE_TYPE (id) = type;
return id;
}
-#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. */
tree
-build_t_desc_overload (type)
- tree type;
+build_overload_with_type (name, type)
+ tree name, type;
{
OB_INIT ();
- OB_PUTS (T_DESC_FORMAT);
+ OB_PUTID (name);
nofold = 1;
-#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
-
build_overload_name (type, 0, 1);
return get_identifier (obstack_base (&scratch_obstack));
}
-/* 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. */
-
-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;
+tree
+get_id_2 (name, name2)
+ char *name;
+ tree name2;
{
- /* @@ */
- return (TREE_OVERLOADED (name)
- && (! IDENTIFIER_CLASS_VALUE (name) || current_class_type == 0)
- && ! IDENTIFIER_LOCAL_VALUE (name));
+ OB_INIT ();
+ OB_PUTCP (name);
+ OB_PUTID (name2);
+ OB_FINISH ();
+ return get_identifier (obstack_base (&scratch_obstack));
}
-#endif
/* Given a tree_code CODE, and some arguments (at least one),
attempt to use an overloaded operator on the arguments.
@@ -1183,13 +1331,16 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
int try_second;
int binary_is_unary;
+ if (flag_ansi_overloading)
+ return build_new_op (code, flags, xarg1, xarg2, arg3);
+
if (xarg1 == error_mark_node)
return error_mark_node;
if (code == COND_EXPR)
{
- if (TREE_CODE (xarg2) == ERROR_MARK
- || TREE_CODE (arg3) == ERROR_MARK)
+ if (xarg2 == error_mark_node
+ || arg3 == error_mark_node)
return error_mark_node;
}
if (code == COMPONENT_REF)
@@ -1226,11 +1377,10 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
case VEC_NEW_EXPR:
case NEW_EXPR:
{
- tree args = tree_cons (NULL_TREE, xarg2, arg3);
+ tree args = expr_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);
+ return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN);
rval = build_method_call
(build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
@@ -1253,16 +1403,32 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
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);
+ build_expr_list (NULL_TREE, xarg1),
+ flags & LOOKUP_COMPLAIN);
+ arg1 = TREE_TYPE (xarg1);
+
+ /* 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);
+ }
rval = build_method_call
- (build_indirect_ref (build1 (NOP_EXPR, TREE_TYPE (xarg1),
+ (build_indirect_ref (build1 (NOP_EXPR, arg1,
error_mark_node),
NULL_PTR),
- fnname, tree_cons (NULL_TREE, xarg1,
- build_tree_list (NULL_TREE, xarg2)),
+ fnname, expr_tree_cons (NULL_TREE, xarg1,
+ build_expr_list (NULL_TREE, xarg2)),
NULL_TREE, flags);
#if 0
/* This can happen when operator delete is protected. */
@@ -1306,7 +1472,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
/* Try to fail. First, fail if unary */
if (! try_second)
return rval;
- /* Second, see if second argument is non-aggregate. */
+ /* Second, see if second argument is non-aggregate. */
type2 = TREE_TYPE (xarg2);
if (TREE_CODE (type2) == OFFSET_TYPE)
type2 = TREE_TYPE (type2);
@@ -1397,9 +1563,8 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
/* 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);
+ pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead",
+ op, op);
xarg2 = NULL_TREE;
binary_is_unary = 1;
}
@@ -1441,27 +1606,26 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
}
else if (code == COND_EXPR)
{
- parms = tree_cons (0, xarg2, build_tree_list (NULL_TREE, arg3));
+ parms = expr_tree_cons (NULL_TREE, xarg2, build_expr_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);
+ parms = expr_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);
+ parms = build_expr_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);
+ parms = expr_tree_cons (NULL_TREE, xarg1,
+ build_expr_list (NULL_TREE, xarg2));
+ rval = build_overload_call (fnname, parms, flags);
}
return rval;
@@ -1478,7 +1642,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 +1651,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)
{
@@ -1530,23 +1692,23 @@ 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 (really_overloaded_fn (value))
{
+#if 0
tree t = get_first_fn (value);
for (; t; t = DECL_CHAIN (t))
{
@@ -1556,21 +1718,33 @@ hack_identifier (value, name, yychar)
assemble_external (t);
TREE_USED (t) = 1;
}
+#endif
}
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
+ 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 +1752,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 +1762,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 +1776,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,152 +1789,12 @@ 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;
@@ -1776,10 +1808,9 @@ make_thunk (function, delta)
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 ();
@@ -1795,259 +1826,127 @@ make_thunk (function, delta)
thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
if (thunk && TREE_CODE (thunk) != THUNK_DECL)
{
- error_with_decl ("implementation-reserved name `%s' used");
+ cp_error ("implementation-reserved name `%D' used", thunk_id);
IDENTIFIER_GLOBAL_VALUE (thunk_id) = thunk = NULL_TREE;
}
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;
+ TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
- 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. */
-
- 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);
+ 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 +1963,8 @@ largest_union_member (type)
}
/* Generate code for default X(X&) constructor. */
-void
+
+static void
do_build_copy_constructor (fndecl)
tree fndecl;
{
@@ -2080,7 +1980,7 @@ do_build_copy_constructor (fndecl)
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 +1999,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 +2017,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)))
@@ -2139,11 +2051,21 @@ do_build_copy_constructor (fndecl)
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (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
+ && TREE_CODE (t) == UNION_TYPE
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (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 +2079,7 @@ do_build_copy_constructor (fndecl)
pop_momentary ();
}
-void
+static void
do_build_assign_ref (fndecl)
tree fndecl;
{
@@ -2170,7 +2092,7 @@ do_build_assign_ref (fndecl)
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 +2106,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 +2121,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)))
@@ -2218,39 +2157,48 @@ do_build_assign_ref (fndecl)
&& TREE_CODE (t) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (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
+ && TREE_CODE (t) == UNION_TYPE
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (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 (at_eof)
+ import_export_decl (fndecl);
- if (nested)
+ 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 +2218,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/gnu/usr.bin/gcc/cp/parse.y b/gnu/usr.bin/gcc/cp/parse.y
index fd034af418d..0941e0f2b99 100644
--- a/gnu/usr.bin/gcc/cp/parse.y
+++ b/gnu/usr.bin/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, 96, 1997 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "lex.h"
#include "cp-tree.h"
#include "output.h"
+#include "except.h"
/* Since parsers are distinct for each language, put the language string
definition here. (fnf) */
@@ -55,13 +56,12 @@ extern int errno;
extern int end_of_file;
extern int current_class_depth;
+extern tree last_tree;
/* 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 +72,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,7 +87,8 @@ empty_parms ()
{
tree parms;
- if (strict_prototype)
+ if (strict_prototype
+ || current_class_type != NULL)
parms = void_list_node;
else
parms = NULL_TREE;
@@ -97,7 +98,7 @@ empty_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 +108,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 +123,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 +137,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 SIGOF
%token ATTRIBUTE EXTENSION LABEL
+%token REALPART IMAGPART
/* the reserved words... C++ extensions */
%token <ttype> AGGR
-%token <itype> VISSPEC
-%token DELETE NEW OVERLOAD THIS OPERATOR CXX_TRUE CXX_FALSE
+%token <ttype> 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 +165,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 +196,15 @@ empty_parms ()
%type <code> unop
%type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
-%type <ttype> paren_expr_or_null nontrivial_exprlist
+%type <ttype> PFUNCNAME
+%type <ttype> paren_expr_or_null nontrivial_exprlist SELFNAME
%type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
-%type <ttype> typed_declspecs reserved_declspecs boolean.literal
-%type <ttype> typed_typespecs reserved_typespecquals
-%type <ttype> declmods typespec typespecqual_reserved
-%type <ttype> SCSPEC TYPESPEC TYPE_QUAL nonempty_type_quals maybe_type_qual
+%type <ttype> reserved_declspecs boolean.literal
+%type <ttype> reserved_typespecquals
+%type <ttype> declmods
+%type <ttype> SCSPEC TYPESPEC CV_QUALIFIER maybe_cv_qualifier
%type <itype> initdecls notype_initdecls initdcl /* C++ modification */
-%type <ttype> init initlist maybeasm maybe_init
+%type <ttype> init initlist maybeasm maybe_init defarg defarg1
%type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
%type <ttype> any_word
@@ -207,36 +214,41 @@ empty_parms ()
%type <ttype> declarator notype_declarator after_type_declarator
%type <ttype> direct_notype_declarator direct_after_type_declarator
-%type <ttype> structsp opt.component_decl_list component_decl_list
+%type <ttype> opt.component_decl_list component_decl_list
%type <ttype> component_decl component_decl_1 components notype_components
-%type <ttype> component_declarator component_declarator0
+%type <ttype> component_declarator component_declarator0 self_reference
%type <ttype> notype_component_declarator notype_component_declarator0
%type <ttype> after_type_component_declarator after_type_component_declarator0
%type <ttype> enumlist enumerator
-%type <ttype> type_id absdcl type_quals
+%type <ttype> absdcl cv_qualifiers
%type <ttype> direct_abstract_declarator conversion_declarator
-%type <ttype> new_type_id new_declarator direct_new_declarator
-%type <ttype> xexpr parmlist parms parm bad_parm full_parm
+%type <ttype> new_declarator direct_new_declarator
+%type <ttype> xexpr parmlist parms bad_parm
%type <ttype> identifiers_or_typenames
%type <ttype> fcast_or_absdcl regcast_or_absdcl
%type <ttype> expr_or_declarator complex_notype_declarator
%type <ttype> notype_unqualified_id unqualified_id qualified_id
+%type <ttype> template_id object_template_id notype_template_declarator
%type <ttype> overqualified_id notype_qualified_id any_id
%type <ttype> complex_direct_notype_declarator functional_cast
-%type <ttype> named_parm complex_parmlist typed_declspecs1 parms_comma
+%type <ttype> complex_parmlist parms_comma
+
+%type <ftype> type_id new_type_id typed_typespecs typespec typed_declspecs
+%type <ftype> typed_declspecs1 type_specifier_seq nonempty_cv_qualifiers
+%type <ftype> structsp typespecqual_reserved parm named_parm full_parm
/* C++ extensions */
%token <ttype> TYPENAME_ELLIPSIS PTYPENAME
%token <ttype> PRE_PARSED_FUNCTION_DECL EXTERN_LANG_STRING ALL
-%token <ttype> PRE_PARSED_CLASS_DECL
-%type <ttype> fn.def1 /* Not really! */
-%type <ttype> fn.def2 return_id
+%token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
+%type <ttype> fn.def1 /* Not really! */ component_constructor_declarator
+%type <ttype> fn.def2 return_id fn.defpen constructor_declarator
%type <itype> ctor_initializer_opt
%type <ttype> named_class_head named_class_head_sans_basetype
%type <ttype> named_complex_class_head_sans_basetype
%type <ttype> unnamed_class_head
%type <ttype> class_head base_class_list
-%type <itype> base_class_access_list
+%type <ttype> base_class_access_list
%type <ttype> base_class maybe_base_class_list base_class.1
%type <ttype> exception_specification_opt ansi_raise_identifier ansi_raise_identifiers
%type <ttype> operator_name
@@ -247,43 +259,42 @@ empty_parms ()
%type <itype> initdcl0 notype_initdcl0 member_init_list
%type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type_parm
+%type <code> template_close_bracket
%type <ttype> template_type template_arg_list template_arg
-%type <ttype> template_instantiation template_type_name tmpl.2
-%type <ttype> template_instantiate_once template_instantiate_some
-%type <itype> fn_tmpl_end
-/* %type <itype> try_for_typename */
%type <ttype> condition xcond paren_cond_or_null
%type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
-%type <ttype> qualified_type_name complete_type_name notype_identifier
+%type <ttype> complete_type_name notype_identifier nonnested_type
%type <ttype> complex_type_name nested_name_specifier_1
%type <itype> nomods_initdecls nomods_initdcl0
-%type <ttype> new_initializer new_placement specialization type_specifier_seq
+%type <ttype> new_initializer new_placement
%type <ttype> using_decl .poplevel
-
-/* in order to recognize aggr tags as defining and thus shadowing. */
+%type <ttype> typename_sub typename_sub0 typename_sub1 typename_sub2
+/* in order to recognize aggr tags as defining and thus shadowing. */
%token TYPENAME_DEFN IDENTIFIER_DEFN PTYPENAME_DEFN
-%type <ttype> named_class_head_sans_basetype_defn
+%type <ttype> named_class_head_sans_basetype_defn
%type <ttype> identifier_defn IDENTIFIER_DEFN TYPENAME_DEFN PTYPENAME_DEFN
+%type <ttype> self_template_type
+
%token NSNAME
%type <ttype> 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;
+static tree current_declspecs = NULL_TREE;
/* 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. */
/* ??? It is not clear yet that all cases where an attribute can now appear in
a declspec list have been updated. */
-static tree prefix_attributes;
+static tree prefix_attributes = NULL_TREE;
/* When defining an aggregate, this is the most recent one being defined. */
static tree current_aggr;
@@ -291,12 +302,13 @@ 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));
%}
%%
-program: /* empty */
+program:
+ /* empty */
| extdefs
{
/* In case there were missing closebraces,
@@ -309,10 +321,11 @@ program: /* empty */
/* 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:
- { $<ttype>$ = NULL_TREE; } lang_extdef
+ { $<ttype>$ = NULL_TREE; }
+ lang_extdef
{ $<ttype>$ = NULL_TREE; }
| extdefs lang_extdef
{ $<ttype>$ = NULL_TREE; }
@@ -332,32 +345,37 @@ extdefs_opt:
{ have_extern_spec = 0; }
;
+extension:
+ EXTENSION
+ { $<itype>$ = 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
@@ -376,7 +394,13 @@ extdef:
| using_decl ';'
{ do_toplevel_using_decl ($1); }
| USING NAMESPACE any_id ';'
- { do_using_directive ($3); }
+ {
+ if (TREE_CODE ($3) == IDENTIFIER_NODE)
+ $3 = lastiddecl;
+ do_using_directive ($3);
+ }
+ | extension extdef
+ { pedantic = $<itype>1; }
;
using_decl:
@@ -411,6 +435,9 @@ template_header:
{ begin_template_parm_list (); }
template_parm_list '>'
{ $$ = end_template_parm_list ($4); }
+ | TEMPLATE '<' '>'
+ { begin_specialization();
+ $$ = NULL_TREE; }
;
template_parm_list:
@@ -428,7 +455,10 @@ template_type_parm:
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'");
+ {
+ pedwarn ("template type parameters must use the keyword `class'");
+ TREE_PURPOSE ($$) = class_type_node;
+ }
}
| aggr identifier
{ $$ = build_tree_list ($1, $2); goto ttpa; }
@@ -447,118 +477,32 @@ 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"); }
+ { $$ = 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); }
;
-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
+ extdef
+ {
+ if ($1)
+ end_template_decl ();
+ else
+ end_specialization ();
}
- | template_header /* notype_initdcl0 ';' */
- notype_declarator exception_specification_opt maybeasm maybe_attribute
- fn_tmpl_end
- {
- tree d;
- int momentary;
- int def = ($6 != ';');
- momentary = suspend_momentary ();
- d = start_decl ($<ttype>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 ($<ttype>3, specs, 0, $<ttype>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)
- {
- reinit_parse_for_template ((int) $7, $1, d);
- yychar = YYEMPTY;
- }
- note_list_got_semicolon ($<ttype>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 ($<ttype>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);
- }
- /* 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_header
+ error %prec EMPTY
+ {
+ if ($1)
+ end_template_decl ();
+ else
+ end_specialization ();
+ }
;
datadef:
@@ -566,50 +510,20 @@ datadef:
{}
| 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 ($<ttype>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 ($<ttype>$);
- }
- /* Normal case: make this fast. */
- | typed_declspecs declarator ';'
- { tree d, specs, attrs;
- split_specs_attrs ($1, &specs, &attrs);
- d = start_decl ($<ttype>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 ($<ttype>$);
+ 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 ($<ttype>$);
- }
+ {
+ tree t, attrs;
+ split_specs_attrs ($1.t, &t, &attrs);
+ shadow_tag (t);
+ note_list_got_semicolon ($1.t);
+ }
| error ';'
| error '}'
| ';'
@@ -635,79 +549,197 @@ eat_saved_input:
fndef:
fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
+ { finish_function (lineno, (int)$3, 0); }
+ | fn.def1 maybe_return_init function_try_block
+ { }
+ | fn.def1 maybe_return_init error
+ { }
+ ;
+
+constructor_declarator:
+ nested_name_specifier SELFNAME '('
{
- finish_function (lineno, (int)$3, 0);
- if ($<ttype>$) process_next_inline ($<ttype>$);
+ $$ = build_parse_node (SCOPE_REF, $1, $2);
+ if ($1 != current_class_type)
+ {
+ push_nested_class ($1, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
}
- | fn.def1 maybe_return_init function_try_block
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
+ | nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
{
- if ($<ttype>$) process_next_inline ($<ttype>$);
+ $$ = build_parse_node (SCOPE_REF, $1, $2);
+ if ($1 != current_class_type)
+ {
+ push_nested_class ($1, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ $$ = make_call_declarator ($$, empty_parms (), $4, $5);
+ }
+ | global_scope nested_name_specifier SELFNAME '('
+ {
+ $$ = build_parse_node (SCOPE_REF, $2, $3);
+ if ($2 != current_class_type)
+ {
+ push_nested_class ($2, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ }
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
+ | global_scope nested_name_specifier SELFNAME LEFT_RIGHT cv_qualifiers exception_specification_opt
+ {
+ $$ = build_parse_node (SCOPE_REF, $2, $3);
+ if ($2 != current_class_type)
+ {
+ push_nested_class ($2, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ $$ = make_call_declarator ($$, empty_parms (), $5, $6);
+ }
+ | nested_name_specifier self_template_type '('
+ {
+ $$ = build_parse_node (SCOPE_REF, $1, $2);
+ if ($1 != current_class_type)
+ {
+ push_nested_class ($1, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ }
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>4, $5, $7, $8); }
+ | nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
+ {
+ $$ = build_parse_node (SCOPE_REF, $1, $2);
+ if ($1 != current_class_type)
+ {
+ push_nested_class ($1, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ $$ = make_call_declarator ($$, empty_parms (), $4, $5);
+ }
+ | global_scope nested_name_specifier self_template_type '('
+ {
+ $$ = build_parse_node (SCOPE_REF, $2, $3);
+ if ($2 != current_class_type)
+ {
+ push_nested_class ($2, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ }
+ parmlist ')' cv_qualifiers exception_specification_opt
+ { $$ = make_call_declarator ($<ttype>5, $6, $8, $9); }
+ | global_scope nested_name_specifier self_template_type LEFT_RIGHT cv_qualifiers exception_specification_opt
+ {
+ $$ = build_parse_node (SCOPE_REF, $2, $3);
+ if ($2 != current_class_type)
+ {
+ push_nested_class ($2, 3);
+ TREE_COMPLEXITY ($$) = current_class_depth;
+ }
+ $$ = 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
+ typed_declspecs declarator
+ { tree specs, attrs;
+ split_specs_attrs ($1.t, &specs, &attrs);
+ if (! start_function (specs, $2, attrs, 0))
+ YYERROR1;
+ reinit_parse_for_function ();
+ $$ = NULL_TREE; }
+ | declmods notype_declarator
{ tree specs, attrs;
split_specs_attrs ($1, &specs, &attrs);
- if (! start_function (specs, $2, $3, attrs, 0))
+ if (! start_function (specs, $2, 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))
+ | notype_declarator
+ { if (! start_function (NULL_TREE, $$, NULL_TREE, 0))
YYERROR1;
reinit_parse_for_function ();
$$ = NULL_TREE; }
- | notype_declarator exception_specification_opt
- { if (! start_function (NULL_TREE, $$, $2, NULL_TREE, 0))
+ | declmods constructor_declarator
+ { tree specs, attrs;
+ split_specs_attrs ($1, &specs, &attrs);
+ if (! start_function (specs, $2, attrs, 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 (); }
+ | constructor_declarator
+ { if (! start_function (NULL_TREE, $$, NULL_TREE, 0))
+ YYERROR1;
+ reinit_parse_for_function ();
+ $$ = NULL_TREE; }
+ ;
+
+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; }
+ | template_header fn.def2
+ {
+ if ($1)
+ end_template_decl ();
+ else
+ end_specialization ();
+
+ if ($2 && DECL_TEMPLATE_INFO ($2)
+ && !DECL_TEMPLATE_SPECIALIZATION ($2))
+ {
+ $$ = DECL_TI_TEMPLATE ($2);
+ check_member_template ($$);
+ }
+ else if ($2)
+ $$ = $2;
+ else
+ {
+ cp_error("invalid member template declaration");
+ $$ = NULL_TREE;
+ }
+ }
;
-return_id: RETURN IDENTIFIER
+return_id:
+ RETURN IDENTIFIER
{
if (! current_function_parms_stored)
store_parm_decls ();
@@ -715,7 +747,8 @@ return_id: RETURN IDENTIFIER
}
;
-return_init: return_id maybe_init
+return_init:
+ return_id maybe_init
{ store_return_init ($<ttype>$, $2); }
| return_id '(' nonnull_exprlist ')'
{ store_return_init ($<ttype>$, $3); }
@@ -730,14 +763,14 @@ base_init:
error ("no base initializers given following ':'");
setup_vtbl_ptr ();
/* Always keep the BLOCK node associated with the outermost
- pair of curley braces of a function. These are needed
+ pair of curly braces of a function. These are needed
for correct operation of dwarfout.c. */
keep_next_level ();
}
;
.set_base_init:
- /* empty */
+ /* empty */
{
if (! current_function_parms_stored)
store_parm_decls ();
@@ -765,40 +798,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, $<ttype>$, $3); }
+ { expand_member_init (current_class_ref, $1, $3); }
| notype_identifier LEFT_RIGHT
- { expand_member_init (C_C_D, $<ttype>$, void_type_node); }
- | complete_type_name '(' nonnull_exprlist ')'
- { expand_member_init (C_C_D, $<ttype>$, $3); }
- | complete_type_name LEFT_RIGHT
- { expand_member_init (C_C_D, $<ttype>$, 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 +838,7 @@ identifier:
notype_identifier:
IDENTIFIER
| PTYPENAME
- | NSNAME %prec EMPTY
+ | NSNAME %prec EMPTY
;
identifier_defn:
@@ -816,39 +848,83 @@ identifier_defn:
;
explicit_instantiation:
- TEMPLATE specialization template_instantiation
- { do_type_instantiation ($3 ? $3 : $2, NULL_TREE); }
+ TEMPLATE typespec ';'
+ { do_type_instantiation ($2.t, NULL_TREE);
+ yyungetc (';', 1); }
| TEMPLATE typed_declspecs declarator
- { tree specs = strip_attrs ($2);
- do_function_instantiation (specs, $3, NULL_TREE); }
+ { tree specs = strip_attrs ($2.t);
+ do_decl_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); }
+ { do_decl_instantiation (NULL_TREE, $2, NULL_TREE); }
+ | TEMPLATE constructor_declarator
+ { do_decl_instantiation (NULL_TREE, $2, NULL_TREE); }
+ | SCSPEC TEMPLATE typespec ';'
+ { do_type_instantiation ($3.t, $1);
+ yyungetc (';', 1); }
| SCSPEC TEMPLATE typed_declspecs declarator
- { tree specs = strip_attrs ($3);
- do_function_instantiation (specs, $4, $1); }
+ { tree specs = strip_attrs ($3.t);
+ do_decl_instantiation (specs, $4, $1); }
| SCSPEC TEMPLATE notype_declarator
- { do_function_instantiation (NULL_TREE, $3, $1); }
+ { do_decl_instantiation (NULL_TREE, $3, $1); }
+ | SCSPEC TEMPLATE constructor_declarator
+ { do_decl_instantiation (NULL_TREE, $3, $1); }
;
+/* 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 template_close_bracket
+ {
+ $$ = lookup_template_class ($1, $3, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
+ | PTYPENAME '<' template_close_bracket
+ {
+ $$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
+ | TYPENAME '<' template_arg_list template_close_bracket
+ {
+ $$ = lookup_template_class ($1, $3, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
+ | TYPENAME '<' template_close_bracket
+ {
+ $$ = lookup_template_class ($1, 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 template_close_bracket
+ {
+ $$ = lookup_template_class ($1, $3, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
+ | SELFNAME '<' template_close_bracket
+ {
+ $$ = lookup_template_class ($1, NULL_TREE, NULL_TREE);
+ if ($$ != error_mark_node)
+ $$ = TYPE_STUB_DECL ($$);
+ }
;
-tmpl.2:
- /* empty */ %prec EMPTY
- { $$ = instantiate_class_template ($<ttype>0, 1); }
+template_close_bracket:
+ '>'
+ | RSHIFT
+ {
+ /* Handle `Class<Class<Type>>' without space in the `>>' */
+ pedwarn ("`>>' should be `> >' in template class name");
+ yyungetc ('>', 1);
+ }
;
template_arg_list:
@@ -860,77 +936,12 @@ 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);
- $<ttype>$ = 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 ($<ttype>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); }
+ | 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 +953,8 @@ unop: '-'
{ $$ = TRUTH_NOT_EXPR; }
;
-expr: nontrivial_exprlist
+expr:
+ nontrivial_exprlist
{ $$ = build_x_compound_expr ($$); }
| expr_no_commas
;
@@ -966,7 +978,7 @@ paren_cond_or_null:
;
xcond:
- /* empty */
+ /* empty */
{ $$ = NULL_TREE; }
| condition
{ $$ = condition_conversion ($$); }
@@ -975,7 +987,7 @@ xcond:
;
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 +999,17 @@ condition:
cp_error ("definition of enum `%T' in condition", s);
}
}
- current_declspecs = $1;
- $<itype>6 = suspend_momentary ();
- $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1, $3);
- cplus_decl_attributes ($<ttype>$, $5,
+ current_declspecs = $1.t;
+ $<itype>5 = suspend_momentary ();
+ $<ttype>$ = start_decl ($<ttype>2, current_declspecs, 1);
+ cplus_decl_attributes ($<ttype>$, $4,
/*prefix_attributes*/ NULL_TREE);
}
- init
+ init
{
- cp_finish_decl ($<ttype>7, $8, $5, 0, LOOKUP_ONLYCONVERTING);
- resume_momentary ($<itype>6);
- $$ = $<ttype>7;
+ cp_finish_decl ($<ttype>6, $7, $4, 1, LOOKUP_ONLYCONVERTING);
+ resume_momentary ($<itype>5);
+ $$ = $<ttype>6;
if (TREE_CODE (TREE_TYPE ($$)) == ARRAY_TYPE)
cp_error ("definition of array `%#D' in condition", $$);
}
@@ -1012,45 +1024,54 @@ compstmtend:
;
already_scoped_stmt:
- '{' compstmtend
- { finish_stmt (); }
+ '{'
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
+ COMPOUND_STMT_NO_SCOPE ($<ttype>$) = 1;
+ add_tree ($<ttype>$);
+ }
+ }
+ compstmtend
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ finish_stmt ();
+ }
| 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
- { $<itype>1 = pedantic;
- pedantic = 0; }
- cast_expr %prec UNARY
- { $$ = $3;
+ | extension cast_expr %prec UNARY
+ { $$ = $2;
pedantic = $<itype>1; }
| '*' cast_expr %prec UNARY
{ $$ = build_x_indirect_ref ($2, "unary *"); }
@@ -1067,6 +1088,8 @@ unary_expr:
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
{ tree label = lookup_label ($2);
+ if (pedantic)
+ pedwarn ("ANSI C++ forbids `&&'");
if (label == NULL_TREE)
$$ = null_pointer_node;
else
@@ -1077,53 +1100,42 @@ unary_expr:
}
}
| 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); }
+ { $$ = build_new ($2, $3.t, $4, $1);
+ check_for_new_type ("new", $3); }
+ | new '(' type_id ')' %prec EMPTY
+ { $$ = build_new (NULL_TREE, groktypename($3.t),
+ NULL_TREE, $1);
+ check_for_new_type ("new", $3); }
| 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); }
+ { $$ = build_new (NULL_TREE, groktypename($3.t), $5, $1);
+ check_for_new_type ("new", $3); }
+ | new new_placement '(' type_id ')' %prec EMPTY
+ { $$ = build_new ($2, groktypename($4.t), NULL_TREE, $1);
+ check_for_new_type ("new", $4); }
| new new_placement '(' type_id ')' new_initializer
- { $$ = build_new ($2, groktypename($4), $6, $1); }
+ { $$ = build_new ($2, groktypename($4.t), $6, $1);
+ check_for_new_type ("new", $4); }
| delete cast_expr %prec UNARY
{ $$ = delete_sanity ($2, NULL_TREE, 0, $1); }
@@ -1131,10 +1143,14 @@ 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); }
;
new_placement:
@@ -1154,7 +1170,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
@@ -1170,15 +1186,16 @@ new_initializer:
/* 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 = tree_cons (NULL_TREE, $2.t, void_list_node);
+ TREE_PARMLIST ($2.t) = 1;
+ $$ = 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 = tree_cons (NULL_TREE, $3.t, void_list_node);
+ TREE_PARMLIST ($3.t) = 1;
+ $$ = make_call_declarator ($$, $3.t, NULL_TREE, NULL_TREE);
+ check_for_new_type ("cast", $3); }
;
cast_expr:
@@ -1242,15 +1259,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 +1271,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 +1286,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
+ ;
+
+template_id:
+ PFUNCNAME '<' template_arg_list template_close_bracket
+ { $$ = lookup_template_function ($1, $3); }
+ | PFUNCNAME '<' template_close_bracket
+ { $$ = lookup_template_function ($1, NULL_TREE); }
+ | operator_name '<' template_arg_list template_close_bracket
+ { $$ = lookup_template_function
+ (do_identifier ($1, 1), $3); }
+ | operator_name '<' template_close_bracket
+ { $$ = lookup_template_function
+ (do_identifier ($1, 1), NULL_TREE); }
+ ;
+
+object_template_id:
+ TEMPLATE identifier '<' template_arg_list template_close_bracket
+ { $$ = lookup_template_function ($2, $4); }
+ | TEMPLATE PFUNCNAME '<' template_arg_list template_close_bracket
+ { $$ = lookup_template_function (DECL_NAME ($2), $4); }
+ | TEMPLATE operator_name '<' template_arg_list template_close_bracket
+ { $$ = lookup_template_function (DECL_NAME ($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 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
+ | notype_template_declarator
| '(' expr_or_declarator ')'
{ $$ = finish_decl_parsing ($2); }
;
@@ -1306,32 +1351,26 @@ primary:
{
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 ($$);
+ else if (TREE_CODE ($$) != TEMPLATE_ID_EXPR)
+ $$ = do_identifier ($$, 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. */
+ /* This inhibits warnings in truthvalue_conversion. */
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
| '(' expr_or_declarator ')'
{ char class;
@@ -1339,7 +1378,7 @@ primary:
class = TREE_CODE_CLASS (TREE_CODE ($$));
if (class == 'e' || class == '1'
|| class == '2' || class == '<')
- /* This inhibits warnings in truthvalue_conversion. */
+ /* This inhibits warnings in truthvalue_conversion. */
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
| '(' error ')'
{ $$ = error_mark_node; }
@@ -1373,20 +1412,15 @@ primary:
$$ = $3;
}
| primary '(' nonnull_exprlist ')'
- { /* [eichin:19911016.1902EST] */
- $<ttype>$ = 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 ($<ttype>5) == CALL_EXPR
- && TREE_TYPE ($<ttype>5) != void_type_node)
- $$ = require_complete_type ($<ttype>5);
- else
- $$ = $<ttype>5;
+ {
+ $$ = build_x_function_call ($1, $3, current_class_ref);
+ if (TREE_CODE ($$) == CALL_EXPR
+ && TREE_TYPE ($$) != void_type_node)
+ $$ = require_complete_type ($$);
}
| primary LEFT_RIGHT
{
- $$ = build_x_function_call ($$, NULL_TREE, current_class_decl);
+ $$ = build_x_function_call ($$, NULL_TREE, current_class_ref);
if (TREE_CODE ($$) == CALL_EXPR
&& TREE_TYPE ($$) != void_type_node)
$$ = require_complete_type ($$);
@@ -1408,12 +1442,12 @@ primary:
$$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); }
/* C++ extensions */
| THIS
- { if (current_class_decl)
+ { if (current_class_ptr)
{
#ifdef WARNING_ABOUT_CCD
- TREE_USED (current_class_decl) = 1;
+ TREE_USED (current_class_ptr) = 1;
#endif
- $$ = current_class_decl;
+ $$ = current_class_ptr;
}
else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
@@ -1430,7 +1464,7 @@ primary:
$$ = error_mark_node;
}
}
- | TYPE_QUAL '(' nonnull_exprlist ')'
+ | CV_QUALIFIER '(' nonnull_exprlist ')'
{
tree type;
tree id = $$;
@@ -1471,153 +1505,124 @@ 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 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); }
+ { if (processing_template_decl)
+ $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1), $3, NULL_TREE);
+ else
+ $$ = build_member_call (OP0 ($$), OP1 ($$), $3); }
| overqualified_id LEFT_RIGHT
- { $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
+ { if (processing_template_decl)
+ $$ = build_min_nt (CALL_EXPR, copy_to_permanent ($1),
+ NULL_TREE, NULL_TREE);
+ else
+ $$ = build_member_call (OP0 ($$), OP1 ($$), NULL_TREE); }
+ | object object_template_id %prec UNARY
+ {
+ $$ = build_x_component_ref ($$, $2, NULL_TREE, 1);
+ }
+ | object object_template_id '(' nonnull_exprlist ')'
+ {
+ $$ = build_method_call ($1, $2, $4,
+ NULL_TREE, LOOKUP_NORMAL);
+ }
+ | object object_template_id LEFT_RIGHT
+ {
+ $$ = build_method_call ($1, $2, NULL_TREE,
+ NULL_TREE, LOOKUP_NORMAL);
+ }
| 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, $$);
+ in build_component_ref entirely yet, we cannot do this. */
+ $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, current_class_ref);
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));
+ LOOKUP_NORMAL);
#endif
}
| 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, $$);
+ in build_component_ref entirely yet, we cannot do this. */
+ $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, current_class_ref);
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));
+ LOOKUP_NORMAL);
#endif
}
| object overqualified_id '(' nonnull_exprlist ')'
{
- got_object = NULL_TREE;
- if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
+ if (IS_SIGNATURE (OP0 ($2)))
{
warning ("signature name in scope resolution ignored");
$$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
+ LOOKUP_NORMAL);
}
else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
}
| object overqualified_id LEFT_RIGHT
{
- got_object = NULL_TREE;
- if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (OP0 ($2))))
+ if (IS_SIGNATURE (OP0 ($2)))
{
warning ("signature name in scope resolution ignored");
$$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE,
- (LOOKUP_NORMAL|LOOKUP_AGGR));
+ LOOKUP_NORMAL);
}
else
$$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE);
@@ -1625,26 +1630,23 @@ primary:
/* 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);
+ $$ = cp_convert (void_type_node, $1);
}
| 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);
+ $$ = cp_convert (void_type_node, $1);
}
| object error
{
- got_object = NULL_TREE;
$$ = error_mark_node;
}
;
@@ -1668,9 +1670,9 @@ primary_no_id:
pedwarn ("ANSI C++ forbids braced-groups within expressions");
$$ = expand_end_stmt_expr ($<ttype>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 +1689,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; }
@@ -1720,13 +1724,14 @@ nodecls:
store_parm_decls ();
setup_vtbl_ptr ();
/* Always keep the BLOCK node associated with the outermost
- pair of curley braces of a function. These are needed
+ pair of curly braces of a function. These are needed
for correct operation of dwarfout.c. */
keep_next_level ();
}
;
-object: primary '.'
+object:
+ primary '.'
{ got_object = TREE_TYPE ($$); }
| primary POINTSAT
{
@@ -1736,79 +1741,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 = $<itype>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 +1808,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 +1841,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 +1859,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 +1886,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
;
@@ -1980,10 +1987,11 @@ maybeasm:
;
initdcl0:
- declarator exception_specification_opt maybeasm maybe_attribute '='
+ declarator maybeasm maybe_attribute '='
{ split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
- if (TREE_CODE (current_declspecs) != TREE_LIST)
+ if (current_declspecs
+ && TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = get_decl_list (current_declspecs);
if (have_extern_spec && !used_extern_spec)
{
@@ -1992,18 +2000,19 @@ initdcl0:
current_declspecs);
used_extern_spec = 1;
}
- $<itype>5 = suspend_momentary ();
- $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
+ $<itype>4 = suspend_momentary ();
+ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1);
+ cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING);
- $$ = $<itype>5; }
- | declarator exception_specification_opt maybeasm maybe_attribute
+ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING);
+ $$ = $<itype>4; }
+ | declarator maybeasm maybe_attribute
{ tree d;
split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
- if (TREE_CODE (current_declspecs) != TREE_LIST)
+ if (current_declspecs
+ && TREE_CODE (current_declspecs) != TREE_LIST)
current_declspecs = get_decl_list (current_declspecs);
if (have_extern_spec && !used_extern_spec)
{
@@ -2013,70 +2022,70 @@ initdcl0:
used_extern_spec = 1;
}
$$ = suspend_momentary ();
- d = start_decl ($<ttype>1, current_declspecs, 0, $2);
- cplus_decl_attributes (d, $4, prefix_attributes);
- cp_finish_decl (d, NULL_TREE, $3, 0, 0); }
+ d = start_decl ($<ttype>1, current_declspecs, 0);
+ cplus_decl_attributes (d, $3, prefix_attributes);
+ cp_finish_decl (d, NULL_TREE, $2, 1, 0); }
;
initdcl:
- declarator exception_specification_opt maybeasm maybe_attribute '='
- { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
+ declarator maybeasm maybe_attribute '='
+ { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1);
+ cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING); }
- | declarator exception_specification_opt maybeasm maybe_attribute
- { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes);
- cp_finish_decl ($<ttype>$, NULL_TREE, $3, 0, 0); }
+ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING); }
+ | declarator maybeasm maybe_attribute
+ { $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 0);
+ cplus_decl_attributes ($<ttype>$, $3, prefix_attributes);
+ cp_finish_decl ($<ttype>$, NULL_TREE, $2, 1, 0); }
;
notype_initdcl0:
- notype_declarator exception_specification_opt maybeasm maybe_attribute '='
+ notype_declarator maybeasm maybe_attribute '='
{ split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
- $<itype>5 = suspend_momentary ();
- $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
+ $<itype>4 = suspend_momentary ();
+ $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1);
+ cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING);
- $$ = $<itype>5; }
- | notype_declarator exception_specification_opt maybeasm maybe_attribute
+ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING);
+ $$ = $<itype>4; }
+ | notype_declarator maybeasm maybe_attribute
{ tree d;
split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
$$ = suspend_momentary ();
- d = start_decl ($<ttype>1, current_declspecs, 0, $2);
- cplus_decl_attributes (d, $4, prefix_attributes);
- cp_finish_decl (d, NULL_TREE, $3, 0, 0); }
+ d = start_decl ($<ttype>1, current_declspecs, 0);
+ cplus_decl_attributes (d, $3, prefix_attributes);
+ cp_finish_decl (d, NULL_TREE, $2, 1, 0); }
;
nomods_initdcl0:
- notype_declarator exception_specification_opt maybeasm maybe_attribute '='
+ notype_declarator maybeasm maybe_attribute '='
{ current_declspecs = NULL_TREE;
prefix_attributes = NULL_TREE;
- $<itype>5 = suspend_momentary ();
- $<ttype>$ = start_decl ($1, current_declspecs, 1, $2);
- cplus_decl_attributes ($<ttype>$, $4, prefix_attributes); }
+ $<itype>4 = suspend_momentary ();
+ $<ttype>$ = start_decl ($1, current_declspecs, 1);
+ cplus_decl_attributes ($<ttype>$, $3, prefix_attributes); }
init
/* Note how the declaration of the variable is in effect while its init is parsed! */
- { cp_finish_decl ($<ttype>6, $7, $3, 0, LOOKUP_ONLYCONVERTING);
- $$ = $<itype>5; }
- | notype_declarator exception_specification_opt maybeasm maybe_attribute
+ { cp_finish_decl ($<ttype>5, $6, $2, 1, LOOKUP_ONLYCONVERTING);
+ $$ = $<itype>4; }
+ | notype_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); }
+ d = start_decl ($1, current_declspecs, 0);
+ cplus_decl_attributes (d, $3, prefix_attributes);
+ 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 +2111,7 @@ attribute_list:
;
attrib:
- /* empty */
+ /* empty */
{ $$ = NULL_TREE; }
| any_word
{ $$ = build_tree_list ($1, NULL_TREE); }
@@ -2121,25 +2130,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 +2171,152 @@ 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); }
+ { $$ = build_expr_list ($2, $4); }
| initlist ',' CASE expr_no_commas ':' init
- { $$ = tree_cons ($4, $6, $$); }
+ { $$ = expr_tree_cons ($4, $6, $$); }
| 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 '{'
{ $<itype>3 = suspend_momentary ();
- $$ = start_enum ($2); }
+ $<ttype>$ = start_enum ($2); }
enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>4, $5);
+ { $$.t = finish_enum ($<ttype>4, $5);
+ $$.new_type_flag = 1;
resume_momentary ((int) $<itype>3);
check_for_missing_semicolon ($<ttype>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 '{'
{ $<itype>2 = suspend_momentary ();
- $$ = start_enum (make_anon_name ()); }
+ $<ttype>$ = start_enum (make_anon_name ()); }
enumlist maybecomma_warn '}'
- { $$ = finish_enum ($<ttype>3, $4);
+ { $$.t = finish_enum ($<ttype>3, $4);
resume_momentary ((int) $<itype>1);
- check_for_missing_semicolon ($<ttype>3); }
+ check_for_missing_semicolon ($<ttype>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
+ { reset_specialization(); }
+ opt.component_decl_list '}' maybe_attribute
{
int semi;
tree id;
+ $<ttype>$ = $1;
#if 0
/* Need to rework class nesting in the
presence of nested classes, etc. */
- shadow_tag (CLASSTYPE_AS_LIST ($$)); */
+ shadow_tag (CLASSTYPE_AS_LIST ($1)); */
#endif
if (yychar == YYEMPTY)
yychar = YYLEX;
semi = yychar == ';';
/* finish_struct nukes this anyway; if
- finish_exception does too, then it can go. */
+ finish_exception does too, then it can go. */
if (semi)
- note_got_semicolon ($$);
+ note_got_semicolon ($1);
- if (TREE_CODE ($$) == ENUMERAL_TYPE)
- /* $$ = $1 from default rule. */;
+ if (TREE_CODE ($1) == ENUMERAL_TYPE)
+ ;
else
{
- $$ = finish_struct ($$, $3, semi);
- if (semi) note_got_semicolon ($$);
+ $<ttype>$ = finish_struct ($1, $4, $6, semi);
+ if (semi) note_got_semicolon ($<ttype>$);
}
pop_obstacks ();
- id = TYPE_IDENTIFIER ($$);
- if (id && IDENTIFIER_TEMPLATE (id))
- {
- 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);
- }
if (! semi)
- check_for_missing_semicolon ($$); }
+ check_for_missing_semicolon ($1);
+ if (current_scope () == current_function_decl)
+ do_pending_defargs ();
+ }
+ pending_defargs
+ {
+ if (pending_inlines
+ && current_scope () == current_function_decl)
+ do_pending_inlines ();
+ }
+ pending_inlines
+ {
+ $$.t = $<ttype>7;
+ $$.new_type_flag = 1;
+ if (current_class_type == NULL_TREE)
+ clear_inline_text_obstack ();
+ }
| class_head %prec EMPTY
{
+ $$.t = $1;
+ $$.new_type_flag = 0;
/* struct B: public A; is not accepted by the WP grammar. */
- if (TYPE_BINFO_BASETYPES ($$) && !TYPE_SIZE ($$)
- && ! TYPE_BEING_DEFINED ($$))
+ if (TYPE_BINFO_BASETYPES ($$.t) && !TYPE_SIZE ($$.t)
+ && ! TYPE_BEING_DEFINED ($$.t))
cp_error ("base clause without member specification for `%#T'",
- $$);
+ $$.t);
}
;
@@ -2265,64 +2328,64 @@ 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 ($<ttype>0 == ridpointers[(int) RID_TEMPLATE])
- instantiate_class_template ($$, 2);
- }
- ;
-
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_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
- { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
+do_xref_defn:
+ /* empty */ %prec EMPTY
+ { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 0); }
;
named_class_head:
- named_class_head_sans_basetype %prec EMPTY
+ 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
{
$$ = $<ttype>2;
if ($3)
@@ -2331,22 +2394,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; }
@@ -2361,9 +2448,8 @@ base_class_list:
base_class:
base_class.1
{
- tree type;
- type = IDENTIFIER_TYPE_VALUE ($$);
- if (! is_aggr_typedef ($$, 1))
+ tree 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 +2461,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 +2469,14 @@ 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);
+ tree 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))
$$ = NULL_TREE;
else if (current_aggr == signature_type_node
&& (! type) && (! IS_SIGNATURE (type)))
@@ -2403,7 +2488,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 +2496,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 +2511,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 +2529,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
{
@@ -2468,51 +2553,53 @@ base_class_access_list:
| SCSPEC see_typename
{ if ($<ttype>$ != ridpointers[(int)RID_VIRTUAL])
sorry ("non-virtual access");
- $$ = access_default_virtual; }
+ $$ = access_default_virtual_node; }
| base_class_access_list VISSPEC see_typename
{ int err = 0;
- if ($2 == access_protected)
+ if ($2 == access_protected_node)
{
warning ("`protected' access not implemented");
- $2 = access_public;
+ $2 = access_public_node;
err++;
}
- else if ($2 == access_public)
+ else if ($2 == access_public_node)
{
- if ($1 == access_private)
+ if ($1 == access_private_node)
{
mixed:
error ("base class cannot be public and private");
}
- else if ($1 == access_default_virtual)
- $$ = access_public_virtual;
+ else if ($1 == access_default_virtual_node)
+ $$ = access_public_virtual_node;
}
- else /* $2 == access_private */
+ else /* $2 == access_private_node */
{
- if ($1 == access_public)
+ if ($1 == access_public_node)
goto mixed;
- else if ($1 == access_default_virtual)
- $$ = access_private_virtual;
+ else if ($1 == access_default_virtual_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; }
+ if ($$ == access_public_node)
+ $$ = access_public_virtual_node;
+ else if ($$ == access_private_node)
+ $$ = access_private_virtual_node; }
;
-left_curly: '{'
+left_curly:
+ '{'
{ tree t = $<ttype>0;
push_obstacks_nochange ();
end_temporary_allocation ();
- if (! IS_AGGR_TYPE (t))
+ if (t == error_mark_node
+ || ! IS_AGGR_TYPE (t))
{
t = $<ttype>0 = make_lang_type (RECORD_TYPE);
- TYPE_NAME (t) = get_identifier ("erroneous type");
+ pushtag (make_anon_name (), t, 0);
}
if (TYPE_SIZE (t))
duplicate_tag_error (t);
@@ -2522,8 +2609,23 @@ left_curly: '{'
pushtag (TYPE_IDENTIFIER ($<ttype>0), t, 0);
$<ttype>0 = t;
}
+ if (processing_template_decl && TYPE_CONTEXT (t)
+ && ! current_class_type)
+ push_template_decl (TYPE_STUB_DECL (t));
pushclass (t, 0);
TYPE_BEING_DEFINED (t) = 1;
+ if (IS_AGGR_TYPE (t) && CLASSTYPE_USE_TEMPLATE (t))
+ {
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
+ && TYPE_SIZE (t) == NULL_TREE)
+ {
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
+ if (processing_template_decl)
+ push_template_decl (TYPE_MAIN_DECL (t));
+ }
+ else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
+ cp_error ("specialization after instantiation of `%T'", t);
+ }
/* Reset the interface data, at the earliest possible
moment, as it might have been set via a class foo;
before. */
@@ -2570,24 +2672,32 @@ left_curly: '{'
}
;
+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 +2747,9 @@ component_decl:
{ $$ = finish_method ($$); }
| ';'
{ $$ = NULL_TREE; }
+ | extension component_decl
+ { $$ = $2;
+ pedantic = $<itype>1; }
;
component_decl_1:
@@ -2644,12 +2757,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 +2779,39 @@ 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); }
- ;
+ | template_header component_decl_1
+ {
+ if ($1)
+ end_template_decl ();
+ else
+ end_specialization ();
+
+ if ($2 && DECL_TEMPLATE_INFO ($2)
+ && !DECL_TEMPLATE_SPECIALIZATION ($2))
+ {
+ $$ = DECL_TI_TEMPLATE ($2);
+ check_member_template ($$);
+ }
+ else if ($2)
+ $$ = $2;
+ else
+ {
+ cp_error("invalid member template declaration");
+ $$ = NULL_TREE;
+ }
+ }
-/* 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 +2854,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 ($<ttype>0, &current_declspecs,
&prefix_attributes);
$<ttype>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 ($<ttype>0, &current_declspecs,
&prefix_attributes);
@@ -2739,12 +2869,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 ($<ttype>0, &current_declspecs,
&prefix_attributes);
$<ttype>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)); }
+ | constructor_declarator maybeasm maybe_attribute maybe_init
+ { split_specs_attrs ($<ttype>0, &current_declspecs,
+ &prefix_attributes);
+ $<ttype>0 = current_declspecs;
+ $$ = grokfield ($$, current_declspecs, $4, $2,
+ build_tree_list ($3, prefix_attributes)); }
| IDENTIFIER ':' expr_no_commas maybe_attribute
{ split_specs_attrs ($<ttype>0, &current_declspecs,
&prefix_attributes);
@@ -2760,18 +2896,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 +2936,50 @@ 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 ']'
{
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 ($2.t), $5);
+ $$.t = build_decl_list (TREE_PURPOSE ($2.t), $$.t);
+ $$.new_type_flag = $2.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:
- { $<itype>$ = suspend_momentary (); }
+ /* empty */
+ { $<itype>$ = suspend_momentary (); }
/* An expression which will not live on the momentary obstack. */
nonmomentary_expr:
- suspend_mom expr
- { resume_momentary ((int) $<itype>1); $$ = $2; }
+ suspend_mom expr
+ { resume_momentary ((int) $<itype>1); $$ = $2; }
;
/* An expression which will not live on the momentary obstack. */
@@ -2855,72 +2997,93 @@ 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);
+ if (current_class_type
+ && TYPE_BEING_DEFINED (current_class_type)
+ && ! IDENTIFIER_CLASS_VALUE ($1))
+ {
+ /* Be sure to get an inherited typedef. */
+ $$ = lookup_name ($1, 1);
+ /* Remember that this name has been used in the class
+ definition, as per [class.scope0] */
+ pushdecl_class_level ($$);
+ }
+ else
+ $$ = identifier_typedecl_value ($1);
}
+ else
+ $$ = $1;
+ }
+ | global_scope type_name
+ {
+ if (TREE_CODE ($2) == IDENTIFIER_NODE)
+ $$ = identifier_typedecl_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 +3091,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 +3107,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 +3116,39 @@ 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 (OP0 ($$) != current_class_type)
{
- push_nested_class (TREE_TYPE (OP0 ($$)), 3);
+ push_nested_class (OP0 ($$), 3);
+ TREE_COMPLEXITY ($$) = 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,16 +3159,17 @@ 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:
@@ -3003,11 +3182,33 @@ nested_name_specifier:
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 = $$ = 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 +3221,77 @@ 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
+ {
+ 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;
+ }
+ ;
+
+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;
+ }
+ ;
+
+typename_sub2:
+ TYPENAME SCOPE
+ {
+ if (TREE_CODE ($1) != IDENTIFIER_NODE)
+ $$ = lastiddecl;
+ got_scope = $$ = complete_type (TREE_TYPE ($$));
+ }
+ | 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 = $$;
+ }
+ ;
+
complex_type_name:
- nested_type
- | global_scope qualified_type_name
+ global_scope type_name
+ {
+ if (TREE_CODE ($2) == IDENTIFIER_NODE)
+ $$ = identifier_typedecl_value ($2);
+ else
+ $$ = $2;
+ got_scope = NULL_TREE;
+ }
+ | nested_type
+ | global_scope nested_type
{ $$ = $2; }
;
@@ -3040,7 +3303,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 +3311,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 +3340,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 +3373,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 +3404,22 @@ stmts:
| stmts errstmt
;
-errstmt: error ';'
+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); }
+.pushlevel:
+ /* empty */
+ { do_pushlevel (); }
;
-.poplevel: /* empty */
- { expand_end_bindings (getdecls (), kept_level_p (), 1);
- $$ = poplevel (kept_level_p (), 1, 0);
- pop_momentary (); }
+.poplevel:
+ /* empty */
+ { $$ = do_poplevel (); }
;
/* Read zero or more forward-declarations for labels
@@ -3196,24 +3456,89 @@ compstmt_or_error:
| error compstmt
;
-compstmt: '{' .pushlevel compstmtend .poplevel
- { $$ = $4; }
+compstmt:
+ '{'
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ }
+ .pushlevel compstmtend .poplevel
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ $$ = $5;
+ }
;
simple_if:
IF
- { cond_stmt_keyword = "if"; }
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE,
+ NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ cond_stmt_keyword = "if";
+ }
.pushlevel paren_cond_or_null
- { emit_line_note (input_filename, lineno);
- expand_start_cond ($4, 0); }
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != $<ttype>2)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = last_tree;
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ TREE_OPERAND ($<ttype>2, 0) = $4;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_start_cond ($4, 0);
+ }
+ }
implicitly_scoped_stmt
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ $<ttype>$ = last_tree = $<ttype>2;
+ }
+ }
;
implicitly_scoped_stmt:
compstmt
{ finish_stmt (); }
- | .pushlevel simple_stmt .poplevel
- { $$ = $3; }
+ | .pushlevel
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ }
+ simple_stmt .poplevel
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ $$ = $4;
+ }
;
stmt:
@@ -3228,53 +3553,134 @@ simple_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);
+ if (! processing_template_decl)
+ {
+ 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 (); }
| simple_if ELSE
- { expand_start_else (); }
+ { if (! processing_template_decl) expand_start_else (); }
implicitly_scoped_stmt
- { expand_end_cond (); }
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>1, 2) = TREE_CHAIN ($<ttype>1);
+ TREE_CHAIN ($<ttype>1) = NULL_TREE;
+ last_tree = $<ttype>1;
+ }
+ else
+ 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 ();
+ | simple_if %prec IF
+ { if (! processing_template_decl) expand_end_cond ();
+ do_poplevel ();
finish_stmt (); }
| WHILE
- { emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop (1);
- cond_stmt_keyword = "while"; }
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ else
+ {
+ 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); }
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != $<ttype>2)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = last_tree;
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ TREE_OPERAND ($<ttype>2, 0) = $4;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, $4);
+ }
+ }
already_scoped_stmt .poplevel
- { expand_end_loop ();
- finish_stmt (); }
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ expand_end_loop ();
+ finish_stmt ();
+ }
| DO
- { emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1); }
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ else
+ {
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop_continue_elsewhere (1);
+ }
+ }
implicitly_scoped_stmt WHILE
- { expand_loop_continue_here ();
- cond_stmt_keyword = "do"; }
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ {
+ expand_loop_continue_here ();
+ cond_stmt_keyword = "do";
+ }
+ }
paren_expr_or_null ';'
- { emit_line_note (input_filename, lineno);
- expand_exit_loop_if_false (0, $6);
- expand_end_loop ();
+ {
+ if (processing_template_decl)
+ TREE_OPERAND ($<ttype>2, 1) = $6;
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, $6);
+ expand_end_loop ();
+ }
clear_momentary ();
- finish_stmt (); }
+ finish_stmt ();
+ }
| FOR
- { emit_line_note (input_filename, lineno);
+ { if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ else
+ emit_line_note (input_filename, lineno);
if (flag_new_for_scope > 0)
{
/* Conditionalize .pushlevel */
@@ -3286,122 +3692,123 @@ simple_stmt:
}
}
'(' for.init.statement
- { emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1); }
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != $<ttype>2)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ }
+ else
+ {
+ 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); }
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != $<ttype>2)
+ {
+ TREE_OPERAND ($<ttype>2, 1) = last_tree;
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ TREE_OPERAND ($<ttype>2, 1) = $7;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ if ($7) expand_exit_loop_if_false (0, $7);
+ }
+ }
xexpr ')'
/* Don't let the tree nodes for $10 be discarded
by clear_momentary during the parsing of the next stmt. */
- { push_momentary (); }
+ {
+ if (processing_template_decl)
+ TREE_OPERAND ($<ttype>2, 2) = $10;
+ push_momentary ();
+ }
already_scoped_stmt .poplevel
- { emit_line_note (input_filename, lineno);
- expand_loop_continue_here ();
- if ($10) cplus_expand_expr_stmt ($10);
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 3) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_loop_continue_here ();
+ if ($10) cplus_expand_expr_stmt ($10);
+ expand_end_loop ();
+ }
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 ();
+ do_poplevel ();
}
finish_stmt (); }
| SWITCH .pushlevel '(' condition ')'
- { emit_line_note (input_filename, lineno);
- c_expand_start_case ($4);
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (SWITCH_STMT, $4, NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ else
+ {
+ 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 (); }
+ push_momentary ();
+ }
implicitly_scoped_stmt
- { expand_end_case ($4);
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>6, 1) = TREE_CHAIN ($<ttype>6);
+ TREE_CHAIN ($<ttype>6) = NULL_TREE;
+ last_tree = $<ttype>6;
+ }
+ else
+ expand_end_case ($4);
pop_momentary ();
- pop_switch (); }
+ pop_switch ();
+ }
.poplevel
{ finish_stmt (); }
| 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);
- }
+ { do_case ($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);
- }
+ { do_case ($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);
- }
+ { do_case (NULL_TREE, NULL_TREE); }
stmt
| BREAK ';'
{ emit_line_note (input_filename, lineno);
- if ( ! expand_exit_something ())
+ if (processing_template_decl)
+ add_tree (build_min_nt (BREAK_STMT));
+ else if ( ! expand_exit_something ())
error ("break statement not within loop or switch"); }
| CONTINUE ';'
{ emit_line_note (input_filename, lineno);
- if (! expand_continue_loop (0))
+ if (processing_template_decl)
+ add_tree (build_min_nt (CONTINUE_STMT));
+ else if (! expand_continue_loop (0))
error ("continue statement not within a loop"); }
| RETURN ';'
{ emit_line_note (input_filename, lineno);
@@ -3411,14 +3818,14 @@ simple_stmt:
c_expand_return ($2);
finish_stmt ();
}
- | asm_keyword maybe_type_qual '(' string ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' string ')' ';'
{ if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
emit_line_note (input_filename, lineno);
expand_asm ($4);
finish_stmt ();
}
/* This is the case with just output operands. */
- | asm_keyword maybe_type_qual '(' string ':' asm_operands ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' 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,
@@ -3427,7 +3834,7 @@ simple_stmt:
finish_stmt ();
}
/* This is the case with input operands as well. */
- | asm_keyword maybe_type_qual '(' string ':' asm_operands ':' asm_operands ')' ';'
+ | asm_keyword maybe_cv_qualifier '(' 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,
@@ -3436,7 +3843,7 @@ simple_stmt:
finish_stmt ();
}
/* 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);
@@ -3446,14 +3853,26 @@ simple_stmt:
finish_stmt ();
}
| GOTO '*' expr ';'
- { emit_line_note (input_filename, lineno);
- expand_computed_goto ($3); }
+ {
+ if (processing_template_decl)
+ add_tree (build_min_nt (GOTO_STMT, $3));
+ else
+ { emit_line_note (input_filename, lineno);
+ expand_computed_goto ($3); }
+ }
| GOTO identifier ';'
- { tree decl;
- emit_line_note (input_filename, lineno);
- decl = lookup_label ($2);
- TREE_USED (decl) = 1;
- expand_goto (decl); }
+ {
+ if (processing_template_decl)
+ add_tree (build_min_nt (GOTO_STMT, $2));
+ else
+ {
+ tree decl;
+ emit_line_note (input_filename, lineno);
+ decl = lookup_label ($2);
+ TREE_USED (decl) = 1;
+ expand_goto (decl);
+ }
+ }
| label_colon stmt
{ finish_stmt (); }
| label_colon '}'
@@ -3472,40 +3891,97 @@ 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 (); }
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (TRY_BLOCK, NULL_TREE,
+ NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_start_try_stmts ();
+ }
+ }
compstmt
- { expand_end_try_stmts ();
- expand_start_all_catch (); }
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ expand_start_all_catch ();
+ }
handler_seq
- { expand_end_all_catch (); }
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ expand_end_all_catch ();
+ }
;
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
+ {
+ if (processing_template_decl)
+ {
+ $<ttype>$ = build_min_nt (HANDLER, NULL_TREE,
+ NULL_TREE);
+ add_tree ($<ttype>$);
+ }
+ }
+ .pushlevel handler_args
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ }
compstmt
- { expand_end_catch_block (); }
+ {
+ if (processing_template_decl)
+ {
+ TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
+ TREE_CHAIN ($<ttype>2) = NULL_TREE;
+ last_tree = $<ttype>2;
+ }
+ else
+ expand_end_catch_block ();
+ }
.poplevel
;
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 +3989,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 +4012,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 +4028,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 +4053,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,17 +4083,16 @@ 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; }
+ { $$ = tree_cons (NULL_TREE, $1.t, void_list_node);
+ TREE_PARMLIST ($$) = 1;
+ check_for_new_type ("inside parameter list", $1); }
;
/* This nonterminal does not include the common sequence '(' type_id ')',
@@ -3628,14 +4114,11 @@ complex_parmlist:
}
| type_id ELLIPSIS
{
- $$ = build_tree_list (NULL_TREE, $$);
+ $$ = build_tree_list (NULL_TREE, $1.t);
TREE_PARMLIST ($$) = 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
@@ -3648,7 +4131,7 @@ complex_parmlist:
}
| type_id TYPENAME_ELLIPSIS
{
- $$ = build_tree_list (NULL_TREE, $$);
+ $$ = build_tree_list (NULL_TREE, $1.t);
TREE_PARMLIST ($$) = 1;
}
| parms ':'
@@ -3668,21 +4151,37 @@ complex_parmlist:
parse errors, for example, a missing right
parenthesis. */
yyerror ("possibly missing ')'");
- $$ = tree_cons (NULL_TREE, $$, void_list_node);
+ $$ = tree_cons (NULL_TREE, $1.t, void_list_node);
TREE_PARMLIST ($$) = 1;
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 +4191,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 ($<ttype>-1 == error_mark_node)
- $$ = 0;
- else
- {
- $$ = 1;
- pushclass ($<ttype>-1, 1);
- }
- }
- ;
-*/
-
bad_parm:
/* empty */ %prec EMPTY
{
@@ -3775,22 +4252,25 @@ bad_parm:
| notype_declarator
{
error ("type specifier omitted for parameter");
+ if (TREE_CODE ($$) == SCOPE_REF
+ && TREE_CODE (TREE_OPERAND ($$, 0)) == TEMPLATE_TYPE_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 +4283,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 +4359,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 +4369,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/gnu/usr.bin/gcc/cp/pt.c b/gnu/usr.bin/gcc/cp/pt.c
index 3ce02248902..49339b1b5a8 100644
--- a/gnu/usr.bin/gcc/cp/pt.c
+++ b/gnu/usr.bin/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,14 +21,9 @@ 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 <stdio.h>
@@ -41,6 +37,11 @@ Boston, MA 02111-1307, USA. */
#include "lex.h"
#include "output.h"
#include "defaults.h"
+#include "except.h"
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
extern struct obstack permanent_obstack;
@@ -48,40 +49,593 @@ 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;
+
+int minimal_parse_mode;
-/* 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 processing_specialization;
+static int template_header_count;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-static int unify ();
-static void add_pending_template ();
+static int unify PROTO((tree, tree *, int, 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));
+static tree tsubst_expr_values PROTO((tree, tree));
+static int comp_template_args PROTO((tree, tree));
+static int list_eq PROTO((tree, tree));
+static tree get_class_bindings PROTO((tree, tree, tree));
+static tree coerce_template_parms PROTO((tree, tree, tree));
+static tree tsubst_enum PROTO((tree, tree, int, tree *));
+static tree add_to_template_args PROTO((tree, tree));
+static int type_unification_real PROTO((tree, tree *, tree, tree, int*,
+ int, int, int));
+static int processing_explicit_specialization PROTO((int));
+static void note_template_header PROTO((int));
+
+/* Restore the template parameter context. */
+
+void
+begin_member_template_processing (decl)
+ tree decl;
+{
+ tree parms;
+ int i;
+
+ parms = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
+
+ ++processing_template_decl;
+ current_template_parms
+ = tree_cons (build_int_2 (0, processing_template_decl),
+ parms, current_template_parms);
+ 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:
+ 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);
+ }
+ }
+}
+
+/* Undo the effects of begin_member_template_processing. */
+
+void
+end_member_template_processing ()
+{
+ if (! processing_template_decl)
+ return;
+
+ --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. Works if T
+ is either a FUNCTION_DECL or a TEMPLATE_DECL. */
-void overload_template_name (), pop_template_decls ();
+int
+is_member_template (t)
+ tree t;
+{
+ int r = 0;
+
+ if (TREE_CODE (t) != FUNCTION_DECL
+ && !DECL_FUNCTION_TEMPLATE_P (t))
+ /* Anything that isn't a template or a template function is
+ certainly not a member template. */
+ 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 = NULL_TREE;
+
+ 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);
+
+ if (tmpl)
+ {
+ tree parms = DECL_TEMPLATE_PARMS (tmpl);
+ int parm_levels = list_length (parms);
+ int template_class_levels = 0;
+ tree ctx = DECL_CLASS_CONTEXT (t);
+
+ if (CLASSTYPE_TEMPLATE_INFO (ctx))
+ {
+ tree args;
+
+ /* Here, we should really count the number of levels
+ deep ctx is, making sure not to count any levels that
+ are just specializations. Since there are no member
+ template classes yet, we don't have to do all that. */
+
+ if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
+ template_class_levels = 1;
+ else
+ {
+ int i;
+
+ args = CLASSTYPE_TI_ARGS (ctx);
+
+ if (args == NULL_TREE)
+ template_class_levels = 1;
+ else
+ for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
+ if (uses_template_parms (TREE_VEC_ELT (args, i)))
+ {
+ template_class_levels++;
+ break;
+ }
+ }
+ }
+
+ if (parm_levels > template_class_levels)
+ r = 1;
+ }
+ }
+
+ return r;
+}
+
+/* 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 (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
+ {
+ 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 ()
{
pushlevel (0);
- push_obstacks (&permanent_obstack, &permanent_obstack);
- pushlevel (0);
+ declare_pseudo_global_level ();
+ ++processing_template_decl;
+ note_template_header (0);
+}
+
+
+/* We've just seen template <>. */
+
+void
+begin_specialization ()
+{
+ note_template_header (1);
+}
+
+
+/* Called at then end of processing a declaration preceded 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++;
+}
+
+
+/* Returns non-zero iff a declarator, in which the number of template
+ types that appeared was TEMPLATE_COUNT, is an explicit
+ specialization. */
+
+static int
+processing_explicit_specialization (template_count)
+ int template_count;
+{
+ /* A function declaration is an explicit specialization of a member
+ template if all of the following conditions hold:
+
+ o There was a template <...> preceding the declaration.
+ o The last template <...> was in fact template <>.
+ o The number of template <...>'s preceding the declaration, less
+ the number of template classes with arguments specified used to
+ qualify the function name, is 1.
+
+ For example:
+
+ template <> void S<int>::foo();
+ template <class T> template <> void S<T>::foo();
+ template <> struct S<int> { ... template <> void foo(); }
+
+ The first of these is not a specialization of S<int>::foo() (it
+ is instead a specialization of S<T>::foo), while the next two are
+ specializations of member template functions. */
+
+ return processing_specialization
+ && template_header_count > template_count;
+}
+
+/* Returns the template function specialized by TEMPLATE_ID, or
+ NULL_TREE if there is none.
+
+ The TEMPLATE_ID is a TEMPLATE_ID_EXPR. The TYPE is
+ the type it has been declared to have. Return the TEMPLATE_DECL
+ that is being specialized, and put the specialization arguments in
+ *TARGS. If no appropriate specialization can be found, NULL_TREE is
+ returned, and *TARGS is assigned NULL_TREE. If complain is
+ non-zero, error messages are printed where appropriate. */
+
+tree
+determine_explicit_specialization (template_id, type, targs_out,
+ need_member_template,
+ complain)
+ tree template_id;
+ tree type;
+ tree* targs_out;
+ int need_member_template;
+ int complain;
+{
+ int i;
+ int overloaded;
+ tree fns;
+ tree matching_fns = NULL_TREE;
+ tree name = NULL_TREE;
+ tree result;
+ tree fn;
+
+ my_friendly_assert (TREE_CODE (template_id) == TEMPLATE_ID_EXPR,
+ 0);
+
+ fns = TREE_OPERAND (template_id, 0);
+
+ overloaded = fns != NULL_TREE && really_overloaded_fn (fns);
+
+ for (fn = (fns != NULL_TREE) ? get_first_fn (fns) : NULL_TREE;
+ fn != NULL_TREE;
+ fn = overloaded ? DECL_CHAIN (fn) : NULL_TREE)
+ {
+ int dummy = 0;
+ tree targs;
+
+ if (name == NULL_TREE)
+ name = DECL_NAME (fn);
+
+ if (TREE_CODE (fn) != TEMPLATE_DECL
+ || (need_member_template && !is_member_template (fn)))
+ continue;
+
+ if (list_length (TREE_OPERAND (template_id, 1)) > DECL_NTPARMS (fn))
+ continue;
+
+ targs = make_scratch_vec (DECL_NTPARMS (fn));
+
+ /* We allow incomplete unification here, because we are going to
+ check all the functions. */
+ i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ &TREE_VEC_ELT (targs, 0),
+ type
+ ? TYPE_ARG_TYPES (TREE_TYPE (fn)) : NULL_TREE,
+ type ? TYPE_ARG_TYPES (type) : NULL_TREE,
+ TREE_OPERAND (template_id, 1),
+ &dummy, 1, 1);
+
+ if (i == 0)
+ {
+ /* Unification was successful. See if the return types
+ match. */
+ if (type != NULL_TREE)
+ {
+ tree tmpl_return_type = tsubst (TREE_TYPE (TREE_TYPE (fn)),
+ targs,
+ DECL_NTPARMS (fn),
+ NULL_TREE);
+
+ if (tmpl_return_type != TREE_TYPE (type))
+ {
+ /* Always complain about this. With ambiguity, some
+ other context, might resolve things. But, a
+ non-matching return type will always be a
+ problem. */
+ cp_error ("Return type of explicit specialization of");
+ cp_error ("`%D' is `%T', but should be `%T'.",
+ fn, TREE_TYPE (type), tmpl_return_type);
+ *targs_out = NULL_TREE;
+ return NULL_TREE;
+ }
+ }
+
+ matching_fns = scratch_tree_cons (fn, targs, matching_fns);
+ }
+ }
+
+ if (matching_fns == NULL_TREE)
+ {
+ if (complain)
+ cp_error ("Specialization of `%s' does not match any template declaration.",
+ IDENTIFIER_POINTER (name));
+ *targs_out = NULL_TREE;
+ return NULL_TREE;
+ }
+
+ if (TREE_CHAIN (matching_fns) != NULL_TREE)
+ {
+ if (complain)
+ {
+ tree fn;
+
+ cp_error ("Ambiguous explicit specialization. Candidates are:");
+ for (fn = matching_fns; fn != NULL_TREE; fn = TREE_CHAIN (fn))
+ cp_error (" %D", TREE_PURPOSE (fn));
+ }
+
+ *targs_out = NULL_TREE;
+ return NULL_TREE;
+ }
+
+ /* We have one, and exactly one, match. */
+ *targs_out = TREE_VALUE (matching_fns);
+ return TREE_PURPOSE (matching_fns);
+}
+
+
+/* Check to see if the function just declared, as indicated in
+ DECLARATOR, and in DECL, is a specialization. Check that the
+ specialization is OK. If FLAGS == 1, we are being called by
+ finish_struct_methods. If FLAGS == 2, we are being called by
+ grokfndecl, and the function has a definition, or is a friend. If
+ FLAGS == 3, this is a friend declaration.
+ Returns 0 if the decl is not an explicit specialization or
+ instantiation, 1 if it is an explicit specialization, and 2 if it
+ is an explicit instantiation. */
+
+int
+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 == 3;
+
+ if (processing_explicit_specialization (template_count)
+ || finish_member
+ || TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+ {
+ tree tmpl = NULL_TREE;
+ tree dname = DECL_NAME (decl);
+ tree ctype = DECL_CLASS_CONTEXT (decl);
+ tree targs;
+
+ /* We've come across a declarator that looks like: U f<T1,
+ T2, ...>(A1, A2, ..). This is an explicit template
+ specialization. Check that:
+
+ o The explicitly specified parameters together with those
+ that can be deduced by template argument deduction
+ uniquely determine a particular specialization.
+
+ See [temp.expl.spec]. */
+
+ if (!finish_member
+ && TREE_CODE (declarator) == TEMPLATE_ID_EXPR
+ && !processing_explicit_specialization (template_count)
+ && !is_friend)
+ {
+ if (!have_def)
+ /* This is not an explicit specialization. It must be
+ an explicit instantiation. */
+ return 2;
+ else if (pedantic)
+ pedwarn ("Explicit specialization not preceded by `template <>'");
+ }
+
+ if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ {
+ tree fns;
+
+ my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE,
+ 0);
+ if (!ctype)
+ fns = IDENTIFIER_GLOBAL_VALUE (dname);
+ else
+ fns = dname;
+
+ declarator = lookup_template_function (fns, NULL_TREE);
+ }
+
+ 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);
+ SET_DECL_IMPLICIT_INSTANTIATION (decl);
+ return 1;
+ }
+
+ if (ctype
+ && TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE)
+ {
+ tree fns;
+
+ if (TYPE_BEING_DEFINED (ctype) && !finish_member)
+ {
+ /* 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_methods fix this up later. */
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ DECL_TEMPLATE_INFO (decl)
+ = perm_tree_cons (NULL_TREE,
+ TREE_OPERAND (declarator, 1),
+ NULL_TREE);
+ return 1;
+ }
+
+ fns = lookup_fnfields (TYPE_BINFO (ctype),
+ TREE_OPERAND (declarator, 0),
+ 1);
+
+ if (fns == NULL_TREE)
+ {
+ cp_error ("No member template `%s' declared in `%T'",
+ IDENTIFIER_POINTER (TREE_OPERAND (declarator,
+ 0)),
+ ctype);
+ return 1;
+ }
+ else
+ TREE_OPERAND (declarator, 0) = fns;
+ }
+
+ tmpl =
+ determine_explicit_specialization
+ (declarator, TREE_TYPE (decl), &targs,
+ TREE_CODE (decl) == TEMPLATE_DECL, 1);
+
+ if (tmpl)
+ {
+ /* Mangle the function name appropriately. */
+ if (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_NAME (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 1;
+ }
+
+ /* This function declaration is a template specialization.
+ Record that fact. */
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
+ = perm_tree_cons (targs, decl,
+ DECL_TEMPLATE_SPECIALIZATIONS
+ (tmpl));
+ /* 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);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* 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,26 +643,49 @@ 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
+ idx = TEMPLATE_CONST_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)
{
- 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;
}
+ 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));
tinfo = make_node (TEMPLATE_CONST_PARM);
my_friendly_assert (TREE_PERMANENT (tinfo), 260.5);
if (TREE_PERMANENT (parm) == 0)
@@ -120,20 +697,17 @@ process_template_parm (list, next)
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
DECL_INITIAL (decl) = tinfo;
DECL_INITIAL (parm) = tinfo;
+ TEMPLATE_CONST_SET_INFO (tinfo, idx, processing_template_decl);
}
else
{
- tree t = make_node (TEMPLATE_TYPE_PARM);
+ tree t = make_lang_type (TEMPLATE_TYPE_PARM);
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
decl = build_decl (TYPE_DECL, TREE_VALUE (parm), t);
- TYPE_MAIN_DECL (t) = decl;
+ TYPE_NAME (t) = decl;
+ TYPE_STUB_DECL (t) = decl;
parm = decl;
- if (defval)
- {
- if (IDENTIFIER_HAS_TYPE_VALUE (defval))
- defval = IDENTIFIER_TYPE_VALUE (defval);
- else
- defval = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (defval));
- }
+ TEMPLATE_TYPE_SET_INFO (t, idx, processing_template_decl);
}
SET_DECL_ARTIFICIAL (decl);
pushdecl (decl);
@@ -150,189 +724,237 @@ tree
end_template_parm_list (parms)
tree parms;
{
- int nparms = 0;
- int saw_default = 0;
- tree saved_parmlist;
+ int nparms;
tree parm;
- for (parm = parms; parm; parm = TREE_CHAIN (parm))
- nparms++;
- saved_parmlist = make_tree_vec (nparms);
+ 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 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");
- }
+ TREE_VEC_ELT (saved_parmlist, nparms) = parm;
- 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;
- }
- set_current_level_tags_transparency (1);
- processing_template_decl++;
return saved_parmlist;
}
-/* 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. */
+/* end_template_decl is called after a template declaration is seen. */
+
void
-end_template_decl (d1, d2, is_class, defn)
- tree d1, d2, is_class;
- int defn;
+end_template_decl ()
{
- tree decl;
- struct template_info *tmpl;
+ reset_specialization ();
- tmpl = (struct template_info *) obstack_alloc (&permanent_obstack,
- sizeof (struct template_info));
- tmpl->text = 0;
- tmpl->length = 0;
- tmpl->aggr = is_class;
+ if (! processing_template_decl)
+ return;
- /* cloned from reinit_parse_for_template */
- tmpl->filename = input_filename;
- tmpl->lineno = lineno;
- tmpl->parm_vec = d1; /* [eichin:19911015.2306EST] */
+ /* 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? */
+}
- if (d2 == NULL_TREE || d2 == error_mark_node)
+/* 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)
{
- decl = 0;
- goto lose;
+ 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)
+ 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);
}
- if (is_class)
+ return args;
+}
+
+void
+push_template_decl (decl)
+ tree decl;
+{
+ tree tmpl;
+ tree args = NULL_TREE;
+ tree info;
+ tree ctx = DECL_CONTEXT (decl) ? DECL_CONTEXT (decl) : current_class_type;
+ int primary = 0;
+
+ /* Kludge! */
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl)
+ && DECL_CLASS_CONTEXT (decl))
+ ;
+ /* Note that this template is a "primary template" */
+ else if (! ctx || ! CLASSTYPE_TEMPLATE_INFO (ctx)
+ /* || (processing_template_decl > CLASSTYPE_TEMPLATE_LEVEL (ctx)) */)
+ primary = 1;
+
+ /* Partial specialization. */
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
{
- decl = build_lang_decl (TEMPLATE_DECL, d2, NULL_TREE);
- GNU_xref_decl (current_function_decl, decl);
+ tree type = TREE_TYPE (decl);
+ tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
+ tree mainargs = CLASSTYPE_TI_ARGS (type);
+ tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl);
+
+ for (; spec; spec = TREE_CHAIN (spec))
+ {
+ /* purpose: args to main template
+ value: spec template */
+ if (comp_template_args (TREE_PURPOSE (spec), mainargs))
+ return;
+ }
+
+ 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;
+ }
+
+ args = current_template_args ();
+
+ if (! ctx || TYPE_BEING_DEFINED (ctx))
+ {
+ tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
+ DECL_TEMPLATE_PARMS (tmpl) = current_template_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);
+
+ if (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
{
- if (TREE_CODE (d2) == TEMPLATE_DECL)
- decl = d2;
+ 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 && DECL_ARTIFICIAL (decl))
+ tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
+ else if (! DECL_TEMPLATE_INFO (decl))
+ {
+ cp_error ("template definition of non-template `%#D'", decl);
+ return;
+ }
else
+ tmpl = DECL_TI_TEMPLATE (decl);
+
+ if (is_member_template (tmpl))
{
- /* Class destructor templates and operator templates are
- slipping past as non-template nodes. Process them here, since
- I haven't figured out where to catch them earlier. I could
- go do that, but it's a choice between getting that done and
- staying only N months behind schedule. Sorry.... */
- enum tree_code code;
- my_friendly_assert (TREE_CODE (d2) == CALL_EXPR, 263);
- code = TREE_CODE (TREE_OPERAND (d2, 0));
- my_friendly_assert (code == BIT_NOT_EXPR
- || code == OP_IDENTIFIER
- || code == SCOPE_REF, 264);
- d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE, NULL_TREE);
- decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2),
- TREE_TYPE (d2));
- DECL_TEMPLATE_RESULT (decl) = d2;
- DECL_CONTEXT (decl) = DECL_CONTEXT (d2);
- DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2);
- DECL_NAME (decl) = DECL_NAME (d2);
- TREE_TYPE (decl) = TREE_TYPE (d2);
- if (interface_unknown && flag_external_templates
- && ! flag_alt_external_templates
- && ! DECL_IN_SYSTEM_HEADER (decl))
- warn_if_unknown_interface (decl);
- TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = flag_external_templates && !interface_unknown;
- DECL_EXTERNAL (decl) = (DECL_EXTERNAL (d2)
- && !(DECL_CLASS_CONTEXT (d2)
- && !DECL_THIS_EXTERN (d2)));
+ a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+ t = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
+ 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);
- /* All routines creating TEMPLATE_DECL nodes should now be using
- build_lang_decl, which will have set this up already. */
- my_friendly_assert (DECL_LANG_SPECIFIC (decl) != 0, 265);
+ t = NULL_TREE;
- /* @@ Somewhere, permanent allocation isn't being used. */
- if (! DECL_TEMPLATE_IS_CLASS (decl)
- && TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == FUNCTION_DECL)
+ if (CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
{
- tree result = DECL_TEMPLATE_RESULT (decl);
- /* Will do nothing if allocation was already permanent. */
- DECL_ARGUMENTS (result) = copy_to_permanent (DECL_ARGUMENTS (result));
+ /* 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 this is for a method, there's an extra binding level here. */
- if (DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
+ if (t != NULL_TREE
+ && TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
{
- /* @@ Find out where this should be getting set! */
- tree r = DECL_TEMPLATE_RESULT (decl);
- if (DECL_LANG_SPECIFIC (r) && DECL_CLASS_CONTEXT (r) == NULL_TREE)
- DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
+ cp_error ("got %d template parameters for `%#D'",
+ TREE_VEC_LENGTH (a), decl);
+ cp_error (" but `%#T' has %d", ctx, TREE_VEC_LENGTH (t));
}
}
- DECL_TEMPLATE_INFO (decl) = tmpl;
- DECL_TEMPLATE_PARMS (decl) = d1;
+ /* Get the innermost set of template arguments. */
+ args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
- /* So that duplicate_decls can do the right thing. */
- if (defn)
- DECL_INITIAL (decl) = error_mark_node;
-
- /* If context of decl is non-null (i.e., method template), add it
- to the appropriate class template, and pop the binding levels. */
- if (! is_class && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
- {
- tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
- tree tmpl, t;
- my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
- tmpl = UPT_TEMPLATE (ctx);
- for (t = DECL_TEMPLATE_MEMBERS (tmpl); t; t = TREE_CHAIN (t))
- if (TREE_PURPOSE (t) == DECL_NAME (decl)
- && duplicate_decls (decl, TREE_VALUE (t)))
- goto already_there;
- DECL_TEMPLATE_MEMBERS (tmpl) =
- perm_tree_cons (DECL_NAME (decl), decl, DECL_TEMPLATE_MEMBERS (tmpl));
- already_there:
- poplevel (0, 0, 0);
- poplevel (0, 0, 0);
- }
- /* Otherwise, go back to top level first, and push the template decl
- again there. */
- else
+ DECL_TEMPLATE_RESULT (tmpl) = decl;
+ TREE_TYPE (tmpl) = TREE_TYPE (decl);
+
+ if (! ctx)
+ tmpl = pushdecl_top_level (tmpl);
+
+ if (primary)
+ TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (tmpl)) = tmpl;
+
+ info = perm_tree_cons (tmpl, args, NULL_TREE);
+
+ if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
{
- poplevel (0, 0, 0);
- poplevel (0, 0, 0);
- pushdecl (decl);
+ CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (tmpl)) = info;
+ DECL_NAME (decl) = classtype_mangled_name (TREE_TYPE (decl));
}
- lose:
-#if 0 /* It happens sometimes, with syntactic or semantic errors.
-
- One specific case:
- template <class A, int X, int Y> class Foo { ... };
- template <class A, int X, int y> Foo<X,Y>::method (Foo& x) { ... }
- Note the missing "A" in the class containing "method". */
- my_friendly_assert (global_bindings_p (), 267);
-#else
- while (! global_bindings_p ())
- poplevel (0, 0, 0);
-#endif
- pop_obstacks ();
- processing_template_decl--;
- (void) get_pending_sizes ();
+ else if (! DECL_LANG_SPECIFIC (decl))
+ cp_error ("template declaration of `%#D'", decl);
+ else
+ DECL_TEMPLATE_INFO (decl) = info;
}
-tree tsubst PROTO ((tree, tree*, int, tree));
-
/* Convert all template arguments to their appropriate types, and return
a vector containing the resulting values. If any error occurs, return
error_mark_node. */
+
static tree
coerce_template_parms (parms, arglist, in_decl)
tree parms, arglist;
@@ -380,8 +1002,13 @@ coerce_template_parms (parms, arglist, in_decl)
else
arg = TREE_VALUE (arg);
}
+ else if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (parms, i)))
+ == TYPE_DECL)
+ arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
+ vec, i, in_decl);
else
- arg = TREE_PURPOSE (TREE_VEC_ELT (parms, i));
+ arg = tsubst_expr (TREE_PURPOSE (TREE_VEC_ELT (parms, i)),
+ vec, i, in_decl);
TREE_VEC_ELT (vec, i) = arg;
}
@@ -395,29 +1022,67 @@ coerce_template_parms (parms, arglist, in_decl)
is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
requires_type = TREE_CODE (parm) == TYPE_DECL;
+
+ if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
+ && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
+ {
+ cp_pedwarn ("to refer to a type member of a template parameter,");
+ cp_pedwarn (" use `typename %E'", arg);
+ arg = make_typename_type (TREE_OPERAND (arg, 0),
+ TREE_OPERAND (arg, 1));
+ is_type = 1;
+ }
if (is_type != requires_type)
{
if (in_decl)
- cp_error ("type/value mismatch in template parameter list for `%D'",
- in_decl);
+ {
+ cp_error ("type/value mismatch at argument %d in template parameter list for `%D'",
+ i, in_decl);
+ if (is_type)
+ cp_error (" expected a constant of type `%T', got `%T'",
+ TREE_TYPE (parm), arg);
+ else
+ cp_error (" expected a type, got `%E'", arg);
+ }
lost++;
TREE_VEC_ELT (vec, i) = error_mark_node;
continue;
}
if (is_type)
- val = groktypename (arg);
+ {
+ val = groktypename (arg);
+ if (! processing_template_decl)
+ {
+ tree t = target_type (val);
+ if (TREE_CODE (t) != TYPENAME_TYPE
+ && IS_AGGR_TYPE (t)
+ && decl_function_context (TYPE_MAIN_DECL (t)))
+ {
+ cp_error ("type `%T' composed from a local class is not a valid template-argument", val);
+ return error_mark_node;
+ }
+ }
+ }
else
{
- tree t = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (vec, 0),
+ tree t = tsubst (TREE_TYPE (parm), vec,
TREE_VEC_LENGTH (vec), in_decl);
- val = digest_init (t, arg, (tree *) 0);
+ if (processing_template_decl)
+ val = arg;
+ else
+ val = digest_init (t, arg, (tree *) 0);
- if (val == error_mark_node)
+ if (val == error_mark_node || processing_template_decl)
;
/* 14.2: Other template-arguments must be constant-expressions,
addresses of objects or functions with external linkage, or of
static class members. */
+ else if (IS_AGGR_TYPE (TREE_TYPE (val)))
+ {
+ cp_error ("object `%E' cannot be used as template argument", arg);
+ val = error_mark_node;
+ }
else if (!TREE_CONSTANT (val))
{
cp_error ("non-const `%E' cannot be used as template argument",
@@ -444,7 +1109,7 @@ coerce_template_parms (parms, arglist, in_decl)
else if (TREE_CODE (a) != VAR_DECL
&& TREE_CODE (a) != FUNCTION_DECL)
goto bad;
- else if (! DECL_PUBLIC (a))
+ else if (! TREE_PUBLIC (a))
{
cp_error ("address of non-extern `%E' cannot be used as template argument", a);
val = error_mark_node;
@@ -474,8 +1139,39 @@ coerce_template_parms (parms, arglist, in_decl)
return vec;
}
+static int
+comp_template_args (oldargs, newargs)
+ tree oldargs, newargs;
+{
+ int i;
+
+ if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
+ return 0;
+
+ for (i = 0; i < TREE_VEC_LENGTH (oldargs); ++i)
+ {
+ tree nt = TREE_VEC_ELT (newargs, i);
+ tree ot = TREE_VEC_ELT (oldargs, i);
+
+ if (nt == ot)
+ continue;
+ if (TREE_CODE (nt) != TREE_CODE (ot))
+ return 0;
+ if (TREE_CODE_CLASS (TREE_CODE (ot)) == 't')
+ {
+ if (comptypes (ot, nt, 1))
+ continue;
+ }
+ else if (cp_tree_equal (ot, nt) > 0)
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
/* Given class template name and parameter list, produce a user-friendly name
for the instantiation. */
+
static char *
mangle_class_name_for_template (name, parms, arglist)
char *name;
@@ -486,12 +1182,10 @@ mangle_class_name_for_template (name, parms, arglist)
int i, nparms;
if (!scratch_firstobj)
- {
- gcc_obstack_init (&scratch_obstack);
- scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
- }
+ gcc_obstack_init (&scratch_obstack);
else
obstack_free (&scratch_obstack, scratch_firstobj);
+ scratch_firstobj = obstack_alloc (&scratch_obstack, 1);
#if 0
#define buflen sizeof(buf)
@@ -560,6 +1254,75 @@ mangle_class_name_for_template (name, parms, arglist)
return NULL;
}
+static tree
+classtype_mangled_name (t)
+ tree t;
+{
+ if (CLASSTYPE_TEMPLATE_INFO (t)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
+ {
+ tree name = DECL_NAME (CLASSTYPE_TI_TEMPLATE (t));
+ char *mangled_name = mangle_class_name_for_template
+ (IDENTIFIER_POINTER (name),
+ DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (t)),
+ CLASSTYPE_TI_ARGS (t));
+ tree id = get_identifier (mangled_name);
+ IDENTIFIER_TEMPLATE (id) = name;
+ return id;
+ }
+ else
+ return TYPE_IDENTIFIER (t);
+}
+
+static void
+add_pending_template (d)
+ tree d;
+{
+ tree ti;
+
+ if (TREE_CODE_CLASS (TREE_CODE (d)) == 't')
+ ti = CLASSTYPE_TEMPLATE_INFO (d);
+ else
+ ti = DECL_TEMPLATE_INFO (d);
+
+ if (TI_PENDING_TEMPLATE_FLAG (ti))
+ return;
+
+ *template_tail = perm_tree_cons
+ (current_function_decl, d, NULL_TREE);
+ template_tail = &TREE_CHAIN (*template_tail);
+ TI_PENDING_TEMPLATE_FLAG (ti) = 1;
+}
+
+
+/* Return a TEMPLATE_ID_EXPR corresponding to the indicated FNS (which
+ may be either a _DECL or an overloaded function or an
+ IDENTIFIER_NODE), and ARGLIST. */
+
+tree
+lookup_template_function (fns, arglist)
+ tree fns, arglist;
+{
+ if (fns == NULL_TREE)
+ {
+ cp_error ("non-template used as template");
+ return error_mark_node;
+ }
+
+ if (arglist != NULL_TREE && !TREE_PERMANENT (arglist))
+ {
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ arglist = copy_list (arglist);
+ pop_obstacks ();
+ }
+
+ return build_min (TEMPLATE_ID_EXPR,
+ TREE_TYPE (fns)
+ ? TREE_TYPE (fns) : unknown_type_node,
+ fns, arglist);
+}
+
+
/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
parameters, find the desired type.
@@ -569,6 +1332,7 @@ mangle_class_name_for_template (name, parms, arglist)
IN_DECL, if non-NULL, is the template declaration we are trying to
instantiate. */
+
tree
lookup_template_class (d1, arglist, in_decl)
tree d1, arglist;
@@ -576,12 +1340,27 @@ lookup_template_class (d1, arglist, in_decl)
{
tree template, parmlist;
char *mangled_name;
- tree id;
+ tree id, t;
+
+ if (TREE_CODE (d1) == IDENTIFIER_NODE)
+ {
+ template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
+ if (! template)
+ template = IDENTIFIER_CLASS_VALUE (d1);
+ }
+ else if (TREE_CODE (d1) == TYPE_DECL && IS_AGGR_TYPE (TREE_TYPE (d1)))
+ {
+ template = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d1));
+ d1 = DECL_NAME (template);
+ }
+ else if (TREE_CODE_CLASS (TREE_CODE (d1)) == 't' && IS_AGGR_TYPE (d1))
+ {
+ template = CLASSTYPE_TI_TEMPLATE (d1);
+ d1 = DECL_NAME (template);
+ }
+ else
+ my_friendly_abort (272);
- my_friendly_assert (TREE_CODE (d1) == IDENTIFIER_NODE, 272);
- template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
- if (! template)
- template = IDENTIFIER_CLASS_VALUE (d1);
/* With something like `template <class T> class X class X { ... };'
we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE.
We don't want to do that, but we have to deal with the situation, so
@@ -595,112 +1374,99 @@ lookup_template_class (d1, arglist, in_decl)
cp_error_at ("for template declaration `%D'", in_decl);
return error_mark_node;
}
- parmlist = DECL_TEMPLATE_PARMS (template);
- arglist = coerce_template_parms (parmlist, arglist, template);
- if (arglist == error_mark_node)
- return error_mark_node;
- if (uses_template_parms (arglist))
- {
- tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
- tree d;
- id = make_anon_name ();
- d = build_decl (TYPE_DECL, id, t);
- TYPE_NAME (t) = d;
- TYPE_VALUES (t) = build_tree_list (template, arglist);
- pushdecl_top_level (d);
- }
- else
+ if (PRIMARY_TEMPLATE_P (template))
{
+ parmlist = DECL_INNERMOST_TEMPLATE_PARMS (template);
+
+ arglist = coerce_template_parms (parmlist, arglist, template);
+ if (arglist == error_mark_node)
+ return error_mark_node;
+ if (uses_template_parms (arglist))
+ {
+ tree found;
+ if (comp_template_args
+ (CLASSTYPE_TI_ARGS (TREE_TYPE (template)), arglist))
+ found = TREE_TYPE (template);
+ else
+ {
+ for (found = DECL_TEMPLATE_INSTANTIATIONS (template);
+ found; found = TREE_CHAIN (found))
+ {
+ if (TI_USES_TEMPLATE_PARMS (found)
+ && comp_template_args (TREE_PURPOSE (found), arglist))
+ break;
+ }
+ if (found)
+ found = TREE_VALUE (found);
+ }
+
+ if (found)
+ {
+ if (can_free (&permanent_obstack, arglist))
+ obstack_free (&permanent_obstack, arglist);
+ return found;
+ }
+ }
+
mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
parmlist, arglist);
id = get_identifier (mangled_name);
- }
- if (!IDENTIFIER_TEMPLATE (id))
- {
- arglist = copy_to_permanent (arglist);
- IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE);
- }
- return id;
-}
-
-void
-push_template_decls (parmlist, arglist, class_level)
- tree parmlist, arglist;
- int class_level;
-{
- int i, nparms;
+ IDENTIFIER_TEMPLATE (id) = d1;
- /* Don't want to push values into global context. */
- if (!class_level)
- {
- pushlevel (1);
- declare_pseudo_global_level ();
+ maybe_push_to_top_level (uses_template_parms (arglist));
+ t = xref_tag_from_type (TREE_TYPE (template), id, 1);
+ pop_from_top_level ();
}
-
- nparms = TREE_VEC_LENGTH (parmlist);
-
- for (i = 0; i < nparms; i++)
+ else
{
- int requires_type, is_type;
- tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i));
- tree arg = TREE_VEC_ELT (arglist, i);
- tree decl = 0;
+ tree ctx = lookup_template_class (TYPE_CONTEXT (TREE_TYPE (template)),
+ arglist, in_decl);
+ id = d1;
+ arglist = CLASSTYPE_TI_ARGS (ctx);
- requires_type = TREE_CODE (parm) == TYPE_DECL;
- is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
- if (is_type)
+ if (TYPE_BEING_DEFINED (ctx) && ctx == current_class_type)
{
- /* add typename to namespace */
- if (!requires_type)
- {
- error ("template use error: type provided where value needed");
- continue;
- }
- decl = arg;
- my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273);
- decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl);
+ int save_temp = processing_template_decl;
+ processing_template_decl = 0;
+ t = xref_tag_from_type (TREE_TYPE (template), id, 0);
+ processing_template_decl = save_temp;
}
else
{
- /* add const decl to namespace */
- tree val;
- tree parmtype;
- if (requires_type)
- {
- error ("template use error: value provided where type needed");
- continue;
- }
- parmtype = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (arglist, 0),
- TREE_VEC_LENGTH (arglist), NULL_TREE);
- val = digest_init (parmtype, arg, (tree *) 0);
- if (val != error_mark_node)
- {
- decl = build_decl (CONST_DECL, DECL_NAME (parm),
- parmtype);
- DECL_INITIAL (decl) = val;
- TREE_READONLY (decl) = 1;
- }
- }
- if (decl != 0)
- {
- SET_DECL_ARTIFICIAL (decl);
- layout_decl (decl, 0);
- if (class_level)
- pushdecl_class_level (decl);
- else
- pushdecl (decl);
+ t = lookup_nested_type_by_name (ctx, id);
+ my_friendly_assert (t != NULL_TREE, 42);
}
}
-}
-void
-pop_template_decls (parmlist, arglist, class_level)
- tree parmlist, arglist;
- int class_level;
-{
- if (!class_level)
- poplevel (0, 0, 0);
+ /* Seems to be wanted. */
+ CLASSTYPE_GOT_SEMICOLON (t) = 1;
+
+ if (! CLASSTYPE_TEMPLATE_INFO (t))
+ {
+ arglist = copy_to_permanent (arglist);
+ CLASSTYPE_TEMPLATE_INFO (t)
+ = perm_tree_cons (template, arglist, NULL_TREE);
+ DECL_TEMPLATE_INSTANTIATIONS (template) = perm_tree_cons
+ (arglist, t, DECL_TEMPLATE_INSTANTIATIONS (template));
+ TI_USES_TEMPLATE_PARMS (DECL_TEMPLATE_INSTANTIATIONS (template))
+ = uses_template_parms (arglist);
+
+ SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
+
+ /* We need to set this again after CLASSTYPE_TEMPLATE_INFO is set up. */
+ DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t)) = id;
+ /* if (! uses_template_parms (arglist)) */
+ DECL_ASSEMBLER_NAME (TYPE_MAIN_DECL (t))
+ = get_identifier (build_overload_name (t, 1, 1));
+
+ if (flag_external_templates && ! uses_template_parms (arglist)
+ && CLASSTYPE_INTERFACE_KNOWN (TREE_TYPE (template))
+ && ! CLASSTYPE_INTERFACE_ONLY (TREE_TYPE (template)))
+ add_pending_template (t);
+ }
+
+ return t;
}
/* Should be defined in parse.h. */
@@ -724,7 +1490,7 @@ uses_template_parms (t)
case IDENTIFIER_NODE:
if (!IDENTIFIER_TEMPLATE (t))
return 0;
- return uses_template_parms (TREE_VALUE (IDENTIFIER_TEMPLATE (t)));
+ my_friendly_abort (42);
/* aggregates of tree nodes */
case TREE_VEC:
@@ -749,11 +1515,9 @@ uses_template_parms (t)
if (TYPE_PTRMEMFUNC_FLAG (t))
return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t));
case UNION_TYPE:
- if (!TYPE_NAME (t))
- return 0;
- if (!TYPE_IDENTIFIER (t))
+ if (! CLASSTYPE_TEMPLATE_INFO (t))
return 0;
- return uses_template_parms (TYPE_IDENTIFIER (t));
+ return uses_template_parms (TREE_VALUE (CLASSTYPE_TEMPLATE_INFO (t)));
case FUNCTION_TYPE:
if (uses_template_parms (TYPE_ARG_TYPES (t)))
return 1;
@@ -775,23 +1539,21 @@ uses_template_parms (t)
/* decl nodes */
case TYPE_DECL:
- return uses_template_parms (DECL_NAME (t));
+ return uses_template_parms (TREE_TYPE (t));
+
case FUNCTION_DECL:
- if (uses_template_parms (TREE_TYPE (t)))
+ case VAR_DECL:
+ /* ??? What about FIELD_DECLs? */
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
+ && uses_template_parms (DECL_TI_ARGS (t)))
return 1;
/* fall through */
- case VAR_DECL:
+ case CONST_DECL:
case PARM_DECL:
- /* ??? What about FIELD_DECLs? */
- /* The type of a decl can't use template parms if the name of the
- variable doesn't, because it's impossible to resolve them. So
- ignore the type field for now. */
+ if (uses_template_parms (TREE_TYPE (t)))
+ return 1;
if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t)))
return 1;
- if (uses_template_parms (TREE_TYPE (t)))
- {
- error ("template parms used where they can't be resolved");
- }
return 0;
case CALL_EXPR:
@@ -811,11 +1573,21 @@ uses_template_parms (t)
return uses_template_parms (TYPE_MAX_VALUE (t));
case REAL_TYPE:
+ case COMPLEX_TYPE:
case VOID_TYPE:
- case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
return 0;
+ case ENUMERAL_TYPE:
+ {
+ tree v;
+
+ for (v = TYPE_VALUES (t); v != NULL_TREE; v = TREE_CHAIN (v))
+ if (uses_template_parms (TREE_VALUE (v)))
+ return 1;
+ }
+ return 0;
+
/* constants */
case INTEGER_CST:
case REAL_CST:
@@ -828,20 +1600,36 @@ uses_template_parms (t)
/* NOTREACHED */
return 0;
- case UNINSTANTIATED_P_TYPE:
+ case LOOKUP_EXPR:
+ case TYPENAME_TYPE:
return 1;
+ case SCOPE_REF:
+ return uses_template_parms (TREE_OPERAND (t, 0));
+
case CONSTRUCTOR:
if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
- /* else fall through */
+ return uses_template_parms (TREE_OPERAND (t, 1));
+
+ case MODOP_EXPR:
+ case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case SIZEOF_EXPR:
+ case ARROW_EXPR:
+ case DOTSTAR_EXPR:
+ case TYPEID_EXPR:
+ return 1;
default:
switch (TREE_CODE_CLASS (TREE_CODE (t)))
{
case '1':
case '2':
- case '3':
+ case 'e':
case '<':
{
int i;
@@ -861,77 +1649,42 @@ uses_template_parms (t)
}
}
-void
-instantiate_member_templates (classname)
- tree classname;
-{
- tree t;
- tree id = classname;
- tree members = DECL_TEMPLATE_MEMBERS (TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)));
-
- for (t = members; t; t = TREE_CHAIN (t))
- {
- tree parmvec, type, classparms, tdecl, t2;
- int nparms, xxx = 0, i;
-
- my_friendly_assert (TREE_VALUE (t) != NULL_TREE, 275);
- my_friendly_assert (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_DECL, 276);
- /* @@ Should verify that class parm list is a list of
- distinct template parameters, and covers all the template
- parameters. */
- tdecl = TREE_VALUE (t);
- type = DECL_CONTEXT (DECL_TEMPLATE_RESULT (tdecl));
- classparms = UPT_PARMS (type);
- nparms = TREE_VEC_LENGTH (classparms);
- parmvec = make_tree_vec (nparms);
- for (i = 0; i < nparms; i++)
- TREE_VEC_ELT (parmvec, i) = NULL_TREE;
- switch (unify (DECL_TEMPLATE_PARMS (tdecl),
- &TREE_VEC_ELT (parmvec, 0), nparms,
- type, IDENTIFIER_TYPE_VALUE (classname),
- &xxx))
- {
- case 0:
- /* Success -- well, no inconsistency, at least. */
- for (i = 0; i < nparms; i++)
- if (TREE_VEC_ELT (parmvec, i) == NULL_TREE)
- goto failure;
- t2 = instantiate_template (tdecl,
- &TREE_VEC_ELT (parmvec, 0));
- type = IDENTIFIER_TYPE_VALUE (id);
- my_friendly_assert (type != 0, 277);
- break;
- case 1:
- /* Failure. */
- failure:
- cp_error_at ("type unification error instantiating `%D'", tdecl);
- cp_error ("while instantiating members of `%T'", classname);
-
- continue /* loop of members */;
- default:
- /* Eek, a bug. */
- my_friendly_abort (83);
- }
- }
-}
-
static struct tinst_level *current_tinst_level = 0;
static struct tinst_level *free_tinst_level = 0;
static int tinst_depth = 0;
-int max_tinst_depth = 17;
+extern int max_tinst_depth;
+#ifdef GATHER_STATISTICS
+int depth_reached = 0;
+#endif
-int
-push_tinst_level (name)
- tree name;
+static int
+push_tinst_level (d)
+ tree d;
{
struct tinst_level *new;
- tree global = IDENTIFIER_GLOBAL_VALUE (name);
if (tinst_depth >= max_tinst_depth)
{
+ struct tinst_level *p = current_tinst_level;
+ int line = lineno;
+ char *file = input_filename;
+
error ("template instantiation depth exceeds maximum of %d",
max_tinst_depth);
- cp_error (" instantiating `%D'", name);
+ error (" (use -ftemplate-depth-NN to increase the maximum)");
+ cp_error (" instantiating `%D'", d);
+
+ for (; p; p = p->next)
+ {
+ cp_error (" instantiated from `%D'", p->decl);
+ lineno = p->line;
+ input_filename = p->file;
+ }
+ error (" instantiated from here");
+
+ lineno = line;
+ input_filename = file;
+
return 0;
}
@@ -943,20 +1696,18 @@ push_tinst_level (name)
else
new = (struct tinst_level *) xmalloc (sizeof (struct tinst_level));
- new->classname = name;
- if (global)
- {
- new->line = DECL_SOURCE_LINE (global);
- new->file = DECL_SOURCE_FILE (global);
- }
- else
- {
- new->line = lineno;
- new->file = input_filename;
- }
+ new->decl = d;
+ new->line = lineno;
+ new->file = input_filename;
new->next = current_tinst_level;
current_tinst_level = new;
+
++tinst_depth;
+#ifdef GATHER_STATISTICS
+ if (tinst_depth > depth_reached)
+ depth_reached = tinst_depth;
+#endif
+
return 1;
}
@@ -983,118 +1734,261 @@ tinst_for_decl ()
}
tree
-instantiate_class_template (classname, setup_parse)
- tree classname;
- int setup_parse;
+instantiate_class_template (type)
+ tree type;
{
- struct template_info *template_info;
- tree template, t1;
+ tree template, template_info, args, pattern, t, *field_chain;
- if (classname == error_mark_node)
+ if (type == error_mark_node)
return error_mark_node;
- my_friendly_assert (TREE_CODE (classname) == IDENTIFIER_NODE, 278);
- template = IDENTIFIER_TEMPLATE (classname);
+ template_info = CLASSTYPE_TEMPLATE_INFO (type);
- if (IDENTIFIER_HAS_TYPE_VALUE (classname))
- {
- tree type = IDENTIFIER_TYPE_VALUE (classname);
- if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)
- return type;
- if (TYPE_BEING_DEFINED (type)
- || TYPE_SIZE (type)
- || CLASSTYPE_USE_TEMPLATE (type) != 0)
- return type;
- }
+ if (TYPE_BEING_DEFINED (type) || TYPE_SIZE (type))
+ return type;
- /* If IDENTIFIER_LOCAL_VALUE is already set on this template classname
- (it's something like `foo<int>'), that means we're already working on
- the instantiation for it. Normally, a classname comes in with nothing
- but its IDENTIFIER_TEMPLATE slot set. If we were to try to instantiate
- this again, we'd get a redeclaration error. Since we're already working
- on it, we'll pass back this classname's TYPE_DECL (it's the value of
- the classname's IDENTIFIER_LOCAL_VALUE). Only do this if we're setting
- things up for the parser, though---if we're just trying to instantiate
- it (e.g., via tsubst) we can trip up cuz it may not have an
- IDENTIFIER_TYPE_VALUE when it will need one. */
- if (setup_parse && IDENTIFIER_LOCAL_VALUE (classname))
- return IDENTIFIER_LOCAL_VALUE (classname);
+ template = TI_TEMPLATE (template_info);
+ my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
+ args = TI_ARGS (template_info);
- if (uses_template_parms (classname))
+ t = most_specialized_class
+ (DECL_TEMPLATE_SPECIALIZATIONS (template), args);
+
+ if (t == error_mark_node)
{
- if (!TREE_TYPE (classname))
+ char *str = "candidates are:";
+ cp_error ("ambiguous class template instantiation for `%#T'", type);
+ for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
{
- tree t = make_lang_type (RECORD_TYPE);
- tree d = build_decl (TYPE_DECL, classname, t);
- DECL_NAME (d) = classname;
- TYPE_NAME (t) = d;
- pushdecl (d);
+ if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
+ {
+ cp_error_at ("%s %+#T", str, TREE_TYPE (t));
+ str = " ";
+ }
}
- return NULL_TREE;
+ TYPE_BEING_DEFINED (type) = 1;
+ return error_mark_node;
}
+ else if (t)
+ pattern = TREE_TYPE (t);
+ else
+ pattern = TREE_TYPE (template);
- t1 = TREE_PURPOSE (template);
- my_friendly_assert (TREE_CODE (t1) == TEMPLATE_DECL, 279);
+ if (TYPE_SIZE (pattern) == NULL_TREE)
+ return type;
- /* If a template is declared but not defined, accept it; don't crash.
- Later uses requiring the definition will be flagged as errors by
- other code. Thanks to niklas@appli.se for this bug fix. */
- if (DECL_TEMPLATE_INFO (t1)->text == 0)
- setup_parse = 0;
+ if (t)
+ args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
- push_to_top_level ();
- template_info = DECL_TEMPLATE_INFO (t1);
- if (setup_parse && push_tinst_level (classname))
- {
- push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)),
- TREE_VALUE (template), 0);
- set_current_level_tags_transparency (1);
- feed_input (template_info->text, template_info->length, (struct obstack *)0);
- lineno = template_info->lineno;
- input_filename = template_info->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- overload_template_name (classname, 0);
- /* Kludge so that we don't get screwed by our own base classes. */
- TYPE_BEING_DEFINED (TREE_TYPE (classname)) = 1;
- yychar = PRE_PARSED_CLASS_DECL;
- yylval.ttype = classname;
- processing_template_defn++;
- if (!flag_external_templates)
- interface_unknown++;
- template_classes
- = perm_tree_cons (classname, NULL_TREE, template_classes);
+ TYPE_BEING_DEFINED (type) = 1;
+
+ if (! push_tinst_level (type))
+ return type;
+
+ maybe_push_to_top_level (uses_template_parms (type));
+ pushclass (type, 0);
+
+ if (flag_external_templates)
+ {
+ if (flag_alt_external_templates)
+ {
+ CLASSTYPE_INTERFACE_ONLY (type) = interface_only;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X (type, interface_unknown);
+ CLASSTYPE_VTABLE_NEEDS_WRITING (type)
+ = ! CLASSTYPE_INTERFACE_ONLY (type)
+ && CLASSTYPE_INTERFACE_KNOWN (type);
+ }
+ else
+ {
+ CLASSTYPE_INTERFACE_ONLY (type) = CLASSTYPE_INTERFACE_ONLY (pattern);
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X
+ (type, CLASSTYPE_INTERFACE_UNKNOWN (pattern));
+ CLASSTYPE_VTABLE_NEEDS_WRITING (type)
+ = ! CLASSTYPE_INTERFACE_ONLY (type)
+ && CLASSTYPE_INTERFACE_KNOWN (type);
+ }
}
else
{
- tree t, decl, id, tmpl;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
+ CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
+ }
+
+ TYPE_HAS_CONSTRUCTOR (type) = TYPE_HAS_CONSTRUCTOR (pattern);
+ TYPE_HAS_DESTRUCTOR (type) = TYPE_HAS_DESTRUCTOR (pattern);
+ TYPE_HAS_ASSIGNMENT (type) = TYPE_HAS_ASSIGNMENT (pattern);
+ TYPE_OVERLOADS_CALL_EXPR (type) = TYPE_OVERLOADS_CALL_EXPR (pattern);
+ TYPE_OVERLOADS_ARRAY_REF (type) = TYPE_OVERLOADS_ARRAY_REF (pattern);
+ TYPE_OVERLOADS_ARROW (type) = TYPE_OVERLOADS_ARROW (pattern);
+ TYPE_GETS_NEW (type) = TYPE_GETS_NEW (pattern);
+ TYPE_GETS_DELETE (type) = TYPE_GETS_DELETE (pattern);
+ TYPE_VEC_DELETE_TAKES_SIZE (type) = TYPE_VEC_DELETE_TAKES_SIZE (pattern);
+ TYPE_HAS_ASSIGN_REF (type) = TYPE_HAS_ASSIGN_REF (pattern);
+ TYPE_HAS_CONST_ASSIGN_REF (type) = TYPE_HAS_CONST_ASSIGN_REF (pattern);
+ TYPE_HAS_ABSTRACT_ASSIGN_REF (type) = TYPE_HAS_ABSTRACT_ASSIGN_REF (pattern);
+ TYPE_HAS_INIT_REF (type) = TYPE_HAS_INIT_REF (pattern);
+ TYPE_HAS_CONST_INIT_REF (type) = TYPE_HAS_CONST_INIT_REF (pattern);
+ TYPE_GETS_INIT_AGGR (type) = TYPE_GETS_INIT_AGGR (pattern);
+ TYPE_HAS_DEFAULT_CONSTRUCTOR (type) = TYPE_HAS_DEFAULT_CONSTRUCTOR (pattern);
+ TYPE_HAS_CONVERSION (type) = TYPE_HAS_CONVERSION (pattern);
+ TYPE_USES_COMPLEX_INHERITANCE (type)
+ = TYPE_USES_COMPLEX_INHERITANCE (pattern);
+ TYPE_USES_MULTIPLE_INHERITANCE (type)
+ = TYPE_USES_MULTIPLE_INHERITANCE (pattern);
+ TYPE_USES_VIRTUAL_BASECLASSES (type)
+ = TYPE_USES_VIRTUAL_BASECLASSES (pattern);
+ TYPE_PACKED (type) = TYPE_PACKED (pattern);
+ TYPE_ALIGN (type) = TYPE_ALIGN (pattern);
+
+ {
+ tree binfo = TYPE_BINFO (type);
+ tree pbases = TYPE_BINFO_BASETYPES (pattern);
+
+ if (pbases)
+ {
+ tree bases;
+ int i;
+ int len = TREE_VEC_LENGTH (pbases);
+ bases = make_tree_vec (len);
+ for (i = 0; i < len; ++i)
+ {
+ tree elt;
+
+ TREE_VEC_ELT (bases, i) = elt
+ = tsubst (TREE_VEC_ELT (pbases, i), args,
+ TREE_VEC_LENGTH (args), NULL_TREE);
+ BINFO_INHERITANCE_CHAIN (elt) = binfo;
+
+ if (! IS_AGGR_TYPE (TREE_TYPE (elt)))
+ cp_error
+ ("base type `%T' of `%T' fails to be a struct or class type",
+ TREE_TYPE (elt), type);
+ else if (! uses_template_parms (type)
+ && (TYPE_SIZE (complete_type (TREE_TYPE (elt)))
+ == NULL_TREE))
+ cp_error ("base class `%T' of `%T' has incomplete type",
+ TREE_TYPE (elt), type);
+ }
+ /* Don't initialize this until the vector is filled out, or
+ lookups will crash. */
+ BINFO_BASETYPES (binfo) = bases;
+ }
+ }
- id = classname;
- tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id));
- t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, NULL_TREE, 0);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
- || TREE_CODE (t) == UNION_TYPE, 280);
+ CLASSTYPE_LOCAL_TYPEDECLS (type) = CLASSTYPE_LOCAL_TYPEDECLS (pattern);
- /* Now, put a copy of the decl in global scope, to avoid
- * recursive expansion. */
- decl = IDENTIFIER_LOCAL_VALUE (id);
- if (!decl)
- decl = IDENTIFIER_CLASS_VALUE (id);
- if (decl)
+ field_chain = &TYPE_FIELDS (type);
+
+ for (t = CLASSTYPE_TAGS (pattern); t; t = TREE_CHAIN (t))
+ {
+ tree name = TREE_PURPOSE (t);
+ tree tag = TREE_VALUE (t);
+
+ /* These will add themselves to CLASSTYPE_TAGS for the new type. */
+ if (TREE_CODE (tag) == ENUMERAL_TYPE)
{
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 281);
- /* We'd better make sure we're on the permanent obstack or else
- * we'll get a "friendly" abort 124 in pushdecl. Perhaps a
- * copy_to_permanent would be sufficient here, but then a
- * sharing problem might occur. I don't know -- niklas@appli.se */
- push_obstacks (&permanent_obstack, &permanent_obstack);
- pushdecl_top_level (copy_node (decl));
- pop_obstacks ();
+ tree e, newtag = tsubst_enum (tag, args,
+ TREE_VEC_LENGTH (args), field_chain);
+
+ while (*field_chain)
+ {
+ DECL_FIELD_CONTEXT (*field_chain) = type;
+ field_chain = &TREE_CHAIN (*field_chain);
+ }
}
- pop_from_top_level ();
+ else
+ tsubst (tag, args,
+ TREE_VEC_LENGTH (args), NULL_TREE);
}
- return NULL_TREE;
+ /* Don't replace enum constants here. */
+ for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t))
+ if (TREE_CODE (t) != CONST_DECL)
+ {
+ tree r = tsubst (t, args,
+ TREE_VEC_LENGTH (args), NULL_TREE);
+ if (TREE_CODE (r) == VAR_DECL)
+ {
+ if (! uses_template_parms (r))
+ pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics);
+ /* Perhaps I should do more of grokfield here. */
+ start_decl_1 (r);
+ DECL_IN_AGGR_P (r) = 1;
+ DECL_EXTERNAL (r) = 1;
+ cp_finish_decl (r, DECL_INITIAL (r), NULL_TREE, 0, 0);
+ }
+
+ *field_chain = r;
+ field_chain = &TREE_CHAIN (r);
+ }
+
+ TYPE_METHODS (type) = tsubst_chain (TYPE_METHODS (pattern), args);
+ for (t = TYPE_METHODS (type); t; t = TREE_CHAIN (t))
+ {
+ if (DECL_CONSTRUCTOR_P (t))
+ grok_ctor_properties (type, t);
+ else if (IDENTIFIER_OPNAME_P (DECL_NAME (t)))
+ grok_op_properties (t, DECL_VIRTUAL_P (t), 0);
+ }
+
+ DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
+ = tsubst (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)),
+ args, TREE_VEC_LENGTH (args), NULL_TREE);
+
+ {
+ tree d = CLASSTYPE_FRIEND_CLASSES (type)
+ = tsubst (CLASSTYPE_FRIEND_CLASSES (pattern), args,
+ TREE_VEC_LENGTH (args), NULL_TREE);
+
+ /* This does injection for friend classes. */
+ for (; d; d = TREE_CHAIN (d))
+ TREE_VALUE (d) = xref_tag_from_type (TREE_VALUE (d), NULL_TREE, 1);
+
+ d = tsubst (DECL_TEMPLATE_INJECT (template), args,
+ TREE_VEC_LENGTH (args), NULL_TREE);
+
+ for (; d; d = TREE_CHAIN (d))
+ {
+ tree t = TREE_VALUE (d);
+
+ if (TREE_CODE (t) == TYPE_DECL)
+ /* Already injected. */;
+ else
+ pushdecl (t);
+ }
+ }
+
+ if (! uses_template_parms (type))
+ {
+ tree tmp;
+ for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
+ if (TREE_CODE (tmp) == FIELD_DECL)
+ {
+ TREE_TYPE (tmp) = complete_type (TREE_TYPE (tmp));
+ require_complete_type (tmp);
+ }
+
+ type = finish_struct_1 (type, 0);
+ CLASSTYPE_GOT_SEMICOLON (type) = 1;
+
+ repo_template_used (type);
+ if (at_eof && TYPE_BINFO_VTABLE (type) != NULL_TREE)
+ finish_prevtable_vardecl (NULL, TYPE_BINFO_VTABLE (type));
+ }
+ else
+ {
+ TYPE_SIZE (type) = integer_zero_node;
+ CLASSTYPE_METHOD_VEC (type)
+ = finish_struct_methods (type, TYPE_METHODS (type), 1);
+ }
+
+ TYPE_BEING_DEFINED (type) = 0;
+ popclass (0);
+
+ pop_from_top_level ();
+ pop_tinst_level ();
+
+ return type;
}
static int
@@ -1113,77 +2007,90 @@ list_eq (t1, t2)
return list_eq (TREE_CHAIN (t1), TREE_CHAIN (t2));
}
-static tree
+tree
lookup_nested_type_by_name (ctype, name)
tree ctype, name;
{
tree t;
+ complete_type (ctype);
+
for (t = CLASSTYPE_TAGS (ctype); t; t = TREE_CHAIN (t))
{
- if (name == TREE_PURPOSE (t))
+ if (name == TREE_PURPOSE (t)
+ /* this catches typedef enum { foo } bar; */
+ || name == TYPE_IDENTIFIER (TREE_VALUE (t)))
return TREE_VALUE (t);
}
return NULL_TREE;
}
-static tree
-search_nested_type_in_tmpl (tmpl, type)
- tree tmpl, type;
-{
- tree t;
-
- if (tmpl == NULL || TYPE_CONTEXT(type) == NULL)
- return tmpl;
- t = search_nested_type_in_tmpl (tmpl, TYPE_CONTEXT(type));
- if (t == NULL) return t;
- t = lookup_nested_type_by_name(t, DECL_NAME(TYPE_NAME(type)));
- return t;
-}
-
tree
tsubst (t, args, nargs, in_decl)
- tree t, *args;
+ tree t, args;
int nargs;
tree in_decl;
{
tree type;
- if (t == NULL_TREE || t == error_mark_node)
+ if (t == NULL_TREE || t == error_mark_node
+ || t == integer_type_node
+ || t == void_type_node
+ || t == char_type_node)
return t;
type = TREE_TYPE (t);
- if (type
- /* Minor optimization.
- ?? Are these really the most frequent cases? Is the savings
- significant? */
- && type != integer_type_node
- && type != void_type_node
- && type != char_type_node)
+ if (type == unknown_type_node)
+ my_friendly_abort (42);
+ if (type && TREE_CODE (t) != FUNCTION_DECL
+ && TREE_CODE (t) != TYPENAME_TYPE)
type = tsubst (type, args, nargs, in_decl);
switch (TREE_CODE (t))
{
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
- return build_ptrmemfunc_type
- (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, nargs, in_decl));
-
+ {
+ tree r = build_ptrmemfunc_type
+ (tsubst (TYPE_PTRMEMFUNC_FN_TYPE (t), args, nargs, in_decl));
+ return cp_build_type_variant (r, TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ }
+
/* else fall through */
+ case UNION_TYPE:
+ if (uses_template_parms (t))
+ {
+ tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, nargs, in_decl);
+ tree r = lookup_template_class (t, argvec, in_decl);
+ return cp_build_type_variant (r, TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ }
+ /* else fall through */
case ERROR_MARK:
case IDENTIFIER_NODE:
case OP_IDENTIFIER:
case VOID_TYPE:
case REAL_TYPE:
- case ENUMERAL_TYPE:
+ case COMPLEX_TYPE:
case BOOLEAN_TYPE:
case INTEGER_CST:
case REAL_CST:
case STRING_CST:
- case UNION_TYPE:
return t;
+ case ENUMERAL_TYPE:
+ {
+ tree ctx = tsubst (TYPE_CONTEXT (t), args, nargs, in_decl);
+ if (ctx == NULL_TREE)
+ return t;
+ else if (ctx == current_function_decl)
+ return lookup_name (TYPE_IDENTIFIER (t), 1);
+ else
+ return lookup_nested_type_by_name (ctx, TYPE_IDENTIFIER (t));
+ }
+
case INTEGER_TYPE:
if (t == integer_type_node)
return t;
@@ -1191,296 +2098,369 @@ tsubst (t, args, nargs, in_decl)
if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST
&& TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST)
return t;
- return build_index_2_type
- (tsubst (TYPE_MIN_VALUE (t), args, nargs, in_decl),
- tsubst (TYPE_MAX_VALUE (t), args, nargs, in_decl));
- case TEMPLATE_TYPE_PARM:
{
- tree arg = args[TEMPLATE_TYPE_IDX (t)];
- return cp_build_type_variant
- (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
- TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+ tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0);
+ max = tsubst_expr (max, args, nargs, in_decl);
+ if (processing_template_decl)
+ {
+ tree itype = make_node (INTEGER_TYPE);
+ TYPE_MIN_VALUE (itype) = size_zero_node;
+ TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max,
+ integer_one_node);
+ return itype;
+ }
+
+ max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1));
+ return build_index_2_type (size_zero_node, max);
}
+ case TEMPLATE_TYPE_PARM:
case TEMPLATE_CONST_PARM:
- return args[TEMPLATE_CONST_IDX (t)];
+ {
+ int idx;
+ int level;
+
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ {
+ idx = TEMPLATE_TYPE_IDX (t);
+ level = TEMPLATE_TYPE_LEVEL (t);
+ }
+ else
+ {
+ idx = TEMPLATE_CONST_IDX (t);
+ level = TEMPLATE_CONST_LEVEL (t);
+ }
+
+ if (TREE_VEC_LENGTH (args) > 0)
+ {
+ tree arg = NULL_TREE;
+
+ if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+ {
+ if (TREE_VEC_LENGTH (args) >= level - 1)
+ arg = TREE_VEC_ELT
+ (TREE_VEC_ELT (args, level - 1), idx);
+ }
+ else if (level == 1)
+ arg = TREE_VEC_ELT (args, idx);
+
+ if (arg != NULL_TREE)
+ {
+ if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+ return cp_build_type_variant
+ (arg, TYPE_READONLY (arg) || TYPE_READONLY (t),
+ TYPE_VOLATILE (arg) || TYPE_VOLATILE (t));
+ else
+ return arg;
+ }
+ }
+
+ /* If we get here, we must have been looking at a parm for a
+ more deeply nested template. */
+ my_friendly_assert((TREE_CODE (t) == TEMPLATE_CONST_PARM
+ && TEMPLATE_CONST_LEVEL (t) > 1)
+ || (TREE_CODE (t) == TEMPLATE_TYPE_PARM
+ && TEMPLATE_TYPE_LEVEL (t) > 1),
+ 0);
+ return t;
+ }
+
+ case TEMPLATE_DECL:
+ {
+ /* We can get here when processing a member template function
+ of a template class. */
+ tree tmpl;
+ tree decl = DECL_TEMPLATE_RESULT (t);
+ tree new_decl;
+ tree parms;
+ tree spec;
+ int i;
+
+ /* We might already have an instance of this template. */
+ tree instances = DECL_TEMPLATE_INSTANTIATIONS (t);
+ tree ctx = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, in_decl);
+
+ for (; instances; instances = TREE_CHAIN (instances))
+ if (DECL_CLASS_CONTEXT (TREE_VALUE (instances)) == ctx)
+ return TREE_VALUE (instances);
+
+ /* Make a new template decl. It will be similar to the
+ original, but will record the current template arguments.
+ We also create a new function declaration, which is just
+ like the old one, but points to this new template, rather
+ than the old one. */
+ tmpl = copy_node (t);
+ copy_lang_decl (tmpl);
+ my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
+ DECL_CHAIN (tmpl) = NULL_TREE;
+ TREE_CHAIN (tmpl) = NULL_TREE;
+ DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
+ new_decl = tsubst (decl, args, nargs, in_decl);
+ DECL_RESULT (tmpl) = new_decl;
+ DECL_TI_TEMPLATE (new_decl) = tmpl;
+ TREE_TYPE (tmpl) = TREE_TYPE (new_decl);
+ DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE;
+ SET_DECL_IMPLICIT_INSTANTIATION (tmpl);
+
+ /* The template parameters for this new template are all the
+ template parameters for the old template, except the
+ outermost level of parameters. */
+ DECL_TEMPLATE_PARMS (tmpl)
+ = copy_node (DECL_TEMPLATE_PARMS (tmpl));
+ for (parms = DECL_TEMPLATE_PARMS (tmpl);
+ TREE_CHAIN (parms) != NULL_TREE;
+ parms = TREE_CHAIN (parms))
+ TREE_CHAIN (parms) = copy_node (TREE_CHAIN (parms));
+
+ /* Record this partial instantiation. */
+ DECL_TEMPLATE_INSTANTIATIONS (t)
+ = perm_tree_cons (NULL_TREE, tmpl,
+ DECL_TEMPLATE_INSTANTIATIONS (t));
+
+ DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE;
+ return tmpl;
+ }
case FUNCTION_DECL:
{
- tree r;
- tree fnargs, result;
-
- if (type == TREE_TYPE (t)
- && (DECL_CONTEXT (t) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't'))
- return t;
- fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
- result = tsubst (DECL_RESULT (t), args, nargs, t);
+ tree r = NULL_TREE;
+ tree ctx;
+
+ int member;
+
if (DECL_CONTEXT (t) != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
{
- /* Look it up in that class, and return the decl node there,
- instead of creating a new one. */
- tree ctx, methods, name, method;
- int n_methods;
- int i, found = 0;
-
- name = DECL_NAME (t);
- ctx = tsubst (DECL_CONTEXT (t), args, nargs, t);
- methods = CLASSTYPE_METHOD_VEC (ctx);
- if (methods == NULL_TREE)
- /* No methods at all -- no way this one can match. */
- goto no_match;
- n_methods = TREE_VEC_LENGTH (methods);
-
- r = NULL_TREE;
-
- if (!strncmp (OPERATOR_TYPENAME_FORMAT,
- IDENTIFIER_POINTER (name),
- sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
- {
- /* Type-conversion operator. Reconstruct the name, in
- case it's the name of one of the template's parameters. */
- name = build_typename_overload (TREE_TYPE (type));
- }
+ if (DECL_NAME (t) == constructor_name (DECL_CONTEXT (t)))
+ member = 2;
+ else
+ member = 1;
+ ctx = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, t);
+ type = tsubst (type, args, nargs, in_decl);
+ }
+ else
+ {
+ member = 0;
+ ctx = NULL_TREE;
+ type = tsubst (type, args, nargs, in_decl);
+ }
- if (DECL_CONTEXT (t) != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'
- && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t))
- name = constructor_name (ctx);
+ if (type == TREE_TYPE (t)
+ && (! member || ctx == DECL_CLASS_CONTEXT (t)))
+ {
+ t = copy_node (t);
+ copy_lang_decl (t);
+ return t;
+ }
- if (DECL_CONSTRUCTOR_P (t) && TYPE_USES_VIRTUAL_BASECLASSES (ctx))
- {
- /* Since we didn't know that this class had virtual bases until after
- we instantiated it, we have to recreate the arguments to this
- constructor, as otherwise it would miss the __in_chrg parameter. */
- tree newtype, parm;
- tree parms = TREE_CHAIN (TYPE_ARG_TYPES (type));
- parms = hash_tree_chain (integer_type_node, parms);
- newtype = build_cplus_method_type (ctx,
- TREE_TYPE (type),
- parms);
- newtype = build_type_variant (newtype,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- type = newtype;
-
- fnargs = copy_node (DECL_ARGUMENTS (t));
- TREE_CHAIN (fnargs) = TREE_CHAIN (DECL_ARGUMENTS (t));
-
- /* 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) = TREE_CHAIN (fnargs);
- TREE_CHAIN (fnargs) = parm;
-
- fnargs = tsubst (fnargs, args, nargs, t);
- }
-#if 0
- fprintf (stderr, "\nfor function %s in class %s:\n",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
-#endif
- for (i = 0; i < n_methods; i++)
+ /* Do we already have this instantiation? */
+ if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+ {
+ tree tmpl = DECL_TI_TEMPLATE (t);
+ tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+
+ for (; decls; decls = TREE_CHAIN (decls))
+ if (TREE_TYPE (TREE_VALUE (decls)) == type
+ && DECL_CLASS_CONTEXT (TREE_VALUE (decls)) == ctx)
+ return TREE_VALUE (decls);
+ }
+
+ /* We do NOT check for matching decls pushed separately at this
+ point, as they may not represent instantiations of this
+ template, and in any case are considered separate under the
+ discrete model. Instead, see add_maybe_template. */
+
+ r = copy_node (t);
+ copy_lang_decl (r);
+ TREE_TYPE (r) = type;
+
+ DECL_CONTEXT (r)
+ = tsubst (DECL_CONTEXT (t), args, nargs, t);
+ DECL_CLASS_CONTEXT (r) = ctx;
+
+ if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
+ IDENTIFIER_POINTER (DECL_NAME (r)),
+ sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
+ {
+ /* Type-conversion operator. Reconstruct the name, in
+ case it's the name of one of the template's parameters. */
+ DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
+ }
+
+ if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
+ {
+ char *buf, *dbuf = build_overload_name (ctx, 1, 1);
+ int len = sizeof (DESTRUCTOR_DECL_PREFIX) - 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 (r) = get_identifier (buf);
+ }
+ else
+ {
+ /* Instantiations of template functions must be mangled
+ specially, in order to conform to 14.5.5.1
+ [temp.over.link]. We use in_decl below rather than
+ DECL_TI_TEMPLATE (r) because the latter is set to
+ NULL_TREE in instantiate_decl. */
+ tree tmpl;
+ tree arg_types;
+
+ if (DECL_TEMPLATE_INFO (r))
+ tmpl = DECL_TI_TEMPLATE (r);
+ else
+ tmpl = in_decl;
+
+ /* tmpl will be NULL if this is a specialization of a
+ member template of a template class. */
+ if (name_mangling_version < 1
+ || tmpl == NULL_TREE
+ || (member && !is_member_template (tmpl)
+ && !DECL_TEMPLATE_INFO (tmpl)))
{
- int pass;
-
- method = TREE_VEC_ELT (methods, i);
- if (method == NULL_TREE || DECL_NAME (method) != name)
- continue;
-
- pass = 0;
- maybe_error:
- for (; method; method = DECL_CHAIN (method))
- {
- my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL,
- 282);
- if (! comptypes (type, TREE_TYPE (method), 1))
- {
- tree mtype = TREE_TYPE (method);
- tree t1, t2;
-
- /* Keep looking for a method that matches
- perfectly. This takes care of the problem
- where destructors (which have implicit int args)
- look like constructors which have an int arg. */
- if (pass == 0)
- continue;
-
- t1 = TYPE_ARG_TYPES (mtype);
- t2 = TYPE_ARG_TYPES (type);
- if (TREE_CODE (mtype) == FUNCTION_TYPE)
- t2 = TREE_CHAIN (t2);
-
- if (list_eq (t1, t2))
- {
- if (TREE_CODE (mtype) == FUNCTION_TYPE)
- {
- tree newtype;
- newtype = build_function_type (TREE_TYPE (type),
- TYPE_ARG_TYPES (type));
- newtype = build_type_variant (newtype,
- TYPE_READONLY (type),
- TYPE_VOLATILE (type));
- type = newtype;
- if (TREE_TYPE (type) != TREE_TYPE (mtype))
- goto maybe_bad_return_type;
- }
- else if (TYPE_METHOD_BASETYPE (mtype)
- == TYPE_METHOD_BASETYPE (type))
- {
- /* Types didn't match, but arg types and
- `this' do match, so the return type is
- all that should be messing it up. */
- maybe_bad_return_type:
- if (TREE_TYPE (type) != TREE_TYPE (mtype))
- error ("inconsistent return types for method `%s' in class `%s'",
- IDENTIFIER_POINTER (name),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));
- }
- r = method;
- break;
- }
- found = 1;
- continue;
- }
-#if 0
- fprintf (stderr, "\tfound %s\n\n",
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));
-#endif
- if (DECL_ARTIFICIAL (method))
- {
- cp_error ("template for method `%D' which has default implementation in class `%T'", name, ctx);
- if (in_decl)
- cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);
- return error_mark_node;
- }
-
- if (DECL_ARGUMENTS (method)
- && ! TREE_PERMANENT (DECL_ARGUMENTS (method)))
- /* @@ Is this early enough? Might we want to do
- this instead while processing the expansion? */
- DECL_ARGUMENTS (method)
- = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
- r = method;
- break;
- }
- if (r == NULL_TREE && pass == 0)
- {
- pass = 1;
- method = TREE_VEC_ELT (methods, i);
- goto maybe_error;
- }
+ arg_types = TYPE_ARG_TYPES (type);
+ if (member && TREE_CODE (type) == FUNCTION_TYPE)
+ arg_types = hash_tree_chain
+ (build_pointer_type (DECL_CONTEXT (r)),
+ arg_types);
+
+ DECL_ASSEMBLER_NAME (r)
+ = build_decl_overload (DECL_NAME (r), arg_types,
+ member);
}
- if (r == NULL_TREE)
+ else
{
- no_match:
- cp_error
- (found
- ? "template for method `%D' doesn't match any in class `%T'"
- : "method `%D' not found in class `%T'", name, ctx);
- if (in_decl)
- cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl);
- return error_mark_node;
+ /* We pass the outermost template parameters to
+ build_template_decl_overload since the innermost
+ template parameters are still just template
+ parameters; there are no corresponding substitution
+ arguments. */
+ /* FIXME The messed up thing here is that we get here with
+ full args and only one level of parms. This is necessary
+ because when we partially instantiate a member template,
+ even though there's really only one level of parms left
+ we re-use the parms from the original template, which
+ have level 2. When this is fixed we can remove the
+ add_to_template_args from instantiate_template. */
+ tree tparms = DECL_TEMPLATE_PARMS (tmpl);
+
+ while (tparms && TREE_CHAIN (tparms) != NULL_TREE)
+ tparms = TREE_CHAIN (tparms);
+
+ my_friendly_assert (tparms != NULL_TREE
+ && TREE_CODE (tparms) == TREE_LIST,
+ 0);
+ tparms = TREE_VALUE (tparms);
+
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (tmpl));
+ if (member && TREE_CODE (type) == FUNCTION_TYPE)
+ arg_types = hash_tree_chain
+ (build_pointer_type (DECL_CONTEXT (r)),
+ arg_types);
+
+ DECL_ASSEMBLER_NAME (r)
+ = build_template_decl_overload
+ (DECL_NAME (r), arg_types,
+ TREE_TYPE (TREE_TYPE (tmpl)),
+ tparms,
+ TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC
+ ? TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1) :
+ args,
+ member);
}
}
- else
+ DECL_RTL (r) = 0;
+ make_decl_rtl (r, NULL_PTR, 1);
+
+ DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, nargs, t);
+ DECL_MAIN_VARIANT (r) = r;
+ DECL_RESULT (r) = NULL_TREE;
+ DECL_INITIAL (r) = NULL_TREE;
+
+ TREE_STATIC (r) = 0;
+ TREE_PUBLIC (r) = 1;
+ DECL_EXTERNAL (r) = 1;
+ DECL_INTERFACE_KNOWN (r) = 0;
+ DECL_DEFER_OUTPUT (r) = 0;
+ TREE_CHAIN (r) = NULL_TREE;
+ DECL_CHAIN (r) = NULL_TREE;
+
+ if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
+ grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
+
+ /* Look for matching decls for the moment. */
+ if (! member && ! flag_ansi_overloading)
{
- r = DECL_NAME (t);
- {
- tree decls;
- int got_it = 0;
-
- decls = lookup_name_nonclass (r);
- if (decls == NULL_TREE)
- /* no match */;
- else if (TREE_CODE (decls) == TREE_LIST)
- for (decls = TREE_VALUE (decls); decls ;
- decls = DECL_CHAIN (decls))
- {
- if (TREE_CODE (decls) == FUNCTION_DECL
- && TREE_TYPE (decls) == type)
- {
- got_it = 1;
- r = decls;
- break;
- }
- }
- else
+ tree decls = lookup_name_nonclass (DECL_NAME (t));
+ tree d = NULL_TREE;
+
+ if (decls == NULL_TREE)
+ /* no match */;
+ else if (is_overloaded_fn (decls))
+ for (decls = get_first_fn (decls); decls;
+ decls = DECL_CHAIN (decls))
{
- tree val = decls;
- decls = NULL_TREE;
- if (TREE_CODE (val) == FUNCTION_DECL
- && TREE_TYPE (val) == type)
+ if (TREE_CODE (decls) == FUNCTION_DECL
+ && TREE_TYPE (decls) == type)
{
- got_it = 1;
- r = val;
+ d = decls;
+ break;
}
}
- if (!got_it)
- {
- tree a = build_decl_overload (r, TYPE_VALUES (type),
- DECL_CONTEXT (t) != NULL_TREE);
- r = build_lang_decl (FUNCTION_DECL, r, type);
- DECL_ASSEMBLER_NAME (r) = a;
- }
- else if (TREE_STATIC (r))
- {
- /* This overrides the template version, use it. */
- return r;
- }
- }
+ if (d)
+ {
+ int dcl_only = ! DECL_INITIAL (d);
+ if (dcl_only)
+ DECL_INITIAL (r) = error_mark_node;
+ duplicate_decls (r, d);
+ r = d;
+ if (dcl_only)
+ DECL_INITIAL (r) = 0;
+ }
}
- TREE_PUBLIC (r) = 1;
- DECL_EXTERNAL (r) = 1;
- TREE_STATIC (r) = 0;
- DECL_INTERFACE_KNOWN (r) = 0;
- DECL_INLINE (r) = DECL_INLINE (t);
- DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t);
- TREE_READONLY (r) = TREE_READONLY (t);
- TREE_THIS_VOLATILE (r) = TREE_THIS_VOLATILE (t);
- {
-#if 0 /* Maybe later. -jason */
- struct tinst_level *til = tinst_for_decl();
- /* should always be true under new approach */
- if (til)
- {
- DECL_SOURCE_FILE (r) = til->file;
- DECL_SOURCE_LINE (r) = til->line;
- }
- else
-#endif
- {
- DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t);
- DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t);
- }
- }
- DECL_CLASS_CONTEXT (r) = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, t);
- make_decl_rtl (r, NULL_PTR, 1);
- DECL_ARGUMENTS (r) = fnargs;
- DECL_RESULT (r) = result;
-#if 0
- if (DECL_CONTEXT (t) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')
- push_overloaded_decl_top_level (r, 0);
-#endif
+ if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
+ {
+ tree tmpl = DECL_TI_TEMPLATE (t);
+ tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+ tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
+
+ if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
+ argvec = add_to_template_args (DECL_TI_ARGS (tmpl), argvec);
+
+ DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
+ *declsp = perm_tree_cons (argvec, r, *declsp);
+
+ /* If we have a preexisting version of this function, don't expand
+ the template version, use the other instead. */
+ if (TREE_STATIC (r) || DECL_TEMPLATE_SPECIALIZATION (r))
+ SET_DECL_TEMPLATE_SPECIALIZATION (r);
+ else
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+
+ DECL_TEMPLATE_INSTANTIATIONS (tmpl)
+ = tree_cons (argvec, r, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
+ }
+
+ /* Like grokfndecl. If we don't do this, pushdecl will mess up our
+ TREE_CHAIN because it doesn't find a previous decl. Sigh. */
+ if (member
+ && IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) == NULL_TREE)
+ IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r)) = r;
+
return r;
}
case PARM_DECL:
{
- tree r;
- r = build_decl (PARM_DECL, DECL_NAME (t), type);
+ tree r = copy_node (t);
+ TREE_TYPE (r) = type;
DECL_INITIAL (r) = TREE_TYPE (r);
- DECL_ARTIFICIAL (r) = DECL_ARTIFICIAL (t);
+ DECL_CONTEXT (r) = NULL_TREE;
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
@@ -1492,6 +2472,90 @@ tsubst (t, args, nargs, in_decl)
return r;
}
+ case FIELD_DECL:
+ {
+ tree r = copy_node (t);
+ TREE_TYPE (r) = type;
+ copy_lang_decl (r);
+#if 0
+ DECL_FIELD_CONTEXT (r) = tsubst (DECL_FIELD_CONTEXT (t), args, nargs, in_decl);
+#endif
+ DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, nargs, in_decl);
+ TREE_CHAIN (r) = NULL_TREE;
+ return r;
+ }
+
+ case USING_DECL:
+ {
+ tree r = copy_node (t);
+ DECL_INITIAL (r)
+ = tsubst_copy (DECL_INITIAL (t), args, nargs, in_decl);
+ TREE_CHAIN (r) = NULL_TREE;
+ return r;
+ }
+
+ case VAR_DECL:
+ {
+ tree r;
+ tree ctx = tsubst_copy (DECL_CONTEXT (t), args, nargs, in_decl);
+
+ /* Do we already have this instantiation? */
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ {
+ tree tmpl = DECL_TI_TEMPLATE (t);
+ tree decls = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+
+ for (; decls; decls = TREE_CHAIN (decls))
+ if (DECL_CONTEXT (TREE_VALUE (decls)) == ctx)
+ return TREE_VALUE (decls);
+ }
+
+ r = copy_node (t);
+ TREE_TYPE (r) = type;
+ DECL_CONTEXT (r) = ctx;
+ if (TREE_STATIC (r))
+ DECL_ASSEMBLER_NAME (r)
+ = build_static_name (DECL_CONTEXT (r), DECL_NAME (r));
+
+ /* Don't try to expand the initializer until someone tries to use
+ this variable; otherwise we run into circular dependencies. */
+ DECL_INITIAL (r) = NULL_TREE;
+
+ DECL_RTL (r) = 0;
+ DECL_SIZE (r) = 0;
+
+ if (DECL_LANG_SPECIFIC (r))
+ {
+ copy_lang_decl (r);
+ DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r);
+ }
+
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ {
+ tree tmpl = DECL_TI_TEMPLATE (t);
+ tree *declsp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl);
+ tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
+
+ DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
+ *declsp = perm_tree_cons (argvec, r, *declsp);
+ SET_DECL_IMPLICIT_INSTANTIATION (r);
+ }
+ TREE_CHAIN (r) = NULL_TREE;
+ return r;
+ }
+
+ case TYPE_DECL:
+ if (t == TYPE_NAME (TREE_TYPE (t)))
+ return TYPE_NAME (type);
+
+ {
+ tree r = copy_node (t);
+ TREE_TYPE (r) = type;
+ DECL_CONTEXT (r) = current_class_type;
+ TREE_CHAIN (r) = NULL_TREE;
+ return r;
+ }
+
case TREE_LIST:
{
tree purpose, value, chain, result;
@@ -1523,14 +2587,54 @@ tsubst (t, args, nargs, in_decl)
return result;
}
case TREE_VEC:
+ if (type != NULL_TREE)
+ {
+ /* A binfo node. */
+
+ t = copy_node (t);
+
+ if (type == TREE_TYPE (t))
+ return t;
+
+ TREE_TYPE (t) = complete_type (type);
+ if (IS_AGGR_TYPE (type))
+ {
+ BINFO_VTABLE (t) = TYPE_BINFO_VTABLE (type);
+ BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (type);
+ if (TYPE_BINFO_BASETYPES (type) != NULL_TREE)
+ BINFO_BASETYPES (t) = copy_node (TYPE_BINFO_BASETYPES (type));
+ }
+ return t;
+ }
+
+ /* Otherwise, a vector of template arguments. */
{
int len = TREE_VEC_LENGTH (t), need_new = 0, i;
tree *elts = (tree *) alloca (len * sizeof (tree));
+
bzero ((char *) elts, len * sizeof (tree));
for (i = 0; i < len; i++)
{
- elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs, in_decl);
+ elts[i] = tsubst_expr (TREE_VEC_ELT (t, i), args, nargs, in_decl);
+
+ if (TREE_CODE_CLASS (TREE_CODE (elts[i])) != 't'
+ && !uses_template_parms (elts[i]))
+ {
+ /* Sometimes, one of the args was an expression involving a
+ template constant parameter, like N - 1. Now that we've
+ tsubst'd, we might have something like 2 - 1. This will
+ confuse lookup_template_class, so we do constant folding
+ here. We have to unset processing_template_decl, to
+ fool build_expr_from_tree() into building an actual
+ tree. */
+
+ int saved_processing_template_decl = processing_template_decl;
+ processing_template_decl = 0;
+ elts[i] = fold (build_expr_from_tree (elts[i]));
+ processing_template_decl = saved_processing_template_decl;
+ }
+
if (elts[i] != TREE_VEC_ELT (t, i))
need_new = 1;
}
@@ -1541,6 +2645,7 @@ tsubst (t, args, nargs, in_decl)
t = make_tree_vec (len);
for (i = 0; i < len; i++)
TREE_VEC_ELT (t, i) = elts[i];
+
return t;
}
case POINTER_TYPE:
@@ -1569,11 +2674,39 @@ tsubst (t, args, nargs, in_decl)
{
tree values = TYPE_ARG_TYPES (t);
tree context = TYPE_CONTEXT (t);
- tree new_value;
+ tree raises = TYPE_RAISES_EXCEPTIONS (t);
+ tree fntype;
/* Don't bother recursing if we know it won't change anything. */
if (values != void_list_node)
- values = tsubst (values, args, nargs, in_decl);
+ {
+ /* This should probably be rewritten to use hash_tree_cons for
+ the memory savings. */
+ tree first = NULL_TREE;
+ tree last;
+
+ for (; values && values != void_list_node;
+ values = TREE_CHAIN (values))
+ {
+ tree value = TYPE_MAIN_VARIANT (type_decays_to
+ (tsubst (TREE_VALUE (values), args, nargs, in_decl)));
+ /* Don't instantiate default args unless they are used.
+ Handle it in build_over_call instead. */
+ tree purpose = TREE_PURPOSE (values);
+ tree x = build_tree_list (purpose, value);
+
+ if (first)
+ TREE_CHAIN (last) = x;
+ else
+ first = x;
+ last = x;
+ }
+
+ if (values == void_list_node)
+ TREE_CHAIN (last) = void_list_node;
+
+ values = first;
+ }
if (context)
context = tsubst (context, args, nargs, in_decl);
/* Could also optimize cases where return value and
@@ -1589,34 +2722,39 @@ tsubst (t, args, nargs, in_decl)
if (TREE_CODE (t) == FUNCTION_TYPE
&& context == NULL_TREE)
{
- new_value = build_function_type (type, values);
+ fntype = build_function_type (type, values);
}
else if (context == NULL_TREE)
{
tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))),
args, nargs, in_decl);
- new_value = build_cplus_method_type (base, type,
- TREE_CHAIN (values));
+ fntype = build_cplus_method_type (base, type,
+ TREE_CHAIN (values));
}
else
{
- new_value = make_node (TREE_CODE (t));
- TREE_TYPE (new_value) = type;
- TYPE_CONTEXT (new_value) = context;
- TYPE_VALUES (new_value) = values;
- TYPE_SIZE (new_value) = TYPE_SIZE (t);
- TYPE_ALIGN (new_value) = TYPE_ALIGN (t);
- TYPE_MODE (new_value) = TYPE_MODE (t);
+ fntype = make_node (TREE_CODE (t));
+ TREE_TYPE (fntype) = type;
+ TYPE_CONTEXT (fntype) = context;
+ TYPE_VALUES (fntype) = values;
+ TYPE_SIZE (fntype) = TYPE_SIZE (t);
+ TYPE_ALIGN (fntype) = TYPE_ALIGN (t);
+ TYPE_MODE (fntype) = TYPE_MODE (t);
if (TYPE_METHOD_BASETYPE (t))
- TYPE_METHOD_BASETYPE (new_value) = tsubst (TYPE_METHOD_BASETYPE (t),
- args, nargs, in_decl);
+ TYPE_METHOD_BASETYPE (fntype) = tsubst (TYPE_METHOD_BASETYPE (t),
+ args, nargs, in_decl);
/* Need to generate hash value. */
my_friendly_abort (84);
}
- new_value = build_type_variant (new_value,
- TYPE_READONLY (t),
- TYPE_VOLATILE (t));
- return new_value;
+ fntype = build_type_variant (fntype,
+ TYPE_READONLY (t),
+ TYPE_VOLATILE (t));
+ if (raises)
+ {
+ raises = tsubst (raises, args, nargs, in_decl);
+ fntype = build_exception_variant (fntype, raises);
+ }
+ return fntype;
}
case ARRAY_TYPE:
{
@@ -1628,39 +2766,8 @@ tsubst (t, args, nargs, in_decl)
return r;
}
- case UNINSTANTIATED_P_TYPE:
- {
- int nparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (UPT_TEMPLATE (t)));
- tree argvec = make_tree_vec (nparms);
- tree parmvec = UPT_PARMS (t);
- int i;
- tree id, rt;
- for (i = 0; i < nparms; i++)
- TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i),
- args, nargs, in_decl);
- id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec, NULL_TREE);
- if (! IDENTIFIER_HAS_TYPE_VALUE (id)) {
- instantiate_class_template(id, 0);
- /* set up pending_classes */
- add_pending_template (id);
-
- TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (id)) =
- IDENTIFIER_TYPE_VALUE (id);
- }
- rt = IDENTIFIER_TYPE_VALUE (id);
-
- /* kung: this part handles nested type in template definition */
-
- if ( !ANON_AGGRNAME_P (DECL_NAME(TYPE_NAME(t))))
- {
- rt = search_nested_type_in_tmpl (rt, t);
- }
-
- return build_type_variant (rt, TYPE_READONLY (t), TYPE_VOLATILE (t));
- }
-
- case MINUS_EXPR:
case PLUS_EXPR:
+ case MINUS_EXPR:
return fold (build (TREE_CODE (t), TREE_TYPE (t),
tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl)));
@@ -1670,340 +2777,739 @@ tsubst (t, args, nargs, in_decl)
return fold (build1 (TREE_CODE (t), TREE_TYPE (t),
tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl)));
+ case TYPENAME_TYPE:
+ {
+ tree ctx = tsubst (TYPE_CONTEXT (t), args, nargs, in_decl);
+ tree f = make_typename_type (ctx, TYPE_IDENTIFIER (t));
+ return cp_build_type_variant
+ (f, TYPE_READONLY (f) || TYPE_READONLY (t),
+ TYPE_VOLATILE (f) || TYPE_VOLATILE (t));
+ }
+
+ case INDIRECT_REF:
+ return make_pointer_declarator
+ (type, tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl));
+
+ case ADDR_EXPR:
+ return make_reference_declarator
+ (type, tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl));
+
+ case ARRAY_REF:
+ return build_parse_node
+ (ARRAY_REF, tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl));
+
+ case CALL_EXPR:
+ return make_call_declarator
+ (tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ TREE_OPERAND (t, 2),
+ tsubst (TREE_TYPE (t), args, nargs, in_decl));
+
+ case SCOPE_REF:
+ return build_parse_node
+ (TREE_CODE (t), tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl));
+
default:
- sorry ("use of `%s' in function template",
+ sorry ("use of `%s' in template",
tree_code_name [(int) TREE_CODE (t)]);
return error_mark_node;
}
}
+void
+do_pushlevel ()
+{
+ emit_line_note (input_filename, lineno);
+ pushlevel (0);
+ clear_last_expr ();
+ push_momentary ();
+ expand_start_bindings (0);
+}
+
tree
-instantiate_template (tmpl, targ_ptr)
- tree tmpl, *targ_ptr;
+do_poplevel ()
{
- tree targs, fndecl;
- int i, len;
- struct pending_inline *p;
- struct template_info *t;
- struct obstack *old_fmp_obstack;
- extern struct obstack *function_maybepermanent_obstack;
+ tree t;
+ int saved_warn_unused;
- push_obstacks (&permanent_obstack, &permanent_obstack);
- old_fmp_obstack = function_maybepermanent_obstack;
- function_maybepermanent_obstack = &permanent_obstack;
+ if (processing_template_decl)
+ {
+ saved_warn_unused = warn_unused;
+ warn_unused = 0;
+ }
+ expand_end_bindings (getdecls (), kept_level_p (), 0);
+ if (processing_template_decl)
+ warn_unused = saved_warn_unused;
+ t = poplevel (kept_level_p (), 1, 0);
+ pop_momentary ();
+ return t;
+}
- my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
- len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl));
+tree
+tsubst_copy (t, args, nargs, in_decl)
+ tree t, args;
+ int nargs;
+ tree in_decl;
+{
+ enum tree_code code;
- i = len;
- while (i--)
- targ_ptr[i] = copy_to_permanent (targ_ptr[i]);
+ if (t == NULL_TREE || t == error_mark_node)
+ return t;
- for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
- fndecl; fndecl = TREE_CHAIN (fndecl))
+ code = TREE_CODE (t);
+
+ switch (code)
{
- tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0);
- for (i = len - 1; i >= 0; i--)
- if (simple_cst_equal (t1[i], targ_ptr[i]) <= 0)
- goto no_match;
+ case PARM_DECL:
+ return do_identifier (DECL_NAME (t), 0);
- /* Here, we have a match. */
- fndecl = TREE_VALUE (fndecl);
- goto exit;
+ case CONST_DECL:
+ case FIELD_DECL:
+ if (DECL_CONTEXT (t))
+ {
+ tree ctx = tsubst (DECL_CONTEXT (t), args, nargs, in_decl);
+ if (ctx == current_function_decl)
+ return lookup_name (DECL_NAME (t), 0);
+ else if (ctx != DECL_CONTEXT (t))
+ return lookup_field (ctx, DECL_NAME (t), 0, 0);
+ }
+ return t;
- no_match:
- ;
- }
+ case VAR_DECL:
+ case FUNCTION_DECL:
+ if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
+ t = tsubst (t, args, nargs, in_decl);
+ mark_used (t);
+ return t;
- targs = make_tree_vec (len);
- i = len;
- while (i--)
- TREE_VEC_ELT (targs, i) = targ_ptr[i];
+ case TEMPLATE_DECL:
+ if (is_member_template (t))
+ return tsubst (t, args, nargs, in_decl);
+ else
+ return t;
- /* substitute template parameters */
- fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr,
- TREE_VEC_LENGTH (targs), tmpl);
+#if 0
+ case IDENTIFIER_NODE:
+ return do_identifier (t, 0);
+#endif
+
+ case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ return build1
+ (code, tsubst (TREE_TYPE (t), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl));
+
+ case INDIRECT_REF:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case NEGATE_EXPR:
+ case TRUTH_NOT_EXPR:
+ case BIT_NOT_EXPR:
+ case ADDR_EXPR:
+ case CONVERT_EXPR: /* Unary + */
+ case SIZEOF_EXPR:
+ case ARROW_EXPR:
+ case THROW_EXPR:
+ case TYPEID_EXPR:
+ return build1
+ (code, NULL_TREE,
+ tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl));
- if (fndecl == error_mark_node)
- goto exit;
+ 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 COMPONENT_REF:
+ case ARRAY_REF:
+ case COMPOUND_EXPR:
+ case SCOPE_REF:
+ case DOTSTAR_EXPR:
+ case MEMBER_REF:
+ return build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl));
- assemble_external (fndecl);
+ case CALL_EXPR:
+ {
+ tree fn = TREE_OPERAND (t, 0);
+ if (really_overloaded_fn (fn))
+ fn = tsubst_copy (TREE_VALUE (fn), args, nargs, in_decl);
+ else
+ fn = tsubst_copy (fn, args, nargs, in_decl);
+ return build_nt
+ (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ NULL_TREE);
+ }
- /* If it's a static member fn in the template, we need to change it
- into a FUNCTION_TYPE and chop off its this pointer. */
- if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE
- && DECL_STATIC_FUNCTION_P (fndecl))
- {
- revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL);
- /* Chop off the this pointer that grokclassfn so kindly added
- for us (it didn't know yet if the fn was static or not). */
- DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
+ case METHOD_CALL_EXPR:
+ {
+ tree name = TREE_OPERAND (t, 0);
+ if (TREE_CODE (name) == BIT_NOT_EXPR)
+ {
+ name = tsubst_copy (TREE_OPERAND (name, 0), args, nargs, in_decl);
+ name = build1 (BIT_NOT_EXPR, NULL_TREE, TYPE_MAIN_VARIANT (name));
+ }
+ else if (TREE_CODE (name) == SCOPE_REF
+ && TREE_CODE (TREE_OPERAND (name, 1)) == BIT_NOT_EXPR)
+ {
+ tree base = tsubst_copy (TREE_OPERAND (name, 0), args, nargs, in_decl);
+ name = TREE_OPERAND (name, 1);
+ name = tsubst_copy (TREE_OPERAND (name, 0), args, nargs, in_decl);
+ name = build1 (BIT_NOT_EXPR, NULL_TREE, TYPE_MAIN_VARIANT (name));
+ name = build_nt (SCOPE_REF, base, name);
+ }
+ else
+ name = tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl);
+ return build_nt
+ (code, name, tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl),
+ NULL_TREE);
+ }
+
+ case COND_EXPR:
+ case MODOP_EXPR:
+ return build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl));
+
+ case NEW_EXPR:
+ {
+ tree r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 2), args, nargs, in_decl));
+ NEW_EXPR_USE_GLOBAL (r) = NEW_EXPR_USE_GLOBAL (t);
+ return r;
+ }
+
+ case DELETE_EXPR:
+ {
+ tree r = build_nt
+ (code, tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl));
+ DELETE_EXPR_USE_GLOBAL (r) = DELETE_EXPR_USE_GLOBAL (t);
+ DELETE_EXPR_USE_VEC (r) = DELETE_EXPR_USE_VEC (t);
+ return r;
+ }
+
+ case TEMPLATE_ID_EXPR:
+ {
+ tree r = lookup_template_function
+ (tsubst_copy (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl));
+ return r;
+ }
+
+ case TREE_LIST:
+ {
+ tree purpose, value, chain;
+
+ if (t == void_list_node)
+ return t;
+
+ purpose = TREE_PURPOSE (t);
+ if (purpose)
+ purpose = tsubst_copy (purpose, args, nargs, in_decl);
+ value = TREE_VALUE (t);
+ if (value)
+ value = tsubst_copy (value, args, nargs, in_decl);
+ chain = TREE_CHAIN (t);
+ if (chain && chain != void_type_node)
+ chain = tsubst_copy (chain, args, nargs, in_decl);
+ if (purpose == TREE_PURPOSE (t)
+ && value == TREE_VALUE (t)
+ && chain == TREE_CHAIN (t))
+ return t;
+ return tree_cons (purpose, value, chain);
+ }
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ case INTEGER_TYPE:
+ case TEMPLATE_TYPE_PARM:
+ case TEMPLATE_CONST_PARM:
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ case OFFSET_TYPE:
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ case ARRAY_TYPE:
+ case TYPENAME_TYPE:
+ return tsubst (t, args, nargs, in_decl);
+
+ case IDENTIFIER_NODE:
+ if (IDENTIFIER_TYPENAME_P (t))
+ return build_typename_overload
+ (tsubst (TREE_TYPE (t), args, nargs, in_decl));
+ else
+ return t;
+
+ case CONSTRUCTOR:
+ return build
+ (CONSTRUCTOR, tsubst (TREE_TYPE (t), args, nargs, in_decl), NULL_TREE,
+ tsubst_copy (CONSTRUCTOR_ELTS (t), args, nargs, in_decl));
+
+ default:
+ return t;
}
-
- t = DECL_TEMPLATE_INFO (tmpl);
-
- /* If we have a preexisting version of this function, don't expand
- the template version, use the other instead. */
- if (TREE_STATIC (fndecl) || DECL_TEMPLATE_SPECIALIZATION (fndecl))
- {
- SET_DECL_TEMPLATE_SPECIALIZATION (fndecl);
- p = (struct pending_inline *)0;
- }
- else if (t->text)
- {
- SET_DECL_IMPLICIT_INSTANTIATION (fndecl);
- repo_template_used (fndecl);
- p = (struct pending_inline *) permalloc (sizeof (struct pending_inline));
- p->parm_vec = t->parm_vec;
- p->bindings = targs;
- p->can_free = 0;
- p->deja_vu = 0;
- p->buf = t->text;
- p->len = t->length;
- p->fndecl = fndecl;
+}
+
+tree
+tsubst_expr (t, args, nargs, in_decl)
+ tree t, args;
+ int nargs;
+ tree in_decl;
+{
+ if (t == NULL_TREE || t == error_mark_node)
+ return t;
+
+ if (processing_template_decl)
+ return tsubst_copy (t, args, nargs, in_decl);
+
+ switch (TREE_CODE (t))
+ {
+ case RETURN_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ c_expand_return
+ (tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl));
+ finish_stmt ();
+ break;
+
+ case EXPR_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ t = tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+ /* Do default conversion if safe and possibly important,
+ in case within ({...}). */
+ if ((TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE && lvalue_p (t))
+ || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+ t = default_conversion (t);
+ cplus_expand_expr_stmt (t);
+ clear_momentary ();
+ finish_stmt ();
+ break;
+
+ case DECL_STMT:
{
- int l = lineno;
- char * f = input_filename;
+ int i = suspend_momentary ();
+ tree dcl, init;
+
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ dcl = start_decl
+ (tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl),
+ TREE_OPERAND (t, 2) != 0);
+ init = tsubst_expr (TREE_OPERAND (t, 2), args, nargs, in_decl);
+ cp_finish_decl
+ (dcl, init, NULL_TREE, 1, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
+ resume_momentary (i);
+ return dcl;
+ }
- lineno = p->lineno = t->lineno;
- input_filename = p->filename = t->filename;
+ case FOR_STMT:
+ {
+ tree tmp;
+ int init_scope = (flag_new_for_scope > 0 && TREE_OPERAND (t, 0)
+ && TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
+ int cond_scope = (TREE_OPERAND (t, 1)
+ && TREE_CODE (TREE_OPERAND (t, 1)) == DECL_STMT);
+
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ if (init_scope)
+ do_pushlevel ();
+ for (tmp = TREE_OPERAND (t, 0); tmp; tmp = TREE_CHAIN (tmp))
+ tsubst_expr (tmp, args, nargs, in_decl);
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop_continue_elsewhere (1);
+
+ if (cond_scope)
+ do_pushlevel ();
+ tmp = tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl);
+ emit_line_note (input_filename, lineno);
+ if (tmp)
+ expand_exit_loop_if_false (0, condition_conversion (tmp));
+
+ if (! cond_scope)
+ do_pushlevel ();
+ tsubst_expr (TREE_OPERAND (t, 3), args, nargs, in_decl);
+ do_poplevel ();
+
+ emit_line_note (input_filename, lineno);
+ expand_loop_continue_here ();
+ tmp = tsubst_expr (TREE_OPERAND (t, 2), args, nargs, in_decl);
+ if (tmp)
+ cplus_expand_expr_stmt (tmp);
+
+ expand_end_loop ();
+ if (init_scope)
+ do_poplevel ();
+ finish_stmt ();
+ }
+ break;
+
+ case WHILE_STMT:
+ {
+ tree cond;
+
+ lineno = TREE_COMPLEXITY (t);
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop (1);
+
+ cond = TREE_OPERAND (t, 0);
+ if (TREE_CODE (cond) == DECL_STMT)
+ do_pushlevel ();
+ cond = tsubst_expr (cond, args, nargs, in_decl);
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, condition_conversion (cond));
+
+ if (TREE_CODE (TREE_OPERAND (t, 0)) != DECL_STMT)
+ do_pushlevel ();
+ tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl);
+ do_poplevel ();
+
+ expand_end_loop ();
+ finish_stmt ();
+ }
+ break;
+
+ case DO_STMT:
+ {
+ tree cond;
- extract_interface_info ();
+ lineno = TREE_COMPLEXITY (t);
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop_continue_elsewhere (1);
- if (interface_unknown && flag_external_templates)
+ tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+ expand_loop_continue_here ();
+
+ cond = tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl);
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, condition_conversion (cond));
+ expand_end_loop ();
+
+ clear_momentary ();
+ finish_stmt ();
+ }
+ break;
+
+ case IF_STMT:
+ {
+ tree tmp;
+ int cond_scope = (TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
+
+ lineno = TREE_COMPLEXITY (t);
+ if (cond_scope)
+ do_pushlevel ();
+ tmp = tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+ emit_line_note (input_filename, lineno);
+ expand_start_cond (condition_conversion (tmp), 0);
+
+ if (tmp = TREE_OPERAND (t, 1), tmp)
+ tsubst_expr (tmp, args, nargs, in_decl);
+
+ if (tmp = TREE_OPERAND (t, 2), tmp)
{
- if (DECL_CLASS_CONTEXT (fndecl)
- && CLASSTYPE_INTERFACE_KNOWN (DECL_CLASS_CONTEXT (fndecl)))
- {
- interface_unknown = 0;
- interface_only
- = CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl));
- }
- else if (! DECL_IN_SYSTEM_HEADER (tmpl))
- warn_if_unknown_interface (tmpl);
+ expand_start_else ();
+ tsubst_expr (tmp, args, nargs, in_decl);
}
- if (interface_unknown || ! flag_external_templates)
- p->interface = 1; /* unknown */
- else
- p->interface = interface_only ? 0 : 2;
+ expand_end_cond ();
- lineno = l;
- input_filename = f;
+ if (cond_scope)
+ do_poplevel ();
- extract_interface_info ();
+ finish_stmt ();
}
- }
- else
- p = (struct pending_inline *)0;
+ break;
- DECL_TEMPLATE_INSTANTIATIONS (tmpl) =
- tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
+ case COMPOUND_STMT:
+ {
+ tree substmt = TREE_OPERAND (t, 0);
- if (p == (struct pending_inline *)0)
- {
- /* do nothing */
- }
- else if (DECL_INLINE (fndecl))
- {
- DECL_PENDING_INLINE_INFO (fndecl) = p;
- p->next = pending_inlines;
- pending_inlines = p;
- }
- else
- {
- p->next = pending_template_expansions;
- pending_template_expansions = p;
- }
- exit:
- function_maybepermanent_obstack = old_fmp_obstack;
- pop_obstacks ();
+ lineno = TREE_COMPLEXITY (t);
- return fndecl;
-}
+ if (COMPOUND_STMT_NO_SCOPE (t) == 0)
+ do_pushlevel ();
-/* classlevel should now never be true. jason 4/12/94 */
-void
-undo_template_name_overload (id, classlevel)
- tree id;
- int classlevel;
-{
- tree template;
+ for (; substmt; substmt = TREE_CHAIN (substmt))
+ tsubst_expr (substmt, args, nargs, in_decl);
- template = IDENTIFIER_TEMPLATE (id);
- if (!template)
- return;
+ if (COMPOUND_STMT_NO_SCOPE (t) == 0)
+ do_poplevel ();
+ }
+ break;
+
+ case BREAK_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ if (! expand_exit_something ())
+ error ("break statement not within loop or switch");
+ break;
+
+ case CONTINUE_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ if (! expand_continue_loop (0))
+ error ("continue statement not within a loop");
+ break;
+
+ case SWITCH_STMT:
+ {
+ tree val, tmp;
+ int cond_scope = (TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
+
+ lineno = TREE_COMPLEXITY (t);
+ if (cond_scope)
+ do_pushlevel ();
+ val = tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+ emit_line_note (input_filename, lineno);
+ c_expand_start_case (val);
+ push_switch ();
+
+ if (tmp = TREE_OPERAND (t, 1), tmp)
+ tsubst_expr (tmp, args, nargs, in_decl);
-#if 0 /* not yet, should get fixed properly later */
- poplevel (0, 0, 0);
-#endif
-#if 1 /* XXX */
- /* This was a botch... See `overload_template_name' just below. */
- if (!classlevel)
- poplevel (0, 0, 0);
-#endif
+ expand_end_case (val);
+ pop_switch ();
+
+ if (cond_scope)
+ do_poplevel ();
+
+ finish_stmt ();
+ }
+ break;
+
+ case CASE_LABEL:
+ do_case (tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl),
+ tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl));
+ break;
+
+ case LABEL_DECL:
+ t = define_label (DECL_SOURCE_FILE (t), DECL_SOURCE_LINE (t),
+ DECL_NAME (t));
+ if (t)
+ expand_label (t);
+ break;
+
+ case GOTO_STMT:
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ if (TREE_CODE (TREE_OPERAND (t, 0)) == IDENTIFIER_NODE)
+ {
+ tree decl = lookup_label (TREE_OPERAND (t, 0));
+ TREE_USED (decl) = 1;
+ expand_goto (decl);
+ }
+ else
+ expand_computed_goto
+ (tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl));
+ break;
+
+ case TRY_BLOCK:
+ lineno = TREE_COMPLEXITY (t);
+ emit_line_note (input_filename, lineno);
+ expand_start_try_stmts ();
+ tsubst_expr (TREE_OPERAND (t, 0), args, nargs, in_decl);
+ expand_start_all_catch ();
+ {
+ tree handler = TREE_OPERAND (t, 1);
+ for (; handler; handler = TREE_CHAIN (handler))
+ tsubst_expr (handler, args, nargs, in_decl);
+ }
+ expand_end_all_catch ();
+ break;
+
+ case HANDLER:
+ lineno = TREE_COMPLEXITY (t);
+ do_pushlevel ();
+ if (TREE_OPERAND (t, 0))
+ {
+ tree d = TREE_OPERAND (t, 0);
+ expand_start_catch_block
+ (tsubst (TREE_OPERAND (d, 1), args, nargs, in_decl),
+ tsubst (TREE_OPERAND (d, 0), args, nargs, in_decl));
+ }
+ else
+ expand_start_catch_block (NULL_TREE, NULL_TREE);
+ tsubst_expr (TREE_OPERAND (t, 1), args, nargs, in_decl);
+ expand_end_catch_block ();
+ do_poplevel ();
+ break;
+
+ case TAG_DEFN:
+ lineno = TREE_COMPLEXITY (t);
+ t = TREE_TYPE (t);
+ if (TREE_CODE (t) == ENUMERAL_TYPE)
+ tsubst_enum (t, args, nargs, NULL);
+ break;
+
+ default:
+ return build_expr_from_tree (tsubst_copy (t, args, nargs, in_decl));
+ }
+ return NULL_TREE;
}
-/* classlevel should now never be true. jason 4/12/94 */
-void
-overload_template_name (id, classlevel)
- tree id;
- int classlevel;
+tree
+instantiate_template (tmpl, targ_ptr)
+ tree tmpl, targ_ptr;
{
- tree template, t, decl;
- struct template_info *tinfo;
+ tree fndecl;
+ int i, len;
+ struct obstack *old_fmp_obstack;
+ extern struct obstack *function_maybepermanent_obstack;
- my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 284);
- template = IDENTIFIER_TEMPLATE (id);
- if (!template)
- return;
+ my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
+
+ if (DECL_FUNCTION_TEMPLATE_P (tmpl))
+ {
+ tree specs;
+
+ /* Check to see if there is a matching specialization. */
+ for (specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ specs != NULL_TREE;
+ specs = TREE_CHAIN (specs))
+ if (comp_template_args (TREE_PURPOSE (specs), targ_ptr))
+ return TREE_VALUE (specs);
+ }
+
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ old_fmp_obstack = function_maybepermanent_obstack;
+ function_maybepermanent_obstack = &permanent_obstack;
- template = TREE_PURPOSE (template);
- tinfo = DECL_TEMPLATE_INFO (template);
- template = DECL_NAME (template);
- my_friendly_assert (template != NULL_TREE, 285);
+ len = DECL_NTPARMS (tmpl);
-#if 1 /* XXX */
- /* This was a botch... names of templates do not get their own private
- scopes. Rather, they should go into the binding level already created
- by push_template_decls. Except that there isn't one of those for
- specializations. */
- if (!classlevel)
+ i = len;
+ while (i--)
{
- pushlevel (1);
- declare_pseudo_global_level ();
+ tree t = TREE_VEC_ELT (targ_ptr, i);
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+ {
+ tree nt = target_type (t);
+ if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
+ {
+ cp_error ("type `%T' composed from a local class is not a valid template-argument", t);
+ cp_error (" trying to instantiate `%D'", tmpl);
+ fndecl = error_mark_node;
+ goto out;
+ }
+ }
+ TREE_VEC_ELT (targ_ptr, i) = copy_to_permanent (t);
}
-#endif
+ targ_ptr = copy_to_permanent (targ_ptr);
- t = xref_tag (tinfo->aggr, id, NULL_TREE, 1);
- my_friendly_assert (TREE_CODE (t) == RECORD_TYPE
- || TREE_CODE (t) == UNION_TYPE
- || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286);
+ if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
+ targ_ptr = add_to_template_args (DECL_TI_ARGS (tmpl), targ_ptr);
- decl = build_decl (TYPE_DECL, template, t);
- SET_DECL_ARTIFICIAL (decl);
+ /* substitute template parameters */
+ fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
-#if 0 /* fix this later */
- /* We don't want to call here if the work has already been done. */
- t = (classlevel
- ? IDENTIFIER_CLASS_VALUE (template)
- : IDENTIFIER_LOCAL_VALUE (template));
- if (t
- && TREE_CODE (t) == TYPE_DECL
- && TREE_TYPE (t) == t)
- my_friendly_abort (85);
-#endif
+ if (flag_external_templates)
+ add_pending_template (fndecl);
- if (classlevel)
- pushdecl_class_level (decl);
- else
- pushdecl (decl);
+ out:
+ function_maybepermanent_obstack = old_fmp_obstack;
+ pop_obstacks ();
-#if 0 /* This seems bogus to me; if it isn't, explain why. (jason) */
- /* Fake this for now, just to make dwarfout.c happy. It will have to
- be done in a proper way later on. */
- DECL_CONTEXT (decl) = t;
-#endif
+ return fndecl;
}
-extern struct pending_input *to_be_restored;
+/* Push the name of the class template into the scope of the instantiation. */
-/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */
void
-end_template_instantiation (name)
- tree name;
+overload_template_name (type)
+ tree type;
{
- tree t, decl;
-
- processing_template_defn--;
- if (!flag_external_templates)
- interface_unknown--;
-
- /* Restore the old parser input state. */
- if (yychar == YYEMPTY)
- yychar = yylex ();
- if (yychar != END_OF_SAVED_INPUT)
- error ("parse error at end of class template");
- else
- {
- restore_pending_input (to_be_restored);
- to_be_restored = 0;
- }
-
- /* Our declarations didn't get stored in the global slot, since
- there was a (supposedly tags-transparent) scope in between. */
- t = IDENTIFIER_TYPE_VALUE (name);
- my_friendly_assert (t != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (t)) == 't',
- 287);
- SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t);
- /* Make methods of template classes static, unless
- -fexternal-templates is given. */
- if (!flag_external_templates)
- SET_CLASSTYPE_INTERFACE_UNKNOWN (t);
- decl = IDENTIFIER_GLOBAL_VALUE (name);
- my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 288);
-
- undo_template_name_overload (name, 0);
- t = IDENTIFIER_TEMPLATE (name);
- pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t),
- 0);
- /* This will fix up the type-value field. */
- pushdecl (decl);
- pop_from_top_level ();
+ tree id = DECL_NAME (CLASSTYPE_TI_TEMPLATE (type));
+ tree decl;
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG && TREE_CODE (decl) == TYPE_DECL)
- {
- /* We just completed the definition of a new file-scope type,
- so we can go ahead and output debug-info for it now. */
- TYPE_STUB_DECL (TREE_TYPE (decl)) = decl;
- rest_of_type_compilation (TREE_TYPE (decl), 1);
- }
-#endif /* DWARF_DEBUGGING_INFO */
+ if (IDENTIFIER_CLASS_VALUE (id)
+ && TREE_TYPE (IDENTIFIER_CLASS_VALUE (id)) == type)
+ return;
- /* Restore interface/implementation settings. */
- extract_interface_info ();
+ decl = build_decl (TYPE_DECL, id, type);
+ SET_DECL_ARTIFICIAL (decl);
+ pushdecl_class_level (decl);
}
-
-/* Store away the text of an template. */
-void
-reinit_parse_for_template (yychar, d1, d2)
- int yychar;
- tree d1, d2;
+/* Like type_unification but designed specially to handle conversion
+ operators. */
+
+int
+fn_type_unification (fn, explicit_targs, targs, args, return_type, strict)
+ tree fn, explicit_targs, targs, args, return_type;
+ int strict;
{
- struct template_info *template_info;
- extern struct obstack inline_text_obstack; /* see comment in lex.c */
+ int i, dummy = 0;
+ tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ tree decl_arg_types = args;
- if (d2 == NULL_TREE || d2 == error_mark_node)
+ my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
+
+ if (IDENTIFIER_TYPENAME_P (DECL_NAME (fn)))
{
- lose:
- /* @@ Should use temp obstack, and discard results. */
- reinit_parse_for_block (yychar, &inline_text_obstack, 1);
- return;
+ /* This is a template conversion operator. Use the return types
+ as well as the argument types. */
+ fn_arg_types = scratch_tree_cons (NULL_TREE,
+ TREE_TYPE (TREE_TYPE (fn)),
+ fn_arg_types);
+ decl_arg_types = scratch_tree_cons (NULL_TREE,
+ return_type,
+ decl_arg_types);
}
- if (TREE_CODE (d2) == IDENTIFIER_NODE)
- d2 = IDENTIFIER_GLOBAL_VALUE (d2);
- if (!d2)
- goto lose;
- template_info = DECL_TEMPLATE_INFO (d2);
- if (!template_info)
- {
- template_info = (struct template_info *) permalloc (sizeof (struct template_info));
- bzero ((char *) template_info, sizeof (struct template_info));
- DECL_TEMPLATE_INFO (d2) = template_info;
- }
- template_info->filename = input_filename;
- template_info->lineno = lineno;
- reinit_parse_for_block (yychar, &inline_text_obstack, 1);
- template_info->text = obstack_base (&inline_text_obstack);
- template_info->length = obstack_object_size (&inline_text_obstack);
- obstack_finish (&inline_text_obstack);
- template_info->parm_vec = d1;
+ i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (fn),
+ &TREE_VEC_ELT (targs, 0),
+ fn_arg_types,
+ decl_arg_types,
+ explicit_targs,
+ &dummy, strict, 0);
+
+ return i;
}
+
/* Type unification.
We have a function template signature with one or more references to
@@ -2022,28 +3528,60 @@ reinit_parse_for_template (yychar, d1, d2)
If SUBR is 1, we're being called recursively (to unify the arguments of
a function or method parameter of a function template), so don't zero
- out targs and don't fail on an incomplete match. */
+ out targs and don't fail on an incomplete match.
+
+ If STRICT is 1, the match must be exact (for casts of overloaded
+ addresses, explicit instantiation, and more_specialized). */
int
-type_unification (tparms, targs, parms, args, nsubsts, subr)
+type_unification (tparms, targs, parms, args, targs_in, nsubsts,
+ strict, allow_incomplete)
+ tree tparms, *targs, parms, args, targs_in;
+ int *nsubsts, strict, allow_incomplete;
+{
+ int ntparms = TREE_VEC_LENGTH (tparms);
+ tree t;
+ int i;
+ int r;
+
+ bzero ((char *) targs, sizeof (tree) * ntparms);
+
+ /* Insert any explicit template arguments. They are encoded as the
+ operands of NOP_EXPRs so that unify can tell that they are
+ explicit arguments. */
+ for (i = 0, t = targs_in; t != NULL_TREE; t = TREE_CHAIN (t), ++i)
+ targs[i] = build1 (NOP_EXPR, NULL_TREE, TREE_VALUE (t));
+
+ r = type_unification_real (tparms, targs, parms, args, nsubsts, 0,
+ strict, allow_incomplete);
+
+ for (i = 0, t = targs_in; t != NULL_TREE; t = TREE_CHAIN (t), ++i)
+ if (TREE_CODE (targs[i]) == NOP_EXPR)
+ targs[i] = TREE_OPERAND (targs[i], 0);
+
+ return r;
+}
+
+
+static int
+type_unification_real (tparms, targs, parms, args, nsubsts, subr,
+ strict, allow_incomplete)
tree tparms, *targs, parms, args;
- int *nsubsts, subr;
+ int *nsubsts, subr, strict, allow_incomplete;
{
tree parm, arg;
int i;
int ntparms = TREE_VEC_LENGTH (tparms);
my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
- my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);
+ my_friendly_assert (parms == NULL_TREE
+ || TREE_CODE (parms) == TREE_LIST, 290);
/* ARGS could be NULL (via a call from parse.y to
build_x_function_call). */
if (args)
my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
my_friendly_assert (ntparms > 0, 292);
- if (!subr)
- bzero ((char *) targs, sizeof (tree) * ntparms);
-
while (parms
&& parms != void_list_node
&& args
@@ -2059,11 +3597,38 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
if (arg == unknown_type_node)
return 1;
- if (! uses_template_parms (parm)
- && TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
+ /* Conversions will be performed on a function argument that
+ corresponds with a function parameter that contains only
+ non-deducible template parameters and explicitly specified
+ template parameters. */
+ if (! uses_template_parms (parm))
{
- if (can_convert_arg (parm, TREE_TYPE (arg), arg))
- continue;
+ tree type;
+
+ if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't')
+ type = TREE_TYPE (arg);
+ else
+ {
+ type = arg;
+ arg = NULL_TREE;
+ }
+
+ if (strict)
+ {
+ if (comptypes (parm, type, 1))
+ continue;
+ }
+ else if (arg)
+ {
+ if (can_convert_arg (parm, type, arg))
+ continue;
+ }
+ else
+ {
+ if (can_convert (parm, type))
+ continue;
+ }
+
return 1;
}
@@ -2086,20 +3651,23 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
/* Have to back unify here */
arg = TREE_VALUE (arg);
nsubsts = 0;
- ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg));
+ ntparms = DECL_NTPARMS (arg);
targs = (tree *) alloca (sizeof (tree) * ntparms);
- parm = tree_cons (NULL_TREE, parm, NULL_TREE);
- return type_unification (DECL_TEMPLATE_PARMS (arg), targs,
- TYPE_ARG_TYPES (TREE_TYPE (arg)),
- parm, &nsubsts, 0);
+ parm = expr_tree_cons (NULL_TREE, parm, NULL_TREE);
+ return
+ type_unification (DECL_INNERMOST_TEMPLATE_PARMS (arg),
+ targs,
+ TYPE_ARG_TYPES (TREE_TYPE (arg)),
+ parm, NULL_TREE, &nsubsts, strict,
+ allow_incomplete);
}
arg = TREE_TYPE (arg);
}
#endif
- if (TREE_CODE (arg) == REFERENCE_TYPE)
+ if (! subr && TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
- if (TREE_CODE (parm) != REFERENCE_TYPE)
+ if (! subr && TREE_CODE (parm) != REFERENCE_TYPE)
{
if (TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE)
@@ -2110,7 +3678,7 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
arg = TYPE_MAIN_VARIANT (arg);
}
- switch (unify (tparms, targs, ntparms, parm, arg, nsubsts))
+ switch (unify (tparms, targs, ntparms, parm, arg, nsubsts, strict))
{
case 0:
break;
@@ -2131,17 +3699,19 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
for (i = 0; i < ntparms; i++)
if (!targs[i])
{
- error ("incomplete type unification");
+ if (!allow_incomplete)
+ error ("incomplete type unification");
return 2;
}
return 0;
}
/* Tail recursion is your friend. */
+
static int
-unify (tparms, targs, ntparms, parm, arg, nsubsts)
+unify (tparms, targs, ntparms, parm, arg, nsubsts, strict)
tree tparms, *targs, parm, arg;
- int *nsubsts, ntparms;
+ int *nsubsts, ntparms, strict;
{
int idx;
@@ -2161,15 +3731,29 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
switch (TREE_CODE (parm))
{
+ case TYPENAME_TYPE:
+ /* In a type which contains a nested-name-specifier, template
+ argument values cannot be deduced for template parameters used
+ within the nested-name-specifier. */
+ return 0;
+
case TEMPLATE_TYPE_PARM:
(*nsubsts)++;
- if (TEMPLATE_TYPE_TPARMLIST (parm) != tparms)
- {
- error ("mixed template headers?!");
- my_friendly_abort (86);
- return 1;
- }
idx = TEMPLATE_TYPE_IDX (parm);
+ /* Check for mixed types and values. */
+ if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
+ return 1;
+
+ if (!strict && targs[idx] != NULL_TREE &&
+ TREE_CODE (targs[idx]) == NOP_EXPR)
+ /* An explicit template argument. Don't even try to match
+ here; the overload resolution code will manage check to
+ see whether the call is legal. */
+ return 0;
+
+ if (strict && (TYPE_READONLY (arg) < TYPE_READONLY (parm)
+ || TYPE_VOLATILE (arg) < TYPE_VOLATILE (parm)))
+ return 1;
#if 0
/* Template type parameters cannot contain cv-quals; i.e.
template <class T> void f (T& a, T& b) will not generate
@@ -2186,89 +3770,89 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
}
#endif
/* Simple cases: Value already set, does match or doesn't. */
- if (targs[idx] == arg)
+ if (targs[idx] == arg
+ || (targs[idx]
+ && TREE_CODE (targs[idx]) == NOP_EXPR
+ && TREE_OPERAND (targs[idx], 0) == arg))
return 0;
else if (targs[idx])
return 1;
- /* Check for mixed types and values. */
- if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL)
- return 1;
targs[idx] = arg;
return 0;
case TEMPLATE_CONST_PARM:
(*nsubsts)++;
idx = TEMPLATE_CONST_IDX (parm);
- if (targs[idx] == arg)
- return 0;
- else if (targs[idx])
+ if (targs[idx])
{
- tree t = targs[idx];
- if (TREE_CODE (t) == TREE_CODE (arg))
- switch (TREE_CODE (arg))
- {
- case INTEGER_CST:
- if (tree_int_cst_equal (t, arg))
- return 0;
- break;
- case REAL_CST:
- if (REAL_VALUES_EQUAL (TREE_REAL_CST (t), TREE_REAL_CST (arg)))
- return 0;
- break;
- /* STRING_CST values are not valid template const parms. */
- default:
- ;
- }
- my_friendly_abort (87);
- return 1;
+ int i = cp_tree_equal (targs[idx], arg);
+ if (i == 1)
+ return 0;
+ else if (i == 0)
+ return 1;
+ else
+ my_friendly_abort (42);
}
-/* else if (typeof arg != tparms[idx])
- return 1;*/
targs[idx] = copy_to_permanent (arg);
return 0;
case POINTER_TYPE:
+ if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
+ return unify (tparms, targs, ntparms, parm,
+ TYPE_PTRMEMFUNC_FN_TYPE (arg), nsubsts, strict);
+
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
- nsubsts);
+ nsubsts, strict);
case REFERENCE_TYPE:
if (TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
- return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts);
+ return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg,
+ nsubsts, strict);
case ARRAY_TYPE:
if (TREE_CODE (arg) != ARRAY_TYPE)
return 1;
if (unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), TYPE_DOMAIN (arg),
- nsubsts) != 0)
+ nsubsts, strict) != 0)
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
- nsubsts);
+ nsubsts, strict);
case REAL_TYPE:
+ case COMPLEX_TYPE:
case INTEGER_TYPE:
+ case BOOLEAN_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
if (TREE_CODE (parm) == INTEGER_TYPE)
{
if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg)
- && unify (tparms, targs, ntparms,
- TYPE_MIN_VALUE (parm), TYPE_MIN_VALUE (arg), nsubsts))
+ && unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm),
+ TYPE_MIN_VALUE (arg), nsubsts, strict))
return 1;
if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg)
- && unify (tparms, targs, ntparms,
- TYPE_MAX_VALUE (parm), TYPE_MAX_VALUE (arg), nsubsts))
+ && unify (tparms, targs, ntparms, TYPE_MAX_VALUE (parm),
+ TYPE_MAX_VALUE (arg), nsubsts, strict))
return 1;
}
+ else if (TREE_CODE (parm) == REAL_TYPE
+ && TYPE_MAIN_VARIANT (arg) != TYPE_MAIN_VARIANT (parm))
+ return 1;
+
/* As far as unification is concerned, this wins. Later checks
will invalidate it if necessary. */
return 0;
/* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */
+ /* Type INTEGER_CST can come from ordinary constant template args. */
case INTEGER_CST:
+ while (TREE_CODE (arg) == NOP_EXPR)
+ arg = TREE_OPERAND (arg, 0);
+
if (TREE_CODE (arg) != INTEGER_CST)
return 1;
return !tree_int_cst_equal (parm, arg);
@@ -2280,7 +3864,7 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
t2 = TREE_OPERAND (parm, 1);
return unify (tparms, targs, ntparms, t1,
fold (build (PLUS_EXPR, integer_type_node, arg, t2)),
- nsubsts);
+ nsubsts, strict);
}
case TREE_VEC:
@@ -2293,35 +3877,39 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--)
if (unify (tparms, targs, ntparms,
TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i),
- nsubsts))
+ nsubsts, strict))
return 1;
return 0;
}
- case UNINSTANTIATED_P_TYPE:
- {
- tree a;
- /* Unification of something that is not a class fails. */
- if (! IS_AGGR_TYPE (arg))
- return 1;
- a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg));
- if (a && UPT_TEMPLATE (parm) == TREE_PURPOSE (a))
- return unify (tparms, targs, ntparms, UPT_PARMS (parm),
- TREE_VALUE (a), nsubsts);
- /* FIXME: Should check base conversions here. */
- return 1;
- }
-
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, ntparms, TYPE_PTRMEMFUNC_FN_TYPE (parm),
- arg, nsubsts);
+ arg, nsubsts, strict);
/* Allow trivial conversions. */
- if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg)
+ if (TREE_CODE (arg) != RECORD_TYPE
|| TYPE_READONLY (parm) < TYPE_READONLY (arg)
|| TYPE_VOLATILE (parm) < TYPE_VOLATILE (arg))
return 1;
+
+ if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
+ {
+ tree t = NULL_TREE;
+ if (flag_ansi_overloading && ! strict)
+ t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
+ else if
+ (CLASSTYPE_TEMPLATE_INFO (arg)
+ && CLASSTYPE_TI_TEMPLATE (parm) == CLASSTYPE_TI_TEMPLATE (arg))
+ t = arg;
+ if (! t || t == error_mark_node)
+ return 1;
+
+ return unify (tparms, targs, ntparms, CLASSTYPE_TI_ARGS (parm),
+ CLASSTYPE_TI_ARGS (t), nsubsts, strict);
+ }
+ else if (TYPE_MAIN_VARIANT (parm) != TYPE_MAIN_VARIANT (arg))
+ return 1;
return 0;
case METHOD_TYPE:
@@ -2334,19 +3922,25 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 1;
check_args:
if (unify (tparms, targs, ntparms, TREE_TYPE (parm),
- TREE_TYPE (arg), nsubsts))
+ TREE_TYPE (arg), nsubsts, strict))
return 1;
- return type_unification (tparms, targs, TYPE_ARG_TYPES (parm),
- TYPE_ARG_TYPES (arg), nsubsts, 1);
+ return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+ TYPE_ARG_TYPES (arg), nsubsts, 1,
+ strict, 0);
case OFFSET_TYPE:
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
if (unify (tparms, targs, ntparms, TYPE_OFFSET_BASETYPE (parm),
- TYPE_OFFSET_BASETYPE (arg), nsubsts))
+ TYPE_OFFSET_BASETYPE (arg), nsubsts, strict))
return 1;
return unify (tparms, targs, ntparms, TREE_TYPE (parm),
- TREE_TYPE (arg), nsubsts);
+ TREE_TYPE (arg), nsubsts, strict);
+
+ case CONST_DECL:
+ if (arg != decl_constant_value (parm))
+ return 1;
+ return 0;
default:
sorry ("use of `%s' in template type unification",
@@ -2354,219 +3948,330 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
return 1;
}
}
-
-#undef DEBUG
+void
+mark_decl_instantiated (result, extern_p)
+ tree result;
+ int extern_p;
+{
+ if (DECL_TEMPLATE_INSTANTIATION (result))
+ SET_DECL_EXPLICIT_INSTANTIATION (result);
+ TREE_PUBLIC (result) = 1;
+
+ if (! extern_p)
+ {
+ DECL_INTERFACE_KNOWN (result) = 1;
+ DECL_NOT_REALLY_EXTERN (result) = 1;
+ }
+ else if (TREE_CODE (result) == FUNCTION_DECL)
+ mark_inline_for_output (result);
+}
+/* Given two function templates PAT1 and PAT2, return:
+
+ 1 if PAT1 is more specialized than PAT2 as described in [temp.func.order].
+ -1 if PAT2 is more specialized than PAT1.
+ 0 if neither is more specialized. */
+
int
-do_pending_expansions ()
+more_specialized (pat1, pat2)
+ tree pat1, pat2;
{
- struct pending_inline *i, *new_list = 0;
-
- {
- tree t;
- for (t = template_classes; t; t = TREE_CHAIN (t))
- instantiate_member_templates (TREE_PURPOSE (t));
- }
-
- if (!pending_template_expansions)
- return 0;
+ tree targs;
+ int winner = 0;
-#ifdef DEBUG
- fprintf (stderr, "\n\n\t\t IN DO_PENDING_EXPANSIONS\n\n");
-#endif
+ targs = get_bindings (pat1, pat2);
+ if (targs)
+ {
+ --winner;
+ }
- i = pending_template_expansions;
- while (i)
+ targs = get_bindings (pat2, pat1);
+ if (targs)
{
- tree context;
+ ++winner;
+ }
- struct pending_inline *next = i->next;
- tree t = i->fndecl;
+ return winner;
+}
- int decision = 0;
-#define DECIDE(N) do {decision=(N); goto decided;} while(0)
+/* Given two class template specialization list nodes PAT1 and PAT2, return:
- my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == VAR_DECL, 294);
- if (TREE_ASM_WRITTEN (t))
- DECIDE (0);
+ 1 if PAT1 is more specialized than PAT2 as described in [temp.class.order].
+ -1 if PAT2 is more specialized than PAT1.
+ 0 if neither is more specialized. */
+
+int
+more_specialized_class (pat1, pat2)
+ tree pat1, pat2;
+{
+ tree targs;
+ int winner = 0;
- if (DECL_EXPLICIT_INSTANTIATION (t))
- DECIDE (DECL_NOT_REALLY_EXTERN (t));
- else if (! flag_implicit_templates)
- DECIDE (0);
+ targs = get_class_bindings
+ (TREE_VALUE (pat1), TREE_PURPOSE (pat1), TREE_PURPOSE (pat2));
+ if (targs)
+ --winner;
- if (i->interface == 1)
- /* OK, it was an implicit instantiation. */
- {
- if (SUPPORTS_WEAK)
- DECL_WEAK (t) = 1;
- else
- TREE_PUBLIC (t) = 0;
- }
+ targs = get_class_bindings
+ (TREE_VALUE (pat2), TREE_PURPOSE (pat2), TREE_PURPOSE (pat1));
+ if (targs)
+ ++winner;
+
+ return winner;
+}
+
+/* Return the template arguments that will produce the function signature
+ DECL from the function template FN. */
+
+tree
+get_bindings (fn, decl)
+ tree fn, decl;
+{
+ int ntparms = DECL_NTPARMS (fn);
+ tree targs = make_scratch_vec (ntparms);
+ int i;
+
+ i = fn_type_unification (fn, NULL_TREE, targs,
+ TYPE_ARG_TYPES (TREE_TYPE (decl)),
+ TREE_TYPE (TREE_TYPE (decl)),
+ 1);
- /* If it's a method, let the class type decide it.
- @@ What if the method template is in a separate file?
- Maybe both file contexts should be taken into account?
- Maybe only do this if i->interface == 1 (unknown)? */
- context = DECL_CONTEXT (t);
- if (context != NULL_TREE
- && TREE_CODE_CLASS (TREE_CODE (context)) == 't')
+ if (i == 0)
+ return targs;
+ return 0;
+}
+
+static tree
+get_class_bindings (tparms, parms, args)
+ tree tparms, parms, args;
+{
+ int i, dummy, ntparms = TREE_VEC_LENGTH (tparms);
+ tree vec = make_temp_vec (ntparms);
+
+ for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
+ {
+ switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms,
+ TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
+ &dummy, 1))
{
- /* I'm interested in the context of this version of the function,
- not the original virtual declaration. */
- context = DECL_CLASS_CONTEXT (t);
-
- /* If `unknown', we might want a static copy.
- If `implementation', we want a global one.
- If `interface', ext ref. */
- if (CLASSTYPE_INTERFACE_KNOWN (context))
- DECIDE (!CLASSTYPE_INTERFACE_ONLY (context));
-#if 1 /* This doesn't get us stuff needed only by the file initializer. */
- DECIDE (TREE_USED (t));
-#else /* This compiles too much stuff, but that's probably better in
- most cases than never compiling the stuff we need. */
- DECIDE (1);
-#endif
+ case 0:
+ break;
+ case 1:
+ return NULL_TREE;
}
+ }
- if (i->interface == 1)
- DECIDE (TREE_USED (t));
- else
- DECIDE (i->interface);
-
- decided:
-#ifdef DEBUG
- print_node_brief (stderr, decision ? "yes: " : "no: ", t, 0);
- fprintf (stderr, "\t%s\n",
- (DECL_ASSEMBLER_NAME (t)
- ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t))
- : ""));
-#endif
- if (decision)
+ for (i = 0; i < ntparms; ++i)
+ if (! TREE_VEC_ELT (vec, i))
+ return NULL_TREE;
+
+ return vec;
+}
+
+/* Return the most specialized of the list of templates in FNS that can
+ produce an instantiation matching DECL. */
+
+tree
+most_specialized (fns, decl)
+ tree fns, decl;
+{
+ tree fn, champ, args, *p;
+ int fate;
+
+ for (p = &fns; *p; )
+ {
+ args = get_bindings (TREE_VALUE (*p), decl);
+ if (args)
{
- i->next = pending_inlines;
- pending_inlines = i;
+ p = &TREE_CHAIN (*p);
}
else
- {
- i->next = new_list;
- new_list = i;
- }
- i = next;
+ *p = TREE_CHAIN (*p);
}
- pending_template_expansions = new_list;
- if (!pending_inlines)
- return 0;
- do_pending_inlines ();
- return 1;
-}
-
-
-struct pending_template {
- struct pending_template *next;
- tree id;
-};
-static struct pending_template* pending_templates;
+ if (! fns)
+ return NULL_TREE;
-void
-do_pending_templates ()
-{
- struct pending_template* t;
-
- for ( t = pending_templates; t; t = t->next)
+ fn = fns;
+ champ = TREE_VALUE (fn);
+ fn = TREE_CHAIN (fn);
+ for (; fn; fn = TREE_CHAIN (fn))
{
- instantiate_class_template (t->id, 1);
+ fate = more_specialized (champ, TREE_VALUE (fn));
+ if (fate == 1)
+ ;
+ else
+ {
+ if (fate == 0)
+ {
+ fn = TREE_CHAIN (fn);
+ if (! fn)
+ return error_mark_node;
+ }
+ champ = TREE_VALUE (fn);
+ }
}
- for ( t = pending_templates; t; t = pending_templates)
+ for (fn = fns; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn))
{
- pending_templates = t->next;
- free(t);
+ fate = more_specialized (champ, TREE_VALUE (fn));
+ if (fate != 1)
+ return error_mark_node;
}
-}
-static void
-add_pending_template (pt)
- tree pt;
-{
- struct pending_template *p;
-
- p = (struct pending_template *) malloc (sizeof (struct pending_template));
- p->next = pending_templates;
- pending_templates = p;
- p->id = pt;
+ return champ;
}
-void
-mark_function_instantiated (result, extern_p)
- tree result;
- int extern_p;
+/* Return the most specialized of the class template specializations in
+ SPECS that can produce an instantiation matching ARGS. */
+
+tree
+most_specialized_class (specs, mainargs)
+ tree specs, mainargs;
{
- if (DECL_TEMPLATE_INSTANTIATION (result))
- SET_DECL_EXPLICIT_INSTANTIATION (result);
- TREE_PUBLIC (result) = 1;
+ tree list = NULL_TREE, t, args, champ;
+ int fate;
- if (! extern_p)
+ for (t = specs; t; t = TREE_CHAIN (t))
{
- DECL_INTERFACE_KNOWN (result) = 1;
- DECL_NOT_REALLY_EXTERN (result) = 1;
+ args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), mainargs);
+ if (args)
+ {
+ list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
+ TREE_TYPE (list) = TREE_TYPE (t);
+ }
+ }
+
+ if (! list)
+ return NULL_TREE;
+
+ t = list;
+ champ = t;
+ t = TREE_CHAIN (t);
+ for (; t; t = TREE_CHAIN (t))
+ {
+ fate = more_specialized_class (champ, t);
+ if (fate == 1)
+ ;
+ else
+ {
+ if (fate == 0)
+ {
+ t = TREE_CHAIN (t);
+ if (! t)
+ return error_mark_node;
+ }
+ champ = t;
+ }
}
+
+ for (t = list; t && t != champ; t = TREE_CHAIN (t))
+ {
+ fate = more_specialized_class (champ, t);
+ if (fate != 1)
+ return error_mark_node;
+ }
+
+ return champ;
}
/* called from the parser. */
+
void
-do_function_instantiation (declspecs, declarator, storage)
+do_decl_instantiation (declspecs, declarator, storage)
tree declspecs, declarator, storage;
{
- tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0,
- NULL_TREE, NULL_TREE);
+ tree decl = grokdeclarator (declarator, declspecs, NORMAL, 0, NULL_TREE);
tree name;
tree fn;
tree result = NULL_TREE;
int extern_p = 0;
+ tree templates = NULL_TREE;
+
+ if (! DECL_LANG_SPECIFIC (decl))
+ {
+ cp_error ("explicit instantiation of non-template `%#D'", decl);
+ return;
+ }
/* If we've already seen this template instance, use it. */
- if (name = DECL_ASSEMBLER_NAME (decl),
- fn = IDENTIFIER_GLOBAL_VALUE (name),
- fn && DECL_TEMPLATE_INSTANTIATION (fn))
- result = fn;
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ result = lookup_field (DECL_CONTEXT (decl), DECL_NAME (decl), 0, 0);
+ if (result && TREE_CODE (result) != VAR_DECL)
+ result = NULL_TREE;
+ }
+ else if (TREE_CODE (decl) != FUNCTION_DECL)
+ {
+ cp_error ("explicit instantiation of `%#D'", decl);
+ return;
+ }
+ else if (DECL_FUNCTION_MEMBER_P (decl))
+ {
+ if (DECL_TEMPLATE_INSTANTIATION (decl))
+ result = decl;
+ else if (name = DECL_ASSEMBLER_NAME (decl),
+ fn = IDENTIFIER_GLOBAL_VALUE (name),
+ fn && DECL_TEMPLATE_INSTANTIATION (fn))
+ result = fn;
+ else
+ {
+ /* Maybe this is an instantiation of a member template
+ function. */
+ tree ctype = DECL_CONTEXT (decl);
+
+ name = DECL_NAME (decl);
+ fn = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
+ if (fn)
+ fn = TREE_VALUE (fn);
+
+ for (; fn; fn = DECL_CHAIN (fn))
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ templates = decl_tree_cons (NULL_TREE, fn, templates);
+ }
+ }
else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
{
for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
- if (decls_match (fn, decl)
- && DECL_DEFER_OUTPUT (fn))
- {
- result = fn;
- break;
- }
- else if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
- tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
- int i, dummy = 0;
- i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
- TYPE_ARG_TYPES (TREE_TYPE (fn)),
- TYPE_ARG_TYPES (TREE_TYPE (decl)),
- &dummy, 0);
- if (i == 0)
- {
- if (result)
- cp_error ("ambiguous template instantiation for `%D' requested", decl);
- else
- result = instantiate_template (fn, targs);
- }
- free (targs);
- }
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ templates = decl_tree_cons (NULL_TREE, fn, templates);
}
+
+ if (templates && !result)
+ {
+ tree args;
+ result = most_specialized (templates, decl);
+ if (result == error_mark_node)
+ {
+ char *str = "candidates are:";
+ cp_error ("ambiguous template instantiation for `%D' requested", decl);
+ for (fn = templates; fn; fn = TREE_CHAIN (fn))
+ {
+ cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
+ str = " ";
+ }
+ return;
+ }
+ else if (result)
+ {
+ args = get_bindings (result, decl);
+ result = instantiate_template (result, args);
+ }
+ }
+
if (! result)
{
cp_error ("no matching template for `%D' found", decl);
return;
}
+ if (! DECL_TEMPLATE_INFO (result))
+ {
+ cp_pedwarn ("explicit instantiation of non-template `%#D'", result);
+ return;
+ }
+
if (flag_external_templates)
return;
@@ -2577,8 +4282,11 @@ do_function_instantiation (declspecs, declarator, storage)
else
cp_error ("storage class `%D' applied to template instantiation",
storage);
- mark_function_instantiated (result, extern_p);
+
+ mark_decl_instantiated (result, extern_p);
repo_template_instantiated (result, extern_p);
+ if (! extern_p)
+ instantiate_decl (result);
}
void
@@ -2599,12 +4307,23 @@ mark_class_instantiated (t, extern_p)
}
void
-do_type_instantiation (name, storage)
- tree name, storage;
+do_type_instantiation (t, storage)
+ tree t, storage;
{
- tree t = TREE_TYPE (name);
int extern_p = 0;
int nomem_p = 0;
+ int static_p = 0;
+
+ if (TREE_CODE (t) == TYPE_DECL)
+ t = TREE_TYPE (t);
+
+ if (! IS_AGGR_TYPE (t) || ! CLASSTYPE_TEMPLATE_INFO (t))
+ {
+ cp_error ("explicit instantiation of non-template type `%T'", t);
+ return;
+ }
+
+ complete_type (t);
/* With -fexternal-templates, explicit instantiations are treated the same
as implicit ones. */
@@ -2624,6 +4343,8 @@ do_type_instantiation (name, storage)
nomem_p = 1;
else if (storage == ridpointers[(int) RID_EXTERN])
extern_p = 1;
+ else if (storage == ridpointers[(int) RID_STATIC])
+ static_p = 1;
else
{
cp_error ("storage class `%D' applied to template instantiation",
@@ -2647,31 +4368,26 @@ do_type_instantiation (name, storage)
{
tree tmp;
- /* Classes nested in template classes currently don't have an
- IDENTIFIER_TEMPLATE--their out-of-line members are handled
- by the enclosing template class. Note that there are name
- conflict bugs with this approach. */
- tmp = TYPE_IDENTIFIER (t);
- if (IDENTIFIER_TEMPLATE (tmp))
- instantiate_member_templates (tmp);
-
- /* this should really be done by instantiate_member_templates */
- tmp = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 0);
- for (; tmp; tmp = TREE_CHAIN (tmp))
- if (DECL_TEMPLATE_INSTANTIATION (tmp))
+
+ if (! static_p)
+ for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
+ if (DECL_TEMPLATE_INSTANTIATION (tmp))
+ {
+ mark_decl_instantiated (tmp, extern_p);
+ repo_template_instantiated (tmp, extern_p);
+ if (! extern_p)
+ instantiate_decl (tmp);
+ }
+
+ for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
+ if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
{
- mark_function_instantiated (tmp, extern_p);
+ mark_decl_instantiated (tmp, extern_p);
repo_template_instantiated (tmp, extern_p);
+ if (! extern_p)
+ instantiate_decl (tmp);
}
-#if 0
- for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (TREE_CODE (tmp) == VAR_DECL)
- /* eventually do something */;
- }
-#endif
-
for (tmp = CLASSTYPE_TAGS (t); tmp; tmp = TREE_CHAIN (tmp))
if (IS_AGGR_TYPE (TREE_VALUE (tmp)))
do_type_instantiation (TYPE_MAIN_DECL (TREE_VALUE (tmp)), storage);
@@ -2679,16 +4395,314 @@ do_type_instantiation (name, storage)
}
tree
-create_nested_upt (scope, name)
- tree scope, name;
+instantiate_decl (d)
+ tree d;
{
- tree t = make_lang_type (UNINSTANTIATED_P_TYPE);
- tree d = build_decl (TYPE_DECL, name, t);
+ tree ti = DECL_TEMPLATE_INFO (d);
+ tree tmpl = TI_TEMPLATE (ti);
+ tree args = TI_ARGS (ti);
+ tree td;
+ tree decl_pattern, code_pattern;
+ tree save_ti;
+ int nested = in_function_p ();
+ int d_defined;
+ int pattern_defined;
+ int line = lineno;
+ char *file = input_filename;
+
+ for (td = tmpl; DECL_TEMPLATE_INSTANTIATION (td); )
+ td = DECL_TI_TEMPLATE (td);
+
+ /* In the case of a member template, decl_pattern is the partially
+ instantiated declaration (in the instantiated class), and code_pattern
+ is the original template definition. */
+ decl_pattern = DECL_TEMPLATE_RESULT (tmpl);
+ code_pattern = DECL_TEMPLATE_RESULT (td);
+
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ {
+ d_defined = (DECL_INITIAL (d) != NULL_TREE);
+ pattern_defined = (DECL_INITIAL (code_pattern) != NULL_TREE);
+ }
+ else
+ {
+ d_defined = ! DECL_IN_AGGR_P (d);
+ pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
+ }
+
+ if (d_defined)
+ return d;
+
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ {
+ tree specs;
+
+ /* Check to see if there is a matching specialization. */
+ for (specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+ specs != NULL_TREE;
+ specs = TREE_CHAIN (specs))
+ if (comp_template_args (TREE_PURPOSE (specs), args))
+ return TREE_VALUE (specs);
+ }
- TYPE_NAME (t) = d;
- TYPE_VALUES (t) = TYPE_VALUES (scope);
- TYPE_CONTEXT (t) = scope;
+ /* This needs to happen before any tsubsting. */
+ if (! push_tinst_level (d))
+ return d;
+
+ push_to_top_level ();
+ lineno = DECL_SOURCE_LINE (d);
+ input_filename = DECL_SOURCE_FILE (d);
+
+ /* We need to set up DECL_INITIAL regardless of pattern_defined if the
+ variable is a static const initialized in the class body. */
+ if (TREE_CODE (d) == VAR_DECL
+ && ! DECL_INITIAL (d) && DECL_INITIAL (code_pattern))
+ {
+ pushclass (DECL_CONTEXT (d), 2);
+ DECL_INITIAL (d) = tsubst_expr (DECL_INITIAL (code_pattern), args,
+ TREE_VEC_LENGTH (args), tmpl);
+ popclass (1);
+ }
+
+ /* import_export_decl has to happen after DECL_INITIAL is set up. */
+ if (pattern_defined)
+ {
+ repo_template_used (d);
+
+ if (flag_external_templates && ! DECL_INTERFACE_KNOWN (d))
+ {
+ if (flag_alt_external_templates)
+ {
+ if (interface_unknown)
+ warn_if_unknown_interface (d);
+ }
+ else if (DECL_INTERFACE_KNOWN (code_pattern))
+ {
+ DECL_INTERFACE_KNOWN (d) = 1;
+ DECL_NOT_REALLY_EXTERN (d) = ! DECL_EXTERNAL (code_pattern);
+ }
+ else
+ warn_if_unknown_interface (code_pattern);
+ }
+
+ if (at_eof)
+ import_export_decl (d);
+ }
+
+ if (! pattern_defined
+ || (TREE_CODE (d) == FUNCTION_DECL && ! DECL_INLINE (d)
+ && (! DECL_INTERFACE_KNOWN (d)
+ || ! DECL_NOT_REALLY_EXTERN (d)))
+ /* Kludge: if we compile a constructor in the middle of processing a
+ toplevel declaration, we blow away the declspecs in
+ temp_decl_obstack when we call permanent_allocation in
+ finish_function. So don't compile it yet. */
+ || (TREE_CODE (d) == FUNCTION_DECL && ! nested && ! at_eof))
+ {
+ add_pending_template (d);
+ goto out;
+ }
+
+ lineno = DECL_SOURCE_LINE (d);
+ input_filename = DECL_SOURCE_FILE (d);
+
+ /* Trick tsubst into giving us a new decl in case the template changed. */
+ save_ti = DECL_TEMPLATE_INFO (decl_pattern);
+ DECL_TEMPLATE_INFO (decl_pattern) = NULL_TREE;
+ td = tsubst (decl_pattern, args, TREE_VEC_LENGTH (args), tmpl);
+ SET_DECL_IMPLICIT_INSTANTIATION (td);
+ DECL_TEMPLATE_INFO (decl_pattern) = save_ti;
+
+ /* And set up DECL_INITIAL, since tsubst doesn't. */
+ if (TREE_CODE (td) == VAR_DECL)
+ {
+ pushclass (DECL_CONTEXT (d), 2);
+ DECL_INITIAL (td) = tsubst_expr (DECL_INITIAL (code_pattern), args,
+ TREE_VEC_LENGTH (args), tmpl);
+ popclass (1);
+ }
+
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ {
+ /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
+ new decl. */
+ DECL_INITIAL (td) = error_mark_node;
+
+ if (DECL_TEMPLATE_SPECIALIZATION (td) && !DECL_TEMPLATE_INFO (td))
+ /* Set up the information about what is being specialized. */
+ DECL_TEMPLATE_INFO (td) = DECL_TEMPLATE_INFO (d);
+ }
+ duplicate_decls (td, d);
+ if (TREE_CODE (d) == FUNCTION_DECL)
+ DECL_INITIAL (td) = 0;
+
+ if (TREE_CODE (d) == VAR_DECL)
+ {
+ DECL_IN_AGGR_P (d) = 0;
+ if (DECL_INTERFACE_KNOWN (d))
+ DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
+ else
+ {
+ DECL_EXTERNAL (d) = 1;
+ DECL_NOT_REALLY_EXTERN (d) = 1;
+ }
+ cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0, 0);
+ }
+ else if (TREE_CODE (d) == FUNCTION_DECL)
+ {
+ tree t = DECL_SAVED_TREE (code_pattern);
+
+ start_function (NULL_TREE, d, NULL_TREE, 1);
+ store_parm_decls ();
+
+ if (t && TREE_CODE (t) == RETURN_INIT)
+ {
+ store_return_init
+ (TREE_OPERAND (t, 0),
+ tsubst_expr (TREE_OPERAND (t, 1), args,
+ TREE_VEC_LENGTH (args), tmpl));
+ t = TREE_CHAIN (t);
+ }
+
+ if (t && TREE_CODE (t) == CTOR_INITIALIZER)
+ {
+ current_member_init_list
+ = tsubst_expr_values (TREE_OPERAND (t, 0), args);
+ current_base_init_list
+ = tsubst_expr_values (TREE_OPERAND (t, 1), args);
+ t = TREE_CHAIN (t);
+ }
+
+ setup_vtbl_ptr ();
+ /* Always keep the BLOCK node associated with the outermost
+ pair of curly braces of a function. These are needed
+ for correct operation of dwarfout.c. */
+ keep_next_level ();
+
+ my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
+ tsubst_expr (t, args, TREE_VEC_LENGTH (args), tmpl);
+
+ finish_function (lineno, 0, nested);
+ }
+
+out:
+ lineno = line;
+ input_filename = file;
+
+ pop_from_top_level ();
+ pop_tinst_level ();
- pushdecl (d);
return d;
}
+
+tree
+tsubst_chain (t, argvec)
+ tree t, argvec;
+{
+ if (t)
+ {
+ tree first = tsubst (t, argvec,
+ TREE_VEC_LENGTH (argvec), NULL_TREE);
+ tree last = first;
+
+ for (t = TREE_CHAIN (t); t; t = TREE_CHAIN (t))
+ {
+ tree x = tsubst (t, argvec, TREE_VEC_LENGTH (argvec), NULL_TREE);
+ TREE_CHAIN (last) = x;
+ last = x;
+ }
+
+ return first;
+ }
+ return NULL_TREE;
+}
+
+static tree
+tsubst_expr_values (t, argvec)
+ tree t, argvec;
+{
+ tree first = NULL_TREE;
+ tree *p = &first;
+
+ for (; t; t = TREE_CHAIN (t))
+ {
+ tree pur = tsubst_copy (TREE_PURPOSE (t), argvec,
+ TREE_VEC_LENGTH (argvec), NULL_TREE);
+ tree val = tsubst_expr (TREE_VALUE (t), argvec,
+ TREE_VEC_LENGTH (argvec), NULL_TREE);
+ *p = build_tree_list (pur, val);
+ p = &TREE_CHAIN (*p);
+ }
+ return first;
+}
+
+tree last_tree;
+
+void
+add_tree (t)
+ tree t;
+{
+ last_tree = TREE_CHAIN (last_tree) = t;
+}
+
+/* D is an undefined function declaration in the presence of templates with
+ the same name, listed in FNS. If one of them can produce D as an
+ instantiation, remember this so we can instantiate it at EOF if D has
+ not been defined by that time. */
+
+void
+add_maybe_template (d, fns)
+ tree d, fns;
+{
+ tree t;
+
+ if (DECL_MAYBE_TEMPLATE (d))
+ return;
+
+ t = most_specialized (fns, d);
+ if (! t)
+ return;
+ if (t == error_mark_node)
+ {
+ cp_error ("ambiguous template instantiation for `%D'", d);
+ return;
+ }
+
+ *maybe_template_tail = perm_tree_cons (t, d, NULL_TREE);
+ maybe_template_tail = &TREE_CHAIN (*maybe_template_tail);
+ DECL_MAYBE_TEMPLATE (d) = 1;
+}
+
+/* Instantiate an enumerated type. Used by instantiate_class_template and
+ tsubst_expr. */
+
+static tree
+tsubst_enum (tag, args, nargs, field_chain)
+ tree tag, args;
+ int nargs;
+ tree * field_chain;
+{
+ extern tree current_local_enum;
+ tree prev_local_enum = current_local_enum;
+
+ tree newtag = start_enum (TYPE_IDENTIFIER (tag));
+ tree e, values = NULL_TREE;
+
+ for (e = TYPE_VALUES (tag); e; e = TREE_CHAIN (e))
+ {
+ tree elt = build_enumerator (TREE_PURPOSE (e),
+ tsubst_expr (TREE_VALUE (e), args,
+ nargs, NULL_TREE));
+ TREE_CHAIN (elt) = values;
+ values = elt;
+ }
+
+ finish_enum (newtag, values);
+
+ if (NULL != field_chain)
+ *field_chain = grok_enum_decls (newtag, NULL_TREE);
+
+ current_local_enum = prev_local_enum;
+
+ return newtag;
+}
diff --git a/gnu/usr.bin/gcc/cp/ptree.c b/gnu/usr.bin/gcc/cp/ptree.c
index ad1480a1ed9..5a859561512 100644
--- a/gnu/usr.bin/gcc/cp/ptree.c
+++ b/gnu/usr.bin/gcc/cp/ptree.c
@@ -72,13 +72,6 @@ print_lang_type (file, node, indent)
return;
}
- if (TREE_CODE (node) == UNINSTANTIATED_P_TYPE)
- {
- print_node (file, "template", UPT_TEMPLATE (node), indent + 4);
- print_node (file, "parameters", UPT_PARMS (node), indent + 4);
- return;
- }
-
if (! (TREE_CODE (node) == RECORD_TYPE
|| TREE_CODE (node) == UNION_TYPE))
return;
diff --git a/gnu/usr.bin/gcc/cp/repo.c b/gnu/usr.bin/gcc/cp/repo.c
index 50fc9f8b727..c1d756c91c2 100644
--- a/gnu/usr.bin/gcc/cp/repo.c
+++ b/gnu/usr.bin/gcc/cp/repo.c
@@ -1,5 +1,5 @@
/* Code to maintain a C++ template repository.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997 Free Software Foundation, Inc.
Contributed by Jason Merrill (jason@cygnus.com)
This file is part of GNU CC.
@@ -25,22 +25,42 @@ Boston, MA 02111-1307, USA. */
The results of the automatic process should be easily reproducible with
explicit code. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "cp-tree.h"
#include "input.h"
#include "obstack.h"
-extern char * rindex ();
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#else
extern char * getenv ();
-extern char * getpwd ();
+#endif
+
+#ifdef NEED_DECLARATION_RINDEX
+extern char *rindex ();
+#endif rindex
+extern char *getpwd PROTO((void));
+
+static tree repo_get_id PROTO((tree));
+static char *save_string PROTO((char *, int));
+static char *extract_string PROTO((char **));
+static char *get_base_filename PROTO((char *));
+static void open_repo_file PROTO((char *));
+static char *afgets PROTO((FILE *));
+static void reopen_repo_file_for_write PROTO((void));
static tree pending_repo;
static tree original_repo;
static char *repo_name;
static FILE *repo_file;
+static char *old_args, *old_dir, *old_main;
+
extern int flag_use_repository;
extern int errorcount, sorrycount;
extern struct obstack temporary_obstack;
@@ -49,6 +69,7 @@ extern struct obstack permanent_obstack;
#define IDENTIFIER_REPO_USED(NODE) (TREE_LANG_FLAG_3 (NODE))
#define IDENTIFIER_REPO_CHOSEN(NODE) (TREE_LANG_FLAG_4 (NODE))
+#if 0
/* Record the flags used to compile this translation unit. */
void
@@ -82,8 +103,9 @@ void
repo_class_defined (t)
tree t;
{}
+#endif
-tree
+static tree
repo_get_id (t)
tree t;
{
@@ -97,7 +119,7 @@ repo_get_id (t)
}
/* Note that a template has been used. If we can see the definition, offer
- to emit it. */
+ to emit it. */
void
repo_template_used (t)
@@ -120,7 +142,7 @@ repo_template_used (t)
else if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
{
if (IDENTIFIER_REPO_CHOSEN (id))
- mark_function_instantiated (t, 0);
+ mark_decl_instantiated (t, 0);
}
else
my_friendly_abort (1);
@@ -132,9 +154,10 @@ repo_template_used (t)
}
}
+#if 0
/* Note that the vtable for a class has been used, and offer to emit it. */
-void
+static void
repo_vtable_used (t)
tree t;
{
@@ -172,6 +195,7 @@ repo_tinfo_used (ti)
tree ti;
{
}
+#endif
void
repo_template_instantiated (t, extern_p)
@@ -194,35 +218,55 @@ save_string (s, len)
return obstack_copy0 (&temporary_obstack, s, len);
}
+/* 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);
+}
+
static char *
get_base_filename (filename)
char *filename;
{
char *p = getenv ("COLLECT_GCC_OPTIONS");
- char *output = 0;
+ char *output = NULL;
int compiling = 0;
- if (p)
- while (*p)
- {
- char *q = p;
- while (*q && *q != ' ') q++;
- if (*p == '-' && p[1] == 'o')
- {
- p += 2;
- if (p == q)
- {
- p++; q++;
- if (*q)
- while (*q && *q != ' ') q++;
- }
+ while (p && *p)
+ {
+ char *q = extract_string (&p);
- output = save_string (p, q - p);
- }
- else if (*p == '-' && p[1] == 'c')
- compiling = 1;
- if (*q) q++;
- p = q;
+ if (strcmp (q, "-o") == 0)
+ output = extract_string (&p);
+ else if (strcmp (q, "-c") == 0)
+ compiling = 1;
}
if (compiling && output)
@@ -246,7 +290,7 @@ static void
open_repo_file (filename)
char *filename;
{
- register char *p, *q;
+ register char *p;
char *s = get_base_filename (filename);
if (s == NULL)
@@ -297,8 +341,16 @@ init_repo (filename)
switch (buf[0])
{
case 'A':
+ old_args = obstack_copy0 (&permanent_obstack, buf + 2,
+ strlen (buf + 2));
+ break;
case 'D':
+ old_dir = obstack_copy0 (&permanent_obstack, buf + 2,
+ strlen (buf + 2));
+ break;
case 'M':
+ old_main = obstack_copy0 (&permanent_obstack, buf + 2,
+ strlen (buf + 2));
break;
case 'C':
case 'O':
@@ -346,6 +398,7 @@ finish_repo ()
tree t;
char *p;
int repo_changed = 0;
+ char *dir, *args;
if (! flag_use_repository)
return;
@@ -378,6 +431,16 @@ finish_repo ()
}
}
+ dir = getpwd ();
+ args = getenv ("COLLECT_GCC_OPTIONS");
+
+ if (! repo_changed && pending_repo)
+ if (strcmp (old_main, main_input_filename) != 0
+ || strcmp (old_dir, dir) != 0
+ || (args == NULL) != (old_args == NULL)
+ || (args && strcmp (old_args, args) != 0))
+ repo_changed = 1;
+
if (! repo_changed || errorcount || sorrycount)
goto out;
@@ -387,13 +450,9 @@ finish_repo ()
goto out;
fprintf (repo_file, "M %s\n", main_input_filename);
-
- p = getpwd ();
- fprintf (repo_file, "D %s\n", p);
-
- p = getenv ("COLLECT_GCC_OPTIONS");
- if (p != 0)
- fprintf (repo_file, "A %s\n", p);
+ fprintf (repo_file, "D %s\n", dir);
+ if (args)
+ fprintf (repo_file, "A %s\n", args);
for (t = pending_repo; t; t = TREE_CHAIN (t))
{
diff --git a/gnu/usr.bin/gcc/cp/search.c b/gnu/usr.bin/gcc/cp/search.c
index 0ac50a1369d..4624ca99518 100644
--- a/gnu/usr.bin/gcc/cp/search.c
+++ b/gnu/usr.bin/gcc/cp/search.c
@@ -1,6 +1,6 @@
/* Breadth-first and depth-first routines for
searching multiple-inheritance lattice for GNU C++.
- Copyright (C) 1987, 89, 92, 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.
@@ -20,7 +20,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. */
-/* High-level class interface. */
+/* High-level class interface. */
#include "config.h"
#include "tree.h"
@@ -34,16 +34,17 @@ Boston, MA 02111-1307, USA. */
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-void init_search ();
extern struct obstack *current_obstack;
extern tree abort_fndecl;
#include "stack.h"
/* Obstack used for remembering decision points of breadth-first. */
+
static struct obstack search_obstack;
/* Methods for pushing and popping objects to and from obstacks. */
+
struct stack_level *
push_stack_level (obstack, tp, size)
struct obstack *obstack;
@@ -74,19 +75,76 @@ pop_stack_level (stack)
#define search_level stack_level
static struct search_level *search_stack;
-static tree lookup_field_1 ();
-static int lookup_fnfields_1 ();
-static void dfs_walk ();
-static int markedp ();
-static void dfs_unmark ();
-static void dfs_init_vbase_pointers ();
+static void clear_memoized_cache PROTO((void));
+static tree make_memoized_table_entry PROTO((tree, tree, int));
+static tree get_abstract_virtuals_1 PROTO((tree, int, tree));
+static tree get_vbase_1 PROTO((tree, tree, unsigned int *));
+static tree convert_pointer_to_vbase PROTO((tree, tree));
+static tree lookup_field_1 PROTO((tree, tree));
+static tree convert_pointer_to_single_level PROTO((tree, tree));
+static int lookup_fnfields_1 PROTO((tree, tree));
+static int lookup_fnfields_here PROTO((tree, tree));
+static int is_subobject_of_p PROTO((tree, tree));
+static int hides PROTO((tree, tree));
+static tree virtual_context PROTO((tree, tree, tree));
+static tree get_template_base_recursive
+ PROTO((tree, tree, tree, int));
+static void dfs_walk PROTO((tree, void (*) (tree), int (*) (tree)));
+static void envelope_add_decl PROTO((tree, tree, tree *));
+static int get_base_distance_recursive
+ PROTO((tree, int, int, int, int *, tree *, tree, tree *,
+ int, int *, int, int));
+static void expand_upcast_fixups
+ PROTO((tree, tree, tree, tree, tree, tree, tree *));
+static void fixup_virtual_upcast_offsets
+ PROTO((tree, tree, int, int, tree, tree, tree, tree,
+ tree *));
+static int markedp PROTO((tree));
+static int unmarkedp PROTO((tree));
+static int numberedp PROTO((tree));
+static int unnumberedp PROTO((tree));
+static int marked_vtable_pathp PROTO((tree));
+static int unmarked_vtable_pathp PROTO((tree));
+static int marked_new_vtablep PROTO((tree));
+static int unmarked_new_vtablep PROTO((tree));
+static int dfs_debug_unmarkedp PROTO((tree));
+static void dfs_number PROTO((tree));
+static void dfs_unnumber PROTO((tree));
+static void dfs_debug_mark PROTO((tree));
+static void dfs_find_vbases PROTO((tree));
+static void dfs_clear_vbase_slots PROTO((tree));
+static void dfs_unmark PROTO((tree));
+static void dfs_init_vbase_pointers PROTO((tree));
+static void dfs_get_vbase_types PROTO((tree));
+static void dfs_record_inheritance PROTO((tree));
+static void dfs_pushdecls PROTO((tree));
+static void dfs_compress_decls PROTO((tree));
+static void dfs_unuse_fields PROTO((tree));
+static void add_conversions PROTO((tree));
+static tree get_virtuals_named_this PROTO((tree));
+static tree get_virtual_destructor PROTO((tree, int));
+static int tree_has_any_destructor_p PROTO((tree, int));
+static struct search_level *push_search_level
+ PROTO((struct stack_level *, struct obstack *));
+static struct search_level *pop_search_level
+ PROTO((struct stack_level *));
+static struct type_level *push_type_level
+ PROTO((struct stack_level *, struct obstack *));
+static struct type_level *pop_type_level
+ PROTO((struct type_level *));
+static tree my_tree_cons PROTO((tree, tree, tree));
+static tree my_build_string PROTO((char *));
+static struct memoized_entry * my_new_memoized_entry
+ PROTO((struct memoized_entry *));
+static HOST_WIDE_INT breadth_first_search
+ PROTO((tree, int (*) (tree, int), int (*) (tree, int)));
static tree vbase_types;
-static tree vbase_decl, vbase_decl_ptr;
-static tree vbase_decl_ptr_intermediate;
+static tree vbase_decl_ptr_intermediate, vbase_decl_ptr;
static tree vbase_init_result;
/* Allocate a level of searching. */
+
static struct search_level *
push_search_level (stack, obstack)
struct stack_level *stack;
@@ -99,6 +157,7 @@ push_search_level (stack, obstack)
}
/* Discard a level of search allocation. */
+
static struct search_level *
pop_search_level (obstack)
struct stack_level *obstack;
@@ -109,6 +168,7 @@ pop_search_level (obstack)
}
/* Search memoization. */
+
struct type_level
{
struct stack_level base;
@@ -133,7 +193,6 @@ static tree _vptr_name;
/* Make things that look like tree nodes, but allocate them
on type_obstack_entries. */
static int my_tree_node_counter;
-static tree my_tree_cons (), my_build_string ();
extern int flag_memoize_lookups, flag_save_memoized_contexts;
@@ -141,12 +200,14 @@ extern int flag_memoize_lookups, flag_save_memoized_contexts;
static int my_memoized_entry_counter;
static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];
static int memoized_fields_searched[2];
+#ifdef GATHER_STATISTICS
static int n_fields_searched;
static int n_calls_lookup_field, n_calls_lookup_field_1;
static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;
static int n_calls_get_base_type;
static int n_outer_fields_searched;
static int n_contexts_saved;
+#endif /* GATHER_STATISTICS */
/* Local variables to help save memoization contexts. */
static tree prev_type_memoized;
@@ -157,6 +218,7 @@ static struct type_level *prev_type_stack;
static tree closed_envelopes = NULL_TREE;
/* Allocate a level of type memoization context. */
+
static struct type_level *
push_type_level (stack, obstack)
struct stack_level *stack;
@@ -186,6 +248,7 @@ pop_type_level (stack)
/* Make something that looks like a TREE_LIST, but
do it on the type_obstack_entries obstack. */
+
static tree
my_tree_cons (purpose, value, chain)
tree purpose, value, chain;
@@ -217,6 +280,7 @@ my_build_string (str)
/* Memoizing machinery to make searches for multiple inheritance
reasonably efficient. */
+
#define MEMOIZE_HASHSIZE 8
typedef struct memoized_entry
{
@@ -237,26 +301,43 @@ static struct memoized_entry *
my_new_memoized_entry (chain)
struct memoized_entry *chain;
{
- struct memoized_entry *p =
- (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
- sizeof (struct memoized_entry));
+ struct memoized_entry *p
+ = (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
+ sizeof (struct memoized_entry));
bzero ((char *) p, sizeof (struct memoized_entry));
MEMOIZED_CHAIN (p) = chain;
MEMOIZED_UID (p) = ++my_memoized_entry_counter;
return p;
}
+/* Clears the deferred pop from pop_memoized_context, if any. */
+
+static void
+clear_memoized_cache ()
+{
+ if (prev_type_stack)
+ {
+ type_stack = pop_type_level (prev_type_stack);
+ prev_type_memoized = 0;
+ prev_type_stack = 0;
+ }
+}
+
/* Make an entry in the memoized table for type TYPE
that the entry for NAME is FIELD. */
-tree
+static tree
make_memoized_table_entry (type, name, function_p)
tree type, name;
int function_p;
{
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
tree entry, *prev_entry;
+ /* Since we allocate from the type_obstack, we must pop any deferred
+ levels. */
+ clear_memoized_cache ();
+
memoized_adds[function_p] += 1;
if (CLASSTYPE_MTABLE_ENTRY (type) == 0)
{
@@ -268,9 +349,9 @@ make_memoized_table_entry (type, name, function_p)
my_friendly_abort (88);
}
if (function_p)
- prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
else
- prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
entry = my_tree_cons (name, NULL_TREE, *prev_entry);
*prev_entry = entry;
@@ -309,6 +390,7 @@ make_memoized_table_entry (type, name, function_p)
be NULL_TREE if we are not in a class's scope.
USE_OLD, if nonzero tries to use previous context. */
+
void
push_memoized_context (type, use_old)
tree type;
@@ -323,7 +405,7 @@ push_memoized_context (type, use_old)
{
#ifdef GATHER_STATISTICS
n_contexts_saved++;
-#endif
+#endif /* GATHER_STATISTICS */
type_stack = prev_type_stack;
prev_type_stack = 0;
@@ -334,9 +416,7 @@ push_memoized_context (type, use_old)
return;
}
/* Otherwise, need to pop old stack here. */
- type_stack = pop_type_level (prev_type_stack);
- prev_type_memoized = 0;
- prev_type_stack = 0;
+ clear_memoized_cache ();
}
type_stack = push_type_level ((struct stack_level *)type_stack,
@@ -349,6 +429,7 @@ push_memoized_context (type, use_old)
If we wanted to, we could not use pop_search_level, since
poping that level allows the data we have collected to
be clobbered; a stack of obstacks would be needed. */
+
void
pop_memoized_context (use_old)
int use_old;
@@ -364,6 +445,9 @@ pop_memoized_context (use_old)
while (len--)
tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]);
+ /* If there was a deferred pop, we need to pop it now. */
+ clear_memoized_cache ();
+
prev_type_stack = type_stack;
prev_type_memoized = type_stack->type;
}
@@ -384,9 +468,10 @@ pop_memoized_context (use_old)
/* Get a virtual binfo that is found inside BINFO's hierarchy that is
the same type as the type given in PARENT. To be optimal, we want
the first one that is found by going through the least number of
- virtual bases. DEPTH should be NULL_PTR. */
+ virtual bases. */
+
static tree
-get_vbase (parent, binfo, depth)
+get_vbase_1 (parent, binfo, depth)
tree parent, binfo;
unsigned int *depth;
{
@@ -394,12 +479,6 @@ get_vbase (parent, binfo, depth)
int i, n_baselinks;
tree rval = NULL_TREE;
- if (depth == 0)
- {
- unsigned int d = (unsigned int)-1;
- return get_vbase (parent, binfo, &d);
- }
-
if (BINFO_TYPE (binfo) == parent && TREE_VIA_VIRTUAL (binfo))
{
*depth = 0;
@@ -420,7 +499,7 @@ get_vbase (parent, binfo, depth)
if (*depth == 0)
break;
- nrval = get_vbase (parent, base_binfo, depth);
+ nrval = get_vbase_1 (parent, base_binfo, depth);
if (nrval)
rval = nrval;
}
@@ -428,46 +507,28 @@ get_vbase (parent, binfo, depth)
return rval;
}
+tree
+get_vbase (parent, binfo)
+ tree parent;
+ tree binfo;
+{
+ unsigned int d = (unsigned int)-1;
+ return get_vbase_1 (parent, binfo, &d);
+}
+
/* Convert EXPR to a virtual base class of type TYPE. We know that
EXPR is a non-null POINTER_TYPE to RECORD_TYPE. We also know that
the type of what expr points to has a virtual base of type TYPE. */
-tree
+
+static tree
convert_pointer_to_vbase (type, expr)
tree type;
tree expr;
{
- tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))), NULL_PTR);
+ tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))));
return convert_pointer_to_real (vb, expr);
}
-/* This is the newer recursive depth first search routine. */
-#if 0 /* unused */
-/* Return non-zero if PARENT is directly derived from TYPE. By directly
- we mean it's only one step up the inheritance lattice. We check this
- by walking horizontally across the types that TYPE directly inherits
- from, to see if PARENT is among them. This is used by get_binfo and
- by compute_access. */
-static int
-immediately_derived (parent, type)
- tree parent, type;
-{
- if (TYPE_BINFO (type))
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
- 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 (parent == BINFO_TYPE (base_binfo))
- return 1;
- }
- }
- return 0;
-}
-#endif
-
/* Check whether the type given in BINFO is derived from PARENT. If
it isn't, return 0. If it is, but the derivation is MI-ambiguous
AND protect != 0, emit an error message and return error_mark_node.
@@ -519,17 +580,27 @@ get_binfo (parent, binfo, protect)
}
/* This is the newer depth first get_base_distance routine. */
+
static int
-get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
+get_base_distance_recursive (binfo, depth, is_private, rval,
rval_private_ptr, new_binfo_ptr, parent, path_ptr,
- protect, via_virtual_ptr, via_virtual)
- tree binfo, basetype_path, *new_binfo_ptr, parent, *path_ptr;
- int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr,
- via_virtual;
+ protect, via_virtual_ptr, via_virtual,
+ current_scope_in_chain)
+ tree binfo;
+ int depth, is_private, rval;
+ int *rval_private_ptr;
+ tree *new_binfo_ptr, parent, *path_ptr;
+ int protect, *via_virtual_ptr, via_virtual;
+ int current_scope_in_chain;
{
tree binfos;
int i, n_baselinks;
+ if (protect
+ && !current_scope_in_chain
+ && is_friend (BINFO_TYPE (binfo), current_scope ()))
+ current_scope_in_chain = 1;
+
if (BINFO_TYPE (binfo) == parent || binfo == parent)
{
if (rval == -1)
@@ -577,19 +648,21 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
tree base_binfo = TREE_VEC_ELT (binfos, i);
/* Find any specific instance of a virtual base, when searching with
- a binfo... */
+ a binfo... */
if (BINFO_MARKED (base_binfo) == 0 || TREE_CODE (parent) == TREE_VEC)
{
int via_private
= (protect
&& (is_private
|| (!TREE_VIA_PUBLIC (base_binfo)
+ && !(TREE_VIA_PROTECTED (base_binfo)
+ && current_scope_in_chain)
&& !is_friend (BINFO_TYPE (binfo), current_scope ()))));
int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
int was;
/* When searching for a non-virtual, we cannot mark
- virtually found binfos. */
+ virtually found binfos. */
if (! this_virtual)
SET_BINFO_MARKED (base_binfo);
@@ -597,11 +670,12 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
was = WATCH_VALUES (rval, *via_virtual_ptr);
rval = get_base_distance_recursive (base_binfo, depth, via_private,
- binfo, rval, rval_private_ptr,
+ rval, rval_private_ptr,
new_binfo_ptr, parent, path_ptr,
protect, via_virtual_ptr,
- this_virtual);
- /* watch for updates; only update if path is good. */
+ this_virtual,
+ current_scope_in_chain);
+ /* watch for updates; only update if path is good. */
if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was)
BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
if (rval == -2 && *via_virtual_ptr == 0)
@@ -647,14 +721,17 @@ get_base_distance (parent, binfo, protect, path_ptr)
int via_virtual;
int watch_access = protect;
+ /* Should we be completing types here? */
if (TREE_CODE (parent) != TREE_VEC)
- parent = TYPE_MAIN_VARIANT (parent);
+ parent = complete_type (TYPE_MAIN_VARIANT (parent));
+ else
+ complete_type (TREE_TYPE (parent));
if (TREE_CODE (binfo) == TREE_VEC)
type = BINFO_TYPE (binfo);
else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
{
- type = binfo;
+ type = complete_type (binfo);
binfo = TYPE_BINFO (type);
if (path_ptr)
@@ -675,9 +752,10 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (path_ptr)
watch_access = 1;
- rval = get_base_distance_recursive (binfo, 0, 0, NULL_TREE, -1,
+ rval = get_base_distance_recursive (binfo, 0, 0, -1,
&rval_private, &new_binfo, parent,
- path_ptr, watch_access, &via_virtual, 0);
+ path_ptr, watch_access, &via_virtual, 0,
+ 0);
dfs_walk (binfo, dfs_unmark, markedp);
@@ -688,7 +766,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
if (rval && protect && rval_private)
return -3;
- /* find real virtual base classes. */
+ /* find real virtual base classes. */
if (rval == -1 && TREE_CODE (parent) == TREE_VEC
&& parent == binfo_member (BINFO_TYPE (parent),
CLASSTYPE_VBASECLASSES (type)))
@@ -711,6 +789,7 @@ get_base_distance (parent, binfo, protect, path_ptr)
/* Do a 1-level search for NAME as a member of TYPE. The caller must
figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */
+
static tree
lookup_field_1 (type, name)
tree type, name;
@@ -719,12 +798,12 @@ lookup_field_1 (type, name)
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
-#endif
+#endif /* GATHER_STATISTICS */
while (field)
{
#ifdef GATHER_STATISTICS
n_fields_searched++;
-#endif
+#endif /* GATHER_STATISTICS */
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
@@ -754,17 +833,17 @@ lookup_field_1 (type, name)
/* There are a number of cases we need to be aware of here:
current_class_type current_function_decl
- * global NULL NULL
- * fn-local NULL SET
- * class-local SET NULL
- * class->fn SET SET
- * fn->class SET SET
+ global NULL NULL
+ fn-local NULL SET
+ class-local SET NULL
+ class->fn SET SET
+ fn->class SET SET
Those last two make life interesting. If we're in a function which is
itself inside a class, we need decls to go into the fn's decls (our
second case below). But if we're in a class and the class itself is
inside a function, we need decls to go into the decls for the class. To
- achieve this last goal, we must see if, when both current_class_decl and
+ achieve this last goal, we must see if, when both current_class_ptr and
current_function_decl are set, the class was declared inside that
function. If so, we know to put the decls into the class's scope. */
@@ -794,23 +873,23 @@ current_scope ()
This will be static when lookup_fnfield comes into this file.
- access_public means that the field can be accessed by the current lexical
+ access_public_node means that the field can be accessed by the current lexical
scope.
- access_protected means that the field cannot be accessed by the current
+ access_protected_node means that the field cannot be accessed by the current
lexical scope because it is protected.
- access_private means that the field cannot be accessed by the current
- lexical scope because it is private. */
+ access_private_node means that the field cannot be accessed by the current
+ lexical scope because it is private. */
#if 0
-#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public
-#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected
-#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private
+#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public_node
+#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected_node
+#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private_node
#else
-#define PUBLIC_RETURN return access_public
-#define PROTECTED_RETURN return access_protected
-#define PRIVATE_RETURN return access_private
+#define PUBLIC_RETURN return access_public_node
+#define PROTECTED_RETURN return access_protected_node
+#define PRIVATE_RETURN return access_private_node
#endif
#if 0
@@ -818,11 +897,11 @@ current_scope ()
static tree previous_scope = NULL_TREE;
#endif
-enum access_type
+tree
compute_access (basetype_path, field)
tree basetype_path, field;
{
- enum access_type access;
+ tree access;
tree types;
tree context;
int protected_ok, via_protected;
@@ -831,16 +910,16 @@ compute_access (basetype_path, field)
/* Replaces static decl above. */
tree previous_scope;
#endif
- int static_mem =
- ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
- || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
+ int static_mem
+ = ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
+ || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
if (! flag_access_control)
- return access_public;
+ return access_public_node;
/* The field lives in the current class. */
if (BINFO_TYPE (basetype_path) == current_class_type)
- return access_public;
+ return access_public_node;
#if 0
/* Disabled until pushing function scope clears these out. If ever. */
@@ -848,17 +927,17 @@ compute_access (basetype_path, field)
if (current_scope () == previous_scope)
{
if (DECL_PUBLIC (field))
- return access_public;
+ return access_public_node;
if (DECL_PROTECTED (field))
- return access_protected;
+ return access_protected_node;
if (DECL_PRIVATE (field))
- return access_private;
+ return access_private_node;
}
#endif
/* We don't currently support access control on nested types. */
if (TREE_CODE (field) == TYPE_DECL)
- return access_public;
+ return access_public_node;
previous_scope = current_scope ();
@@ -868,10 +947,10 @@ compute_access (basetype_path, field)
/* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
slot set to the union type rather than the record type containing
- the anonymous union. In this case, DECL_FIELD_CONTEXT is correct. */
+ the anonymous union. */
if (context && TREE_CODE (context) == UNION_TYPE
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
- context = DECL_FIELD_CONTEXT (field);
+ context = TYPE_CONTEXT (context);
/* Virtual function tables are never private. But we should know that
we are looking for this, and not even try to hide it. */
@@ -899,7 +978,7 @@ compute_access (basetype_path, field)
{
if (current_class_type
&& static_mem
- && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
+ && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
PUBLIC_RETURN;
else
PROTECTED_RETURN;
@@ -912,7 +991,7 @@ compute_access (basetype_path, field)
basetype_path = reverse_path (basetype_path);
types = basetype_path;
via_protected = 0;
- access = access_default;
+ access = access_default_node;
protected_ok = static_mem && current_class_type
&& ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type);
@@ -934,7 +1013,7 @@ compute_access (basetype_path, field)
member = purpose_member (type, DECL_ACCESS (field));
if (member)
{
- access = (enum access_type) TREE_VALUE (member);
+ access = TREE_VALUE (member);
break;
}
@@ -948,7 +1027,7 @@ compute_access (basetype_path, field)
via_protected = 1;
else if (! TREE_VIA_PUBLIC (types) && ! private_ok)
{
- access = access_private;
+ access = access_private_node;
break;
}
}
@@ -959,30 +1038,30 @@ compute_access (basetype_path, field)
/* No special visibilities apply. Use normal rules. */
- if (access == access_default)
+ if (access == access_default_node)
{
if (is_friend (context, previous_scope))
- access = access_public;
+ access = access_public_node;
else if (TREE_PRIVATE (field))
- access = access_private;
+ access = access_private_node;
else if (TREE_PROTECTED (field))
- access = access_protected;
+ access = access_protected_node;
else
- access = access_public;
+ access = access_public_node;
}
- if (access == access_public && via_protected)
- access = access_protected;
+ if (access == access_public_node && via_protected)
+ access = access_protected_node;
- if (access == access_protected && protected_ok)
- access = access_public;
+ if (access == access_protected_node && protected_ok)
+ access = access_public_node;
#if 0
- if (access == access_public)
+ if (access == access_public_node)
DECL_PUBLIC (field) = 1;
- else if (access == access_protected)
+ else if (access == access_protected_node)
DECL_PROTECTED (field) = 1;
- else if (access == access_private)
+ else if (access == access_private_node)
DECL_PRIVATE (field) = 1;
else my_friendly_abort (96);
#endif
@@ -993,6 +1072,7 @@ compute_access (basetype_path, field)
found as a base class and sub-object of the object denoted by
BINFO. This routine relies upon binfos not being shared, except
for binfos for virtual bases. */
+
static int
is_subobject_of_p (parent, binfo)
tree parent, binfo;
@@ -1019,7 +1099,8 @@ is_subobject_of_p (parent, binfo)
correspond to ANSI working paper Sept 17, 1992 10p4. The two
binfos given are the binfos corresponding to the particular places
the FIELD_DECLs are found. This routine relies upon binfos not
- being shared, except for virtual bases. */
+ being shared, except for virtual bases. */
+
static int
hides (hider_binfo, hidee_binfo)
tree hider_binfo, hidee_binfo;
@@ -1029,28 +1110,30 @@ hides (hider_binfo, hidee_binfo)
part is always true is the second part is true.
When hider and hidee are the same (two ways to get to the exact
- same member) we consider either one as hiding the other. */
+ same member) we consider either one as hiding the other. */
return is_subobject_of_p (hidee_binfo, hider_binfo);
}
/* Very similar to lookup_fnfields_1 but it ensures that at least one
function was declared inside the class given by TYPE. It really should
only return functions that match the given TYPE. */
+
static int
lookup_fnfields_here (type, name)
tree type, name;
{
- int index = lookup_fnfields_1 (type, name);
+ int idx = lookup_fnfields_1 (type, name);
tree fndecls;
- if (index <= 0)
- return index;
- fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ /* ctors and dtors are always only in the right class. */
+ if (idx <= 1)
+ return idx;
+ fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
while (fndecls)
{
if (TYPE_MAIN_VARIANT (DECL_CLASS_CONTEXT (fndecls))
== TYPE_MAIN_VARIANT (type))
- return index;
+ return idx;
fndecls = TREE_CHAIN (fndecls);
}
return -1;
@@ -1064,6 +1147,7 @@ lookup_fnfields_here (type, name)
It was not clear what should happen if WANT_TYPE is set, and an
ambiguity is found. At least one use (lookup_name) to not see
the error. */
+
tree
lookup_field (xbasetype, name, protect, want_type)
register tree xbasetype, name;
@@ -1072,9 +1156,9 @@ lookup_field (xbasetype, name, protect, want_type)
int head = 0, tail = 0;
tree rval, rval_binfo = NULL_TREE, rval_binfo_h;
tree type, basetype_chain, basetype_path;
- enum access_type this_v = access_default;
+ tree this_v = access_default_node;
tree entry, binfo, binfo_h;
- enum access_type own_access = access_default;
+ tree own_access = access_default_node;
int vbase_name_p = VBASE_NAME_P (name);
/* rval_binfo is the binfo associated with the found member, note,
@@ -1095,12 +1179,25 @@ lookup_field (xbasetype, name, protect, want_type)
/* Set this to nonzero if we don't know how to compute
accurate error messages for access control. */
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
+#if 0
+ /* We cannot search for constructor/destructor names like this. */
+ /* This can't go here, but where should it go? */
/* If we are looking for a constructor in a templated type, use the
unspecialized name, as that is how we store it. */
if (IDENTIFIER_TEMPLATE (name))
name = constructor_name (name);
+#endif
+
+ if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype)
+ && IDENTIFIER_CLASS_VALUE (name))
+ {
+ tree field = IDENTIFIER_CLASS_VALUE (name);
+ if (TREE_CODE (field) != FUNCTION_DECL
+ && ! (want_type && TREE_CODE (field) != TYPE_DECL))
+ return field;
+ }
if (TREE_CODE (xbasetype) == TREE_VEC)
{
@@ -1110,15 +1207,18 @@ lookup_field (xbasetype, name, protect, want_type)
else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype)))
{
type = xbasetype;
- basetype_path = TYPE_BINFO (xbasetype);
+ basetype_path = TYPE_BINFO (type);
BINFO_VIA_PUBLIC (basetype_path) = 1;
BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE;
}
- else my_friendly_abort (97);
+ else
+ my_friendly_abort (97);
+
+ complete_type (type);
if (CLASSTYPE_MTABLE_ENTRY (type))
{
- tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
while (tem && TREE_PURPOSE (tem) != name)
{
@@ -1144,7 +1244,7 @@ lookup_field (xbasetype, name, protect, want_type)
#ifdef GATHER_STATISTICS
n_calls_lookup_field++;
-#endif
+#endif /* GATHER_STATISTICS */
if (protect && flag_memoize_lookups && ! global_bindings_p ())
entry = make_memoized_table_entry (type, name, 0);
else
@@ -1179,16 +1279,16 @@ lookup_field (xbasetype, name, protect, want_type)
this_v = compute_access (basetype_path, rval);
if (TREE_CODE (rval) == CONST_DECL)
{
- if (this_v == access_private)
+ if (this_v == access_private_node)
errstr = "enum `%D' is a private value of class `%T'";
- else if (this_v == access_protected)
+ else if (this_v == access_protected_node)
errstr = "enum `%D' is a protected value of class `%T'";
}
else
{
- if (this_v == access_private)
+ if (this_v == access_private_node)
errstr = "member `%D' is a private member of class `%T'";
- else if (this_v == access_protected)
+ else if (this_v == access_protected_node)
errstr = "member `%D' is a protected member of class `%T'";
}
}
@@ -1217,12 +1317,12 @@ lookup_field (xbasetype, name, protect, want_type)
return rval;
}
- basetype_chain = build_tree_list (NULL_TREE, basetype_path);
+ basetype_chain = build_expr_list (NULL_TREE, basetype_path);
TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
- /* The ambiguity check relies upon breadth first searching. */
+ /* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
binfo = basetype_path;
@@ -1248,11 +1348,11 @@ lookup_field (xbasetype, name, protect, want_type)
TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
btypes);
else
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
btypes);
obstack_ptr_grow (&search_obstack, btypes);
@@ -1293,12 +1393,12 @@ lookup_field (xbasetype, name, protect, want_type)
else if (rval_binfo && hides (rval_binfo_h, binfo_h))
{
/* This is ok, the member found is in rval_binfo, not
- here (binfo). */
+ here (binfo). */
}
else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h))
{
/* This is ok, the member found is here (binfo), not in
- rval_binfo. */
+ rval_binfo. */
if (nval)
{
rval = nval;
@@ -1310,7 +1410,7 @@ lookup_field (xbasetype, name, protect, want_type)
}
else
{
- /* Undo finding it before, as something else hides it. */
+ /* Undo finding it before, as something else hides it. */
rval = NULL_TREE;
}
rval_binfo = binfo;
@@ -1318,9 +1418,9 @@ lookup_field (xbasetype, name, protect, want_type)
}
else
{
- /* This is ambiguous. */
+ /* This is ambiguous. */
errstr = "request for member `%D' is ambiguous";
- protect = 2;
+ protect += 2;
break;
}
}
@@ -1370,14 +1470,14 @@ lookup_field (xbasetype, name, protect, want_type)
/* If is possible for one of the derived types on the path to
have defined special access for this field. Look for such
declarations and report an error if a conflict is found. */
- enum access_type new_v;
+ tree new_v;
- if (this_v != access_default)
+ if (this_v != access_default_node)
new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval);
- if (this_v != access_default && new_v != this_v)
+ if (this_v != access_default_node && new_v != this_v)
{
errstr = "conflicting access to member `%D'";
- this_v = access_default;
+ this_v = access_default_node;
}
own_access = new_v;
CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp)));
@@ -1397,15 +1497,15 @@ lookup_field (xbasetype, name, protect, want_type)
if (errstr == 0)
{
- if (own_access == access_private)
+ if (own_access == access_private_node)
errstr = "member `%D' declared private";
- else if (own_access == access_protected)
+ else if (own_access == access_protected_node)
errstr = "member `%D' declared protected";
- else if (this_v == access_private)
+ else if (this_v == access_private_node)
errstr = TREE_PRIVATE (rval)
? "member `%D' is private"
: "member `%D' is from private base class";
- else if (this_v == access_protected)
+ else if (this_v == access_protected_node)
errstr = TREE_PROTECTED (rval)
? "member `%D' is protected"
: "member `%D' is from protected base class";
@@ -1426,6 +1526,14 @@ lookup_field (xbasetype, name, protect, want_type)
}
}
+ if (protect == 2)
+ {
+ /* If we are not interested in ambiguities, don't report them,
+ just return NULL_TREE. */
+ rval = NULL_TREE;
+ protect = 0;
+ }
+
if (errstr && protect)
{
cp_error (errstr, name, type);
@@ -1435,6 +1543,7 @@ lookup_field (xbasetype, name, protect, want_type)
}
/* Try to find NAME inside a nested class. */
+
tree
lookup_nested_field (name, complain)
tree name;
@@ -1477,10 +1586,8 @@ lookup_nested_field (name, complain)
enums in nested classes) when we do need to call
this fn at parse time. So, in those cases, we pass
complain as a 0 and just return a NULL_TREE. */
- error ("assignment to non-static member `%s' of enclosing class `%s'",
- lang_printable_name (id),
- IDENTIFIER_POINTER (TYPE_IDENTIFIER
- (DECL_CONTEXT (t))));
+ cp_error ("assignment to non-static member `%D' of enclosing class `%T'",
+ id, DECL_CONTEXT (t));
/* Mark this for do_identifier(). It would otherwise
claim that the variable was undeclared. */
TREE_TYPE (id) = error_mark_node;
@@ -1501,6 +1608,7 @@ lookup_nested_field (name, complain)
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 is no such field exists. */
+
static int
lookup_fnfields_1 (type, name)
tree type, name;
@@ -1514,18 +1622,41 @@ lookup_fnfields_1 (type, name)
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields_1++;
-#endif
- if (*methods && name == constructor_name (type))
+#endif /* GATHER_STATISTICS */
+
+ /* Constructors are first... */
+ if (*methods && name == ctor_identifier)
return 0;
+ /* and destructors are second. */
+ if (*++methods && name == dtor_identifier)
+ return 1;
+
while (++methods != end)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
-#endif
+#endif /* GATHER_STATISTICS */
if (DECL_NAME (*methods) == name)
break;
}
+
+ /* If we didn't find it, it might have been a template
+ conversion operator. (Note that we don't look for this case
+ above so that we will always find specializations first.) */
+ if (methods == end
+ && IDENTIFIER_TYPENAME_P (name))
+ {
+ methods = &TREE_VEC_ELT (method_vec, 0) + 1;
+
+ while (++methods != end)
+ {
+ if (TREE_CODE (*methods) == TEMPLATE_DECL
+ && IDENTIFIER_TYPENAME_P (DECL_NAME (*methods)))
+ break;
+ }
+ }
+
if (methods != end)
return methods - &TREE_VEC_ELT (method_vec, 0);
}
@@ -1537,7 +1668,7 @@ lookup_fnfields_1 (type, name)
which gives the following information (in a list):
TREE_TYPE: list of basetypes needed to get to...
- TREE_VALUE: list of all functions in of given type
+ TREE_VALUE: list of all functions in a given type
which have name NAME.
No access information is computed by this function,
@@ -1551,6 +1682,7 @@ lookup_fnfields_1 (type, name)
As a special case, is COMPLAIN is -1, we don't complain, and we
don't return error_mark_node, but rather the complete list of
virtuals. This is used by get_virtuals_named_this. */
+
tree
lookup_fnfields (basetype_path, name, complain)
tree basetype_path, name;
@@ -1582,7 +1714,7 @@ lookup_fnfields (basetype_path, name, complain)
/* Set this to nonzero if we don't know how to compute
accurate error messages for access control. */
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
if (complain == -1)
{
@@ -1590,19 +1722,23 @@ lookup_fnfields (basetype_path, name, complain)
protect = complain = 0;
}
+#if 0
+ /* We cannot search for constructor/destructor names like this. */
+ /* This can't go here, but where should it go? */
/* If we are looking for a constructor in a templated type, use the
unspecialized name, as that is how we store it. */
if (IDENTIFIER_TEMPLATE (name))
name = constructor_name (name);
+#endif
binfo = basetype_path;
binfo_h = binfo;
- type = BINFO_TYPE (basetype_path);
+ type = complete_type (BINFO_TYPE (basetype_path));
- /* The memoization code is in need of maintenance. */
+ /* The memoization code is in need of maintenance. */
if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
{
- tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
while (tem && TREE_PURPOSE (tem) != name)
{
@@ -1653,25 +1789,25 @@ lookup_fnfields (basetype_path, name, complain)
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields++;
-#endif
+#endif /* GATHER_STATISTICS */
if (protect && flag_memoize_lookups && ! global_bindings_p ())
entry = make_memoized_table_entry (type, name, 1);
else
entry = 0;
- index = lookup_fnfields_here (type, name);
- if (index >= 0 || lookup_field_1 (type, name))
+ idx = lookup_fnfields_here (type, name);
+ if (idx >= 0 || lookup_field_1 (type, name))
{
rval_binfo = basetype_path;
rval_binfo_h = rval_binfo;
}
- if (index >= 0)
+ if (idx >= 0)
{
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
rvals = my_tree_cons (basetype_path, rval, rvals);
if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
if (entry)
{
@@ -1683,6 +1819,16 @@ lookup_fnfields (basetype_path, name, complain)
}
rval = NULL_TREE;
+ if (name == ctor_identifier || name == dtor_identifier)
+ {
+ /* Don't allow lookups of constructors and destructors to go
+ deeper than the first place we look. */
+ if (entry)
+ TREE_TYPE (entry) = TREE_VALUE (entry) = NULL_TREE;
+
+ return NULL_TREE;
+ }
+
if (basetype_path == TYPE_BINFO (type))
{
basetype_chain = CLASSTYPE_BINFO_AS_LIST (type);
@@ -1692,13 +1838,13 @@ lookup_fnfields (basetype_path, name, complain)
}
else
{
- basetype_chain = build_tree_list (NULL_TREE, basetype_path);
+ basetype_chain = build_expr_list (NULL_TREE, basetype_path);
TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path);
TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
}
- /* The ambiguity check relies upon breadth first searching. */
+ /* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
binfo = basetype_path;
@@ -1708,7 +1854,7 @@ lookup_fnfields (basetype_path, name, complain)
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int index;
+ int idx;
/* Process and/or queue base types. */
for (i = 0; i < n_baselinks; i++)
@@ -1724,11 +1870,11 @@ lookup_fnfields (basetype_path, name, complain)
TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo);
TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo);
if (TREE_VIA_VIRTUAL (base_binfo))
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))),
btypes);
else
- btypes = tree_cons (NULL_TREE,
+ btypes = my_tree_cons (NULL_TREE,
TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i),
btypes);
obstack_ptr_grow (&search_obstack, btypes);
@@ -1758,32 +1904,32 @@ lookup_fnfields (basetype_path, name, complain)
and we do find NAME in TYPE, verify that such a second
sighting is in fact valid. */
- index = lookup_fnfields_here (type, name);
+ idx = lookup_fnfields_here (type, name);
- if (index >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
+ if (idx >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
{
if (rval_binfo && !find_all && hides (rval_binfo_h, binfo_h))
{
/* This is ok, the member found is in rval_binfo, not
- here (binfo). */
+ here (binfo). */
}
else if (rval_binfo==NULL_TREE || find_all || hides (binfo_h, rval_binfo_h))
{
/* This is ok, the member found is here (binfo), not in
- rval_binfo. */
- if (index >= 0)
+ rval_binfo. */
+ if (idx >= 0)
{
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
/* Note, rvals can only be previously set if find_all is
true. */
rvals = my_tree_cons (basetype_path, rval, rvals);
if (TYPE_BINFO_BASETYPES (type)
&& CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
}
else
{
- /* Undo finding it before, as something else hides it. */
+ /* Undo finding it before, as something else hides it. */
rval = NULL_TREE;
rvals = NULL_TREE;
}
@@ -1792,7 +1938,7 @@ lookup_fnfields (basetype_path, name, complain)
}
else
{
- /* This is ambiguous. */
+ /* This is ambiguous. */
errstr = "request for method `%D' is ambiguous";
rvals = error_mark_node;
break;
@@ -1840,17 +1986,17 @@ lookup_fnfields (basetype_path, name, complain)
/* Search a multiple inheritance hierarchy by breadth-first search.
- TYPE is an aggregate type, possibly in a multiple-inheritance hierarchy.
+ BINFO is an aggregate type, possibly in a multiple-inheritance hierarchy.
TESTFN is a function, which, if true, means that our condition has been met,
and its return value should be returned.
QFN, if non-NULL, is a predicate dictating whether the type should
even be queued. */
-HOST_WIDE_INT
+static HOST_WIDE_INT
breadth_first_search (binfo, testfn, qfn)
tree binfo;
- int (*testfn)();
- int (*qfn)();
+ int (*testfn) PROTO((tree, int));
+ int (*qfn) PROTO((tree, int));
{
int head = 0, tail = 0;
int rval = 0;
@@ -1908,18 +2054,7 @@ breadth_first_search (binfo, testfn, qfn)
}
/* Functions to use in breadth first searches. */
-typedef tree (*pft)();
-typedef int (*pfi)();
-
-int tree_needs_constructor_p (binfo, i)
- tree binfo;
- int i;
-{
- tree basetype;
- my_friendly_assert (i != 0, 296);
- basetype = BINFO_TYPE (BINFO_BASETYPE (binfo, i));
- return TYPE_NEEDS_CONSTRUCTING (basetype);
-}
+typedef int (*pfi) PROTO((tree, int));
static tree declarator;
@@ -1949,7 +2084,8 @@ get_virtuals_named_this (binfo)
return NULL_TREE;
}
-static tree get_virtual_destructor (binfo, i)
+static tree
+get_virtual_destructor (binfo, i)
tree binfo;
int i;
{
@@ -1957,12 +2093,13 @@ static tree get_virtual_destructor (binfo, i)
if (i >= 0)
type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i));
if (TYPE_HAS_DESTRUCTOR (type)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0)))
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
+ && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1)))
+ return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1);
return 0;
}
-int tree_has_any_destructor_p (binfo, i)
+static int
+tree_has_any_destructor_p (binfo, i)
tree binfo;
int i;
{
@@ -1978,6 +2115,7 @@ int tree_has_any_destructor_p (binfo, i)
DTORP is nonzero if we are looking for a destructor. Destructors
need special treatment because they do not match by name. */
+
tree
get_matching_virtual (binfo, fndecl, dtorp)
tree binfo, fndecl;
@@ -2059,18 +2197,19 @@ get_matching_virtual (binfo, fndecl, dtorp)
{
tree binfo = get_binfo (b, d, 1);
if (binfo != error_mark_node
- && ! BINFO_OFFSET_ZEROP (binfo))
+ && (! BINFO_OFFSET_ZEROP (binfo)
+ || TREE_VIA_VIRTUAL (binfo)))
sorry ("adjusting pointers for covariant returns");
}
if (TYPE_READONLY (d) > TYPE_READONLY (b))
{
- cp_error ("return type of `%#D' adds const", fndecl);
+ cp_error_at ("return type of `%#D' adds const", fndecl);
cp_error_at (" overriding definition as `%#D'",
tmp);
}
else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b))
{
- cp_error ("return type of `%#D' adds volatile",
+ cp_error_at ("return type of `%#D' adds volatile",
fndecl);
cp_error_at (" overriding definition as `%#D'",
tmp);
@@ -2081,11 +2220,11 @@ get_matching_virtual (binfo, fndecl, dtorp)
{
error ("invalid covariant return type (must use pointer or reference)");
cp_error_at (" overriding `%#D'", tmp);
- cp_error (" with `%#D'", fndecl);
+ cp_error_at (" with `%#D'", fndecl);
}
else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE)
{
- cp_error ("conflicting return type specified for virtual function `%#D'", fndecl);
+ cp_error_at ("conflicting return type specified for virtual function `%#D'", fndecl);
cp_error_at (" overriding definition as `%#D'", tmp);
SET_IDENTIFIER_ERROR_LOCUS (name, basetype);
}
@@ -2098,8 +2237,6 @@ get_matching_virtual (binfo, fndecl, dtorp)
break;
}
}
- if (best == NULL_TREE && warn_overloaded_virtual)
- cp_warning_at ("conflicting specification deriving virtual function `%D'", fndecl);
return best;
}
@@ -2108,10 +2245,12 @@ get_matching_virtual (binfo, fndecl, dtorp)
/* Return the list of virtual functions which are abstract in type
TYPE that come from non virtual base classes. See
expand_direct_vtbls_init for the style of search we do. */
+
static tree
get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
- tree binfo, abstract_virtuals;
+ tree binfo;
int do_self;
+ tree abstract_virtuals;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2119,8 +2258,8 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
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))
abstract_virtuals
= get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
@@ -2148,6 +2287,7 @@ get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
/* Return the list of virtual functions which are abstract in type TYPE.
This information is cached, and so must be built on a
non-temporary obstack. */
+
tree
get_abstract_virtuals (type)
tree type;
@@ -2155,7 +2295,7 @@ get_abstract_virtuals (type)
tree vbases;
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
- /* First get all from non-virtual bases. */
+ /* First get all from non-virtual bases. */
abstract_virtuals
= get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
@@ -2190,7 +2330,7 @@ get_baselinks (type_as_binfo_list, type, name)
tree type_as_binfo_list;
tree type, name;
{
- int head = 0, tail = 0, index;
+ int head = 0, tail = 0, idx;
tree rval = 0, nval = 0;
tree basetypes = type_as_binfo_list;
tree binfo = TYPE_BINFO (type);
@@ -2226,17 +2366,17 @@ get_baselinks (type_as_binfo_list, type, name)
basetypes = search_stack->first[head++];
binfo = TREE_VALUE (basetypes);
type = BINFO_TYPE (binfo);
- index = lookup_fnfields_1 (type, name);
- if (index >= 0)
+ idx = lookup_fnfields_1 (type, name);
+ if (idx >= 0)
{
- nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval);
if (TYPE_BINFO_BASETYPES (type) == 0)
goto dont_queue;
else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1)
{
if (CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
goto dont_queue;
}
}
@@ -2294,7 +2434,8 @@ static int mi_size;
/* This routine converts a pointer to be a pointer of an immediate
base class. The normal convert_pointer_to routine would diagnose
the conversion as ambiguous, under MI code that has the base class
- as an ambiguous base class. */
+ as an ambiguous base class. */
+
static tree
convert_pointer_to_single_level (to_type, expr)
tree to_type, expr;
@@ -2313,12 +2454,13 @@ convert_pointer_to_single_level (to_type, expr)
This routine has to remember the path it walked up, when
dfs_init_vbase_pointers is the work function, as otherwise there
- would be no record. */
+ would be no record. */
+
static void
dfs_walk (binfo, fn, qfn)
tree binfo;
- void (*fn)();
- int (*qfn)();
+ void (*fn) PROTO((tree));
+ int (*qfn) PROTO((tree));
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2329,7 +2471,9 @@ dfs_walk (binfo, fn, qfn)
if (qfn == 0 || (*qfn)(base_binfo))
{
- if (fn == dfs_init_vbase_pointers)
+ if (TREE_CODE (BINFO_TYPE (base_binfo)) == TEMPLATE_TYPE_PARM)
+ /* Pass */;
+ else if (fn == dfs_init_vbase_pointers)
{
/* When traversing an arbitrary MI hierarchy, we need to keep
a record of the path we took to get down to the final base
@@ -2354,7 +2498,7 @@ dfs_walk (binfo, fn, qfn)
/* No need for the conversion here, as we know it is the
right type. */
vbase_decl_ptr_intermediate
- = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
+ = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (base_binfo));
}
else
{
@@ -2366,8 +2510,9 @@ dfs_walk (binfo, fn, qfn)
dfs_walk (base_binfo, fn, qfn);
vbase_decl_ptr_intermediate = saved_vbase_decl_ptr_intermediate;
- } else
- dfs_walk (base_binfo, fn, qfn);
+ }
+ else
+ dfs_walk (base_binfo, fn, qfn);
}
}
@@ -2382,31 +2527,37 @@ static int unnumberedp (binfo) tree binfo;
static int markedp (binfo) tree binfo;
{ return BINFO_MARKED (binfo); }
-static int bfs_markedp (binfo, i) tree binfo; int i;
-{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
static int unmarkedp (binfo) tree binfo;
{ return BINFO_MARKED (binfo) == 0; }
+
+#if 0
+static int bfs_markedp (binfo, i) tree binfo; int i;
+{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)); }
static int bfs_unmarkedp (binfo, i) tree binfo; int i;
{ return BINFO_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo); }
static int bfs_marked_vtable_pathp (binfo, i) tree binfo; int i;
{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_vtable_pathp (binfo) tree binfo;
-{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
static int bfs_unmarked_vtable_pathp (binfo, i) tree binfo; int i;
{ return BINFO_VTABLE_PATH_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
-static int marked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo); }
static int bfs_marked_new_vtablep (binfo, i) tree binfo; int i;
{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)); }
-static int unmarked_new_vtablep (binfo) tree binfo;
-{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
static int bfs_unmarked_new_vtablep (binfo, i) tree binfo; int i;
{ return BINFO_NEW_VTABLE_MARKED (BINFO_BASETYPE (binfo, i)) == 0; }
+#endif
+
+static int marked_vtable_pathp (binfo) tree binfo;
+{ return BINFO_VTABLE_PATH_MARKED (binfo); }
+static int unmarked_vtable_pathp (binfo) tree binfo;
+{ return BINFO_VTABLE_PATH_MARKED (binfo) == 0; }
+static int marked_new_vtablep (binfo) tree binfo;
+{ return BINFO_NEW_VTABLE_MARKED (binfo); }
+static int unmarked_new_vtablep (binfo) tree binfo;
+{ return BINFO_NEW_VTABLE_MARKED (binfo) == 0; }
+#if 0
static int dfs_search_slot_nonempty_p (binfo) tree binfo;
{ return CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) != 0; }
+#endif
static int dfs_debug_unmarkedp (binfo) tree binfo;
{ return CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo)) == 0; }
@@ -2432,14 +2583,17 @@ dfs_unnumber (binfo)
BINFO_CID (binfo) = 0;
}
+#if 0
static void
dfs_mark (binfo) tree binfo;
{ SET_BINFO_MARKED (binfo); }
+#endif
static void
dfs_unmark (binfo) tree binfo;
{ CLEAR_BINFO_MARKED (binfo); }
+#if 0
static void
dfs_mark_vtable_path (binfo) tree binfo;
{ SET_BINFO_VTABLE_PATH_MARKED (binfo); }
@@ -2459,6 +2613,7 @@ dfs_unmark_new_vtable (binfo) tree binfo;
static void
dfs_clear_search_slot (binfo) tree binfo;
{ CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (binfo)) = 0; }
+#endif
static void
dfs_debug_mark (binfo)
@@ -2472,9 +2627,12 @@ dfs_debug_mark (binfo)
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
- /* If interface info is known, the value of (?@@?) is correct. */
- if (methods == 0
- || CLASSTYPE_INTERFACE_KNOWN (t)
+ if (methods == 0)
+ return;
+
+ /* If interface info is known, either we've already emitted the debug
+ info or we don't need to. */
+ if (CLASSTYPE_INTERFACE_KNOWN (t)
|| (write_virtuals == 2 && TYPE_VIRTUAL_P (t)))
return;
@@ -2484,10 +2642,12 @@ dfs_debug_mark (binfo)
if (current_function_decl == NULL_TREE
|| DECL_CLASS_CONTEXT (current_function_decl) != t)
{
- if (TREE_VEC_ELT (methods, 0))
+ if (TREE_VEC_ELT (methods, 1))
+ methods = TREE_VEC_ELT (methods, 1);
+ else if (TREE_VEC_ELT (methods, 0))
methods = TREE_VEC_ELT (methods, 0);
else
- methods = TREE_VEC_ELT (methods, 1);
+ methods = TREE_VEC_ELT (methods, 2);
while (methods)
{
if (DECL_VINDEX (methods)
@@ -2512,6 +2672,7 @@ dfs_debug_mark (binfo)
virtual base class, given the global pointer vbase_decl_ptr.
We use the global vbase_types. ICK! */
+
static void
dfs_find_vbases (binfo)
tree binfo;
@@ -2530,8 +2691,8 @@ dfs_find_vbases (binfo)
tree binfo = binfo_member (vbase, vbase_types);
CLASSTYPE_SEARCH_SLOT (vbase)
- = (char *) build (PLUS_EXPR, build_pointer_type (vbase),
- vbase_decl_ptr, BINFO_OFFSET (binfo));
+ = build (PLUS_EXPR, build_pointer_type (vbase),
+ vbase_decl_ptr, BINFO_OFFSET (binfo));
}
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
@@ -2548,12 +2709,12 @@ dfs_init_vbase_pointers (binfo)
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
- /* If there is a rtti, it is the first field, though perhaps from
- the base class. Otherwise, the first fields are virtual base class
- pointer fields. */
- if (CLASSTYPE_RTTI (type) && VFIELD_NAME_P (DECL_NAME (fields)))
- /* Get past vtable for the object. */
+#if 0
+ /* See finish_struct_1 for when we can enable this. */
+ /* If we have a vtable pointer first, skip it. */
+ if (VFIELD_NAME_P (DECL_NAME (fields)))
fields = TREE_CHAIN (fields);
+#endif
if (fields == NULL_TREE
|| DECL_NAME (fields) == NULL_TREE
@@ -2570,7 +2731,7 @@ dfs_init_vbase_pointers (binfo)
{
tree ref = build (COMPONENT_REF, TREE_TYPE (fields),
build_indirect_ref (this_vbase_ptr, NULL_PTR), fields);
- tree init = (tree)CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
+ tree init = CLASSTYPE_SEARCH_SLOT (TREE_TYPE (TREE_TYPE (fields)));
vbase_init_result = tree_cons (binfo_member (TREE_TYPE (TREE_TYPE (fields)),
vbase_types),
build_modify_expr (ref, NOP_EXPR, init),
@@ -2582,6 +2743,7 @@ dfs_init_vbase_pointers (binfo)
/* Sometimes this needs to clear both VTABLE_PATH and NEW_VTABLE. Other
times, just NEW_VTABLE, but optimizer should make both with equal
efficiency (though it does not currently). */
+
static void
dfs_clear_vbase_slots (binfo)
tree binfo;
@@ -2603,9 +2765,7 @@ init_vbase_pointers (type, decl_ptr)
tree binfo = TYPE_BINFO (type);
flag_this_is_variable = -2;
vbase_types = CLASSTYPE_VBASECLASSES (type);
- vbase_decl_ptr = decl_ptr;
- vbase_decl = build_indirect_ref (decl_ptr, NULL_PTR);
- vbase_decl_ptr_intermediate = vbase_decl_ptr;
+ vbase_decl_ptr = vbase_decl_ptr_intermediate = decl_ptr;
vbase_init_result = NULL_TREE;
dfs_walk (binfo, dfs_find_vbases, unmarked_vtable_pathp);
dfs_walk (binfo, dfs_init_vbase_pointers, marked_vtable_pathp);
@@ -2626,6 +2786,7 @@ init_vbase_pointers (type, decl_ptr)
We know that if there is more than one place (binfo) the fndecl that the
declared, they all refer to the same binfo. See get_class_offset_1 for
the check that ensures this. */
+
static tree
virtual_context (fndecl, t, vbase)
tree fndecl, t, vbase;
@@ -2663,7 +2824,10 @@ virtual_context (fndecl, t, vbase)
they may upcast into a direct base, or
they may upcast into a different vbase.
- We only need to do fixups in case 2 and 3.
+ We only need to do fixups in case 2 and 3. In case 2, we add in
+ the virtual base offset to effect an upcast, in case 3, we add in
+ the virtual base offset to effect an upcast, then subtract out the
+ offset for the other virtual base, to effect a downcast into it.
This routine mirrors fixup_vtable_deltas in functionality, though
this one is runtime based, and the other is compile time based.
@@ -2671,10 +2835,15 @@ virtual_context (fndecl, t, vbase)
done at runtime.
VBASE_OFFSETS is an association list of virtual bases that contains
- offset information, so the offsets are only calculated once. */
+ offset information for the virtual bases, so the offsets are only
+ calculated once. The offsets are computed by where we think the
+ vbase should be (as noted by the CLASSTYPE_SEARCH_SLOT) minus where
+ the vbase really is. */
+
static void
-expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
- tree binfo, addr, orig_addr, vbase, t, *vbase_offsets;
+expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
+ vbase_offsets)
+ tree binfo, addr, orig_addr, vbase, vbase_addr, t, *vbase_offsets;
{
tree virtuals = BINFO_VIRTUALS (binfo);
tree vc;
@@ -2684,8 +2853,8 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
delta = purpose_member (vbase, *vbase_offsets);
if (! delta)
{
- delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbase));
- delta = build (MINUS_EXPR, ptrdiff_type_node, delta, addr);
+ delta = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbase));
+ delta = build (MINUS_EXPR, ptrdiff_type_node, delta, vbase_addr);
delta = save_expr (delta);
delta = tree_cons (vbase, delta, *vbase_offsets);
*vbase_offsets = delta;
@@ -2702,8 +2871,8 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
&& current_fndecl != abort_fndecl
&& (vc=virtual_context (current_fndecl, t, vbase)) != vbase)
{
- /* This may in fact need a runtime fixup. */
- tree idx = DECL_VINDEX (current_fndecl);
+ /* This may in fact need a runtime fixup. */
+ tree idx = build_int_2 (n, 0);
tree vtbl = BINFO_VTABLE (binfo);
tree nvtbl = lookup_name (DECL_NAME (vtbl), 0);
tree aref, ref, naref;
@@ -2720,6 +2889,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
DECL_ALIGN (nvtbl) = MAX (TYPE_ALIGN (double_type_node),
DECL_ALIGN (nvtbl));
TREE_READONLY (nvtbl) = 0;
+ DECL_ARTIFICIAL (nvtbl) = 1;
nvtbl = pushdecl (nvtbl);
init = NULL_TREE;
cp_finish_decl (nvtbl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
@@ -2729,7 +2899,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
nvtbl, vtbl);
TREE_SIDE_EFFECTS (init) = 1;
expand_expr_stmt (init);
- /* Update the vtable pointers as necessary. */
+ /* Update the vtable pointers as necessary. */
ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR), DECL_CONTEXT (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))));
expand_expr_stmt (build_modify_expr (ref, NOP_EXPR,
build_unary_op (ADDR_EXPR, nvtbl, 0)));
@@ -2737,28 +2907,34 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
assemble_external (vtbl);
aref = build_array_ref (vtbl, idx);
naref = build_array_ref (nvtbl, idx);
- old_delta = build_component_ref (aref, delta_identifier, 0, 0);
- new_delta = build_component_ref (naref, delta_identifier, 0, 0);
+ old_delta = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
+ new_delta = build_component_ref (naref, delta_identifier, NULL_TREE, 0);
+
+ /* This is a upcast, so we have to add the offset for the
+ virtual base. */
old_delta = build_binary_op (PLUS_EXPR, old_delta,
TREE_VALUE (delta), 0);
if (vc)
{
- /* If this is set, we need to add in delta adjustments for
- the other virtual base. */
+ /* If this is set, we need to subtract out the delta
+ adjustments for the other virtual base that we
+ downcast into. */
tree vc_delta = purpose_member (vc, *vbase_offsets);
if (! vc_delta)
{
tree vc_addr = convert_pointer_to_real (vc, orig_addr);
- vc_delta = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc));
+ vc_delta = CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vc));
vc_delta = build (MINUS_EXPR, ptrdiff_type_node,
- vc_addr, vc_delta);
+ vc_delta, vc_addr);
vc_delta = save_expr (vc_delta);
*vbase_offsets = tree_cons (vc, vc_delta, *vbase_offsets);
}
else
vc_delta = TREE_VALUE (vc_delta);
- old_delta = build_binary_op (PLUS_EXPR, old_delta, vc_delta, 0);
+ /* This is a downcast, so we have to subtract the offset
+ for the virtual base. */
+ old_delta = build_binary_op (MINUS_EXPR, old_delta, vc_delta, 0);
}
TREE_READONLY (new_delta) = 0;
@@ -2772,10 +2948,12 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, t, vbase_offsets)
/* Fixup upcast offsets for all direct vtables. Patterned after
expand_direct_vtbls_init. */
+
static void
fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, orig_addr, type, vbase, vbase_offsets)
- tree real_binfo, binfo, addr, orig_addr, type, vbase, *vbase_offsets;
+ tree real_binfo, binfo;
int init_self, can_elide;
+ tree addr, orig_addr, type, vbase, *vbase_offsets;
{
tree real_binfos = BINFO_BASETYPES (real_binfo);
tree binfos = BINFO_BASETYPES (binfo);
@@ -2785,8 +2963,8 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
{
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))
fixup_virtual_upcast_offsets (real_base_binfo, base_binfo,
is_not_base_vtable, can_elide, addr,
@@ -2800,8 +2978,9 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
/* Should we use something besides CLASSTYPE_VFIELDS? */
if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
{
- addr = convert_pointer_to_real (binfo, addr);
- expand_upcast_fixups (real_binfo, addr, orig_addr, vbase, type, vbase_offsets);
+ tree new_addr = convert_pointer_to_real (binfo, addr);
+ expand_upcast_fixups (real_binfo, new_addr, orig_addr, vbase, addr,
+ type, vbase_offsets);
}
}
@@ -2818,30 +2997,22 @@ fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, ori
offsets are valid to store vtables. When zero, we must store new
vtables through virtual baseclass pointers.
- We setup and use the globals: vbase_decl, vbase_decl_ptr, vbase_types
+ We setup and use the globals: vbase_decl_ptr, vbase_types
ICK! */
void
-expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
+expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
tree binfo;
tree true_exp, decl_ptr;
- int use_computed_offsets;
{
tree type = BINFO_TYPE (binfo);
+
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
{
rtx fixup_insns = NULL_RTX;
- int old_flag = flag_this_is_variable;
tree vbases = CLASSTYPE_VBASECLASSES (type);
vbase_types = vbases;
vbase_decl_ptr = true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) : decl_ptr;
- vbase_decl = true_exp ? true_exp : build_indirect_ref (decl_ptr, NULL_PTR);
-
- if (use_computed_offsets)
- {
- /* This is an object of type IN_TYPE, */
- flag_this_is_variable = -2;
- }
dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep);
@@ -2849,57 +3020,25 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
for (; vbases; vbases = TREE_CHAIN (vbases))
{
tree addr;
- if (use_computed_offsets)
- addr = (tree)CLASSTYPE_SEARCH_SLOT (BINFO_TYPE (vbases));
- else
- {
-#if 1
- addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
-#else
- /* This should should never work better than the above. (mrs) */
- tree vbinfo = get_binfo (TREE_TYPE (vbases),
- TREE_TYPE (vbase_decl),
- 0);
-
- /* See is we can get lucky. */
- if (TREE_VIA_VIRTUAL (vbinfo))
- addr = convert_pointer_to_real (vbinfo, vbase_decl_ptr);
- else
- {
- /* We go through all these contortions to avoid this
- call, as it will fail when the virtual base type
- is ambiguous from here. We don't yet have a way
- to search for and find just an instance of the
- virtual base class. Searching for the binfo in
- vbases won't work, as we don't have the vbase
- pointer field, for all vbases in the main class,
- only direct vbases. */
- addr = convert_pointer_to_real (TREE_TYPE (vbases),
- vbase_decl_ptr);
- if (addr == error_mark_node)
- continue;
- }
-#endif
- }
- /* Do all vtables from this virtual base. */
+ addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
+
+ /* Do all vtables from this virtual base. */
/* This assumes that virtual bases can never serve as parent
- binfos. (in the CLASSTPE_VFIELD_PARENT sense) */
+ binfos. (in the CLASSTYPE_VFIELD_PARENT sense) */
expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
1, 0, addr);
- /* If we are using computed offsets we can skip fixups. */
- if (use_computed_offsets)
- continue;
-
- /* Now we adjust the offsets for virtual functions that cross
- virtual boundaries on an implicit upcast on vf call so that
- the layout of the most complete type is used, instead of
- assuming the layout of the virtual bases from our current type. */
+ /* Now we adjust the offsets for virtual functions that
+ cross virtual boundaries on an implicit upcast on vf call
+ so that the layout of the most complete type is used,
+ instead of assuming the layout of the virtual bases from
+ our current type. */
if (flag_vtable_thunks)
{
- /* We don't have dynamic thunks yet! So for now, just fail silently. */
+ /* We don't have dynamic thunks yet!
+ So for now, just fail silently. */
}
else
{
@@ -2930,19 +3069,9 @@ expand_indirect_vtbls_init (binfo, true_exp, decl_ptr, use_computed_offsets)
}
dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep);
-
- flag_this_is_variable = old_flag;
}
}
-void
-clear_search_slots (type)
- tree type;
-{
- dfs_walk (TYPE_BINFO (type),
- dfs_clear_search_slot, dfs_search_slot_nonempty_p);
-}
-
/* get virtual base class types.
This adds type to the vbase_types list in reverse dfs order.
Ordering is very important, so don't change it. */
@@ -2963,6 +3092,7 @@ dfs_get_vbase_types (binfo)
}
/* get a list of virtual base classes in dfs order. */
+
tree
get_vbase_types (type)
tree type;
@@ -3004,6 +3134,10 @@ dfs_record_inheritance (binfo)
tree baseclass = BINFO_TYPE (base_binfo);
mi_boolean *base_row = BINFO_DERIVES_FROM_STAR (base_binfo);
+ if (TREE_CODE (baseclass) == TEMPLATE_TYPE_PARM)
+ continue;
+ my_friendly_assert (CLASSTYPE_CID (baseclass) != 0, 2365);
+
/* Don't search if there's nothing there! MI_SIZE can be
zero as a result of parse errors. */
if (TYPE_BINFO_BASETYPES (baseclass) && mi_size > 0)
@@ -3045,11 +3179,14 @@ build_mi_matrix (type)
}
#endif
+ dfs_walk (binfo, dfs_number, unnumberedp);
+
mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
+ if (mi_size < (cid-1))
+ mi_size = cid-1;
mi_matrix = (char *)xmalloc ((mi_size + 1) * (mi_size + 1));
mi_type = type;
bzero (mi_matrix, (mi_size + 1) * (mi_size + 1));
- dfs_walk (binfo, dfs_number, unnumberedp);
dfs_walk (binfo, dfs_record_inheritance, unmarkedp);
dfs_walk (binfo, dfs_unmark, markedp);
}
@@ -3078,6 +3215,18 @@ note_debug_info_needed (type)
tree type;
{
tree field;
+
+ if (current_template_parms)
+ return;
+
+ /* We can't do the TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
+ does not support name references between translation units. Well, we
+ could, but that would mean putting global labels in the debug output
+ before each exported type and each of its functions and static data
+ members. */
+ if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
+ return;
+
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
@@ -3100,7 +3249,7 @@ envelope_add_decl (type, decl, values)
tree name = DECL_NAME (decl);
int dont_add = 0;
- /* virtual base names are always unique. */
+ /* virtual base names are always unique. */
if (VBASE_NAME_P (name))
*values = NULL_TREE;
@@ -3134,7 +3283,12 @@ envelope_add_decl (type, decl, values)
else
dont_add = 1;
}
- else if (context && TYPE_DERIVES_FROM (context, type))
+ /* If we don't check CLASSTYPE_CID on CONTEXT right now, we'll end
+ up subtracting from the address of MI_MATRIX, putting us off
+ in la la land. */
+ else if (context
+ && CLASSTYPE_CID (context)
+ && TYPE_DERIVES_FROM (context, type))
{
/* Don't add in *values to list */
*values = NULL_TREE;
@@ -3152,7 +3306,12 @@ envelope_add_decl (type, decl, values)
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
- if (context && TYPE_DERIVES_FROM (context, type))
+ /* If we don't check CLASSTYPE_CID on CONTEXT right now, we'll end
+ up subtracting from the address of MI_MATRIX, putting us off
+ in la la land. */
+ if (context
+ && CLASSTYPE_CID (context)
+ && TYPE_DERIVES_FROM (context, type))
{
/* remove *tmp from list */
*tmp = TREE_CHAIN (*tmp);
@@ -3253,10 +3412,10 @@ dfs_pushdecls (binfo)
}
method_vec = CLASSTYPE_METHOD_VEC (type);
- if (method_vec != 0)
+ if (method_vec)
{
/* Farm out constructors and destructors. */
- methods = &TREE_VEC_ELT (method_vec, 1);
+ methods = &TREE_VEC_ELT (method_vec, 2);
end = TREE_VEC_END (method_vec);
while (methods != end)
@@ -3293,6 +3452,7 @@ dfs_pushdecls (binfo)
}
/* Consolidate unique (by name) member functions. */
+
static void
dfs_compress_decls (binfo)
tree binfo;
@@ -3303,7 +3463,7 @@ dfs_compress_decls (binfo)
if (method_vec != 0)
{
/* Farm out constructors and destructors. */
- tree *methods = &TREE_VEC_ELT (method_vec, 1);
+ tree *methods = &TREE_VEC_ELT (method_vec, 2);
tree *end = TREE_VEC_END (method_vec);
for (; methods != end; methods++)
@@ -3335,26 +3495,14 @@ dfs_compress_decls (binfo)
with `error_mark_node' so that if they are encountered
without explicit qualification, we can emit an error
message. */
+
void
push_class_decls (type)
tree type;
{
- tree id;
struct obstack *ambient_obstack = current_obstack;
-
search_stack = push_search_level (search_stack, &search_obstack);
- id = TYPE_IDENTIFIER (type);
-#if 0
- if (IDENTIFIER_TEMPLATE (id) != 0)
- {
- tree tmpl = IDENTIFIER_TEMPLATE (id);
- push_template_decls (DECL_ARGUMENTS (TREE_PURPOSE (tmpl)),
- TREE_VALUE (tmpl), 1);
- overload_template_name (id, 1);
- }
-#endif
-
/* Push class fields into CLASS_VALUE scope, and mark. */
dfs_walk (TYPE_BINFO (type), dfs_pushdecls, unmarkedp);
@@ -3381,7 +3529,31 @@ push_class_decls (type)
{
tree node = TREE_VALUE (new);
- while (TREE_CODE (node) == TREE_LIST)
+ if (TREE_CODE (node) == TYPE_DECL
+ && DECL_ARTIFICIAL (node)
+ && IS_AGGR_TYPE (TREE_TYPE (node))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (node)))
+ {
+ tree t = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (node));
+ tree n = new;
+
+ for (; n; n = TREE_CHAIN (n))
+ {
+ tree d = TREE_VALUE (n);
+ if (TREE_CODE (d) == TYPE_DECL
+ && DECL_ARTIFICIAL (node)
+ && IS_AGGR_TYPE (TREE_TYPE (d))
+ && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (d))
+ && CLASSTYPE_TI_TEMPLATE (TREE_TYPE (d)) == t)
+ /* OK */;
+ else
+ break;
+ }
+
+ if (n == NULL_TREE)
+ new = t;
+ }
+ else while (TREE_CODE (node) == TREE_LIST)
node = TREE_VALUE (node);
id = DECL_NAME (node);
}
@@ -3402,6 +3574,7 @@ push_class_decls (type)
}
/* Here's a subroutine we need because C lacks lambdas. */
+
static void
dfs_unuse_fields (binfo)
tree binfo;
@@ -3429,8 +3602,7 @@ unuse_fields (type)
}
void
-pop_class_decls (type)
- tree type;
+pop_class_decls ()
{
/* We haven't pushed a search level when dealing with cached classes,
so we'd better not try to pop it. */
@@ -3464,9 +3636,9 @@ print_search_statistics ()
fprintf (stderr, "%d fnfields searched in %d calls to lookup_fnfields\n",
n_outer_fields_searched, n_calls_lookup_fnfields);
fprintf (stderr, "%d calls to get_base_type\n", n_calls_get_base_type);
-#else
+#else /* GATHER_STATISTICS */
fprintf (stderr, "no search statistics\n");
-#endif
+#endif /* GATHER_STATISTICS */
}
void
@@ -3478,7 +3650,7 @@ init_search_processing ()
/* This gives us room to build our chains of basetypes,
whether or not we decide to memoize them. */
- type_stack = push_type_level (0, &type_obstack);
+ type_stack = push_type_level ((struct stack_level *)0, &type_obstack);
_vptr_name = get_identifier ("_vptr");
}
@@ -3494,24 +3666,34 @@ reinit_search_statistics ()
memoized_fast_rejects[1] = 0;
memoized_fields_searched[0] = 0;
memoized_fields_searched[1] = 0;
+#ifdef GATHER_STATISTICS
n_fields_searched = 0;
n_calls_lookup_field = 0, n_calls_lookup_field_1 = 0;
n_calls_lookup_fnfields = 0, n_calls_lookup_fnfields_1 = 0;
n_calls_get_base_type = 0;
n_outer_fields_searched = 0;
n_contexts_saved = 0;
+#endif /* GATHER_STATISTICS */
}
+#define scratch_tree_cons expr_tree_cons
+
static tree conversions;
static void
add_conversions (binfo)
tree binfo;
{
- tree tmp = CLASSTYPE_FIRST_CONVERSION (BINFO_TYPE (binfo));
- for (; tmp && IDENTIFIER_TYPENAME_P (DECL_NAME (tmp));
- tmp = TREE_CHAIN (tmp))
- conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
- conversions);
+ int i;
+ tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
+
+ for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
+ {
+ tree tmp = TREE_VEC_ELT (method_vec, i);
+ if (! IDENTIFIER_TYPENAME_P (DECL_NAME (tmp)))
+ break;
+ conversions = scratch_tree_cons (binfo, tmp, conversions);
+ }
+ SET_BINFO_MARKED (binfo);
}
tree
@@ -3519,6 +3701,89 @@ lookup_conversions (type)
tree type;
{
conversions = NULL_TREE;
- dfs_walk (TYPE_BINFO (type), add_conversions, 0);
+ if (TYPE_SIZE (type))
+ {
+ dfs_walk (TYPE_BINFO (type), add_conversions, unmarkedp);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
+ }
return conversions;
}
+
+/* Subroutine of get_template_base. */
+
+static tree
+get_template_base_recursive (binfo, rval, template, via_virtual)
+ tree binfo, template, rval;
+ int via_virtual;
+{
+ tree binfos;
+ int i, n_baselinks;
+ tree type = BINFO_TYPE (binfo);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && CLASSTYPE_TI_TEMPLATE (type) == template)
+ {
+ if (rval == NULL_TREE || rval == type)
+ return type;
+ else
+ return error_mark_node;
+ }
+
+ binfos = BINFO_BASETYPES (binfo);
+ n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
+
+ /* Process base types. */
+ for (i = 0; i < n_baselinks; i++)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, i);
+
+ /* Find any specific instance of a virtual base, when searching with
+ a binfo... */
+ if (BINFO_MARKED (base_binfo) == 0)
+ {
+ int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
+
+ /* When searching for a non-virtual, we cannot mark
+ virtually found binfos. */
+ if (! this_virtual)
+ SET_BINFO_MARKED (base_binfo);
+
+ rval = get_template_base_recursive
+ (base_binfo, rval, template, this_virtual);
+ if (rval == error_mark_node)
+ return rval;
+ }
+ }
+
+ return rval;
+}
+
+/* Given a class template TEMPLATE and a class type or binfo node BINFO,
+ find the unique base type in BINFO that is an instance of TEMPLATE.
+ If there are more than one, return error_mark_node. Used by unify. */
+
+tree
+get_template_base (template, binfo)
+ register tree template, binfo;
+{
+ tree type, rval;
+
+ if (TREE_CODE (binfo) == TREE_VEC)
+ type = BINFO_TYPE (binfo);
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
+ {
+ type = complete_type (binfo);
+ binfo = TYPE_BINFO (type);
+ }
+ else
+ my_friendly_abort (92);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && CLASSTYPE_TI_TEMPLATE (type) == template)
+ return type;
+
+ rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
+ dfs_walk (binfo, dfs_unmark, markedp);
+
+ return rval;
+}
diff --git a/gnu/usr.bin/gcc/cp/sig.c b/gnu/usr.bin/gcc/cp/sig.c
index 135dc6d7794..ba3af425384 100644
--- a/gnu/usr.bin/gcc/cp/sig.c
+++ b/gnu/usr.bin/gcc/cp/sig.c
@@ -1,5 +1,5 @@
/* Functions dealing with signatures and signature pointers/references.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
Contributed by Gerald Baumgartner (gb@cs.purdue.edu)
This file is part of GNU CC.
@@ -32,10 +32,22 @@ extern struct obstack *current_obstack;
extern struct obstack permanent_obstack;
extern struct obstack *saveable_obstack;
-extern void error ();
-extern void sorry ();
extern void compiler_error ();
-extern void make_decl_rtl PROTO((tree, char *, int));
+
+static tree save_this PROTO((tree));
+static tree build_sptr_ref PROTO((tree));
+static tree build_member_function_pointer PROTO((tree));
+static void undo_casts PROTO((tree));
+static tree build_signature_pointer_or_reference_name
+ PROTO((tree, int, int, int));
+static void build_signature_pointer_or_reference_decl
+ PROTO((tree, tree));
+static tree build_signature_pointer_or_reference_type
+ PROTO((tree, int, int, int));
+static tree get_sigtable_name PROTO((tree, tree));
+static tree build_signature_table_constructor PROTO((tree, tree));
+static int match_method_types PROTO((tree, tree));
+static tree build_sigtable PROTO((tree, tree, tree));
/* Used to help generate globally unique names for signature tables. */
@@ -153,8 +165,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
const s * sptr;
};
- Similarly, for `volatile' and `const volatile'.
- */
+ Similarly, for `volatile' and `const volatile'. */
t = make_lang_type (RECORD_TYPE);
{
@@ -185,7 +196,10 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
TREE_CHAIN (optr) = sptr;
TYPE_FIELDS (t) = optr;
- TYPE_ALIGN (t) = TYPE_ALIGN (optr_type);
+ /* Allow signature pointers/references to be grabbed 2 words at a time.
+ For this to work on a Sparc, we need 8-byte alignment. */
+ TYPE_ALIGN (t) = MAX (TYPE_ALIGN (double_type_node),
+ TYPE_ALIGN (optr_type));
/* A signature pointer/reference type isn't a `real' class type. */
IS_AGGR_TYPE (t) = 0;
@@ -396,8 +410,8 @@ match_method_types (sig_mtype, class_mtype)
/* Compare the first argument `this.' */
{
/* Get the type of what the `optr' is pointing to. */
- tree sig_this =
- TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types))));
+ tree sig_this
+ = TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types))));
tree class_this = TREE_VALUE (class_arg_types);
if (TREE_CODE (class_this) == RECORD_TYPE) /* Is `this' a sig ptr? */
@@ -420,6 +434,7 @@ match_method_types (sig_mtype, class_mtype)
}
/* Undo casts of opaque type variables to the RHS types. */
+
static void
undo_casts (sig_ty)
tree sig_ty;
@@ -530,11 +545,11 @@ build_signature_table_constructor (sig_ty, rhs)
if (rhs_method == NULL_TREE
|| (compute_access (basetypes, rhs_method)
- != access_public))
+ != access_public_node))
{
error ("class `%s' does not contain a method conforming to `%s'",
TYPE_NAME_STRING (rhstype),
- fndecl_as_string (NULL, sig_method, 1));
+ fndecl_as_string (sig_method, 1));
undo_casts (sig_ty);
return error_mark_node;
}
@@ -559,7 +574,7 @@ build_signature_table_constructor (sig_ty, rhs)
}
else
{
- tree tag, vb_off, delta, index, pfn, vt_off;
+ tree tag, vb_off, delta, idx, pfn, vt_off;
tree tag_decl, vb_off_decl, delta_decl, index_decl;
tree pfn_decl, vt_off_decl;
@@ -569,8 +584,9 @@ build_signature_table_constructor (sig_ty, rhs)
tag = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
delta = integer_zero_node;
- index = integer_zero_node;
- pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+ idx = integer_zero_node;
+ pfn = build_addr_func (rhs_method);
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
TREE_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1;
offset_p = 0; /* we can't offset the rhs sig table */
@@ -580,9 +596,13 @@ build_signature_table_constructor (sig_ty, rhs)
/* virtual member function */
tag = integer_one_node;
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
- delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
- rhstype, 1));
- index = DECL_VINDEX (rhs_method);
+ if (flag_vtable_thunks)
+ delta = BINFO_OFFSET
+ (get_binfo (DECL_CONTEXT (rhs_method), rhstype, 1));
+ else
+ delta = BINFO_OFFSET
+ (get_binfo (DECL_CLASS_CONTEXT (rhs_method), rhstype, 1));
+ idx = DECL_VINDEX (rhs_method);
vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method),
rhstype, 0));
}
@@ -593,8 +613,9 @@ build_signature_table_constructor (sig_ty, rhs)
vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
rhstype, 1));
- index = integer_zero_node;
- pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+ idx = integer_zero_node;
+ pfn = build_addr_func (rhs_method);
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
TREE_TYPE (pfn) = ptr_type_node;
TREE_ADDRESSABLE (rhs_method) = 1;
}
@@ -609,25 +630,25 @@ build_signature_table_constructor (sig_ty, rhs)
pfn_decl = TREE_CHAIN (index_decl);
vt_off_decl = TREE_CHAIN (pfn_decl);
- tag = convert (TREE_TYPE (tag_decl), tag);
- vb_off = convert (TREE_TYPE (vb_off_decl), vb_off);
- delta = convert (TREE_TYPE (delta_decl), delta);
- index = convert (TREE_TYPE (index_decl), index);
+ tag = cp_convert (TREE_TYPE (tag_decl), tag);
+ vb_off = cp_convert (TREE_TYPE (vb_off_decl), vb_off);
+ delta = cp_convert (TREE_TYPE (delta_decl), delta);
+ idx = cp_convert (TREE_TYPE (index_decl), idx);
if (DECL_VINDEX (rhs_method))
{
- vt_off = convert (TREE_TYPE (vt_off_decl), vt_off);
+ vt_off = cp_convert (TREE_TYPE (vt_off_decl), vt_off);
tbl_entry = build_tree_list (vt_off_decl, vt_off);
}
else
{
- pfn = convert (TREE_TYPE (pfn_decl), pfn);
+ pfn = cp_convert (TREE_TYPE (pfn_decl), pfn);
tbl_entry = build_tree_list (pfn_decl, pfn);
}
tbl_entry = tree_cons (delta_decl, delta,
- tree_cons (index_decl, index, tbl_entry));
+ tree_cons (index_decl, idx, tbl_entry));
tbl_entry = tree_cons (tag_decl, tag,
tree_cons (vb_off_decl, vb_off, tbl_entry));
tbl_entry = build (CONSTRUCTOR, sigtable_entry_type,
@@ -779,9 +800,9 @@ build_signature_pointer_constructor (lhs, rhs)
if (! ((TREE_CODE (rhstype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (rhstype)) == RECORD_TYPE)
- || (TYPE_LANG_SPECIFIC (rhstype) &&
- (IS_SIGNATURE_POINTER (rhstype)
- || IS_SIGNATURE_REFERENCE (rhstype)))))
+ || (TYPE_LANG_SPECIFIC (rhstype)
+ && (IS_SIGNATURE_POINTER (rhstype)
+ || IS_SIGNATURE_REFERENCE (rhstype)))))
{
error ("invalid assignment to signature pointer or reference");
return error_mark_node;
@@ -803,8 +824,8 @@ build_signature_pointer_constructor (lhs, rhs)
saveable_obstack = &permanent_obstack;
}
- if (TYPE_LANG_SPECIFIC (rhstype) &&
- (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype)))
+ if (TYPE_LANG_SPECIFIC (rhstype)
+ && (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype)))
{
if (SIGNATURE_TYPE (rhstype) == sig_ty)
{
@@ -910,22 +931,24 @@ save_this (instance)
/* Build a signature member function call. Looks up the signature table
entry corresponding to FUNCTION. Depending on the value of the CODE
field, either call the function in PFN directly, or use OFFSET to
- index INSTANCE's virtual function table. */
+ index the object's virtual function table. */
tree
-build_signature_method_call (basetype, instance, function, parms)
- tree basetype, instance, function, parms;
+build_signature_method_call (function, parms)
+ tree function, parms;
{
+ tree instance = TREE_VALUE (parms);
tree saved_instance = save_this (instance); /* Create temp for `this'. */
tree object_ptr = build_optr_ref (saved_instance);
tree new_object_ptr, new_parms;
tree signature_tbl_ptr = build_sptr_ref (saved_instance);
tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function));
+ tree basetype = DECL_CONTEXT (function);
tree basetype_path = TYPE_BINFO (basetype);
tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype,
signature_tbl_ptr),
sig_field_name, basetype_path, 1);
- tree tag, delta, pfn, vt_off, index, vfn;
+ tree tag, delta, pfn, vt_off, idx, vfn;
tree deflt_call = NULL_TREE, direct_call, virtual_call, result;
tbl_entry = save_expr (tbl_entry);
@@ -933,7 +956,7 @@ build_signature_method_call (basetype, instance, function, parms)
delta = build_component_ref (tbl_entry, delta_identifier, NULL_TREE, 1);
pfn = build_component_ref (tbl_entry, pfn_identifier, NULL_TREE, 1);
vt_off = build_component_ref (tbl_entry, vt_off_identifier, NULL_TREE, 1);
- index = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1);
+ idx = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1);
TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function));
if (IS_DEFAULT_IMPLEMENTATION (function))
@@ -943,11 +966,11 @@ build_signature_method_call (basetype, instance, function, parms)
}
new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype),
- convert (ptrdiff_type_node, object_ptr),
- convert (ptrdiff_type_node, delta));
+ cp_convert (ptrdiff_type_node, object_ptr),
+ cp_convert (ptrdiff_type_node, delta));
parms = tree_cons (NULL_TREE,
- convert (build_pointer_type (basetype), object_ptr),
+ cp_convert (build_pointer_type (basetype), object_ptr),
TREE_CHAIN (parms));
new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms));
@@ -955,10 +978,10 @@ build_signature_method_call (basetype, instance, function, parms)
/* Cast the signature method to have `this' of a normal pointer type. */
tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
- TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) =
- build_type_variant (build_pointer_type (basetype),
- TYPE_READONLY (old_this),
- TYPE_VOLATILE (old_this));
+ TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))))
+ = build_type_variant (build_pointer_type (basetype),
+ TYPE_READONLY (old_this),
+ TYPE_VOLATILE (old_this));
direct_call = build_function_call (pfn, new_parms);
@@ -967,23 +990,20 @@ build_signature_method_call (basetype, instance, function, parms)
vfld = build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtbl_type_node)),
- convert (ptrdiff_type_node, object_ptr),
- convert (ptrdiff_type_node, vt_off));
+ cp_convert (ptrdiff_type_node, object_ptr),
+ cp_convert (ptrdiff_type_node, vt_off));
vtbl = build_indirect_ref (build_indirect_ref (vfld, NULL_PTR),
NULL_PTR);
- aref = build_array_ref (vtbl, index);
+ aref = build_array_ref (vtbl, idx);
if (flag_vtable_thunks)
vfn = aref;
else
- vfn = build_component_ref (aref, pfn_identifier, 0, 0);
+ vfn = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
- if (flag_vtable_thunks)
- virtual_call = build_function_call (vfn, parms);
- else
- virtual_call = build_function_call (vfn, new_parms);
+ virtual_call = build_function_call (vfn, new_parms);
}
/* Undo the cast, make `this' a signature pointer again. */
@@ -998,7 +1018,7 @@ build_signature_method_call (basetype, instance, function, parms)
&& (!deflt_call || deflt_call == error_mark_node)))
{
compiler_error ("cannot build call of signature member function `%s'",
- fndecl_as_string (NULL, function, 1));
+ fndecl_as_string (function, 1));
return error_mark_node;
}
@@ -1039,7 +1059,7 @@ build_optr_ref (instance)
/* Create a COMPONENT_REF expression for referencing the SPTR field
of a signature pointer or reference. */
-tree
+static tree
build_sptr_ref (instance)
tree instance;
{
diff --git a/gnu/usr.bin/gcc/cp/spew.c b/gnu/usr.bin/gcc/cp/spew.c
index 4b30b955c46..ce884def14a 100644
--- a/gnu/usr.bin/gcc/cp/spew.c
+++ b/gnu/usr.bin/gcc/cp/spew.c
@@ -28,16 +28,16 @@ Boston, MA 02111-1307, USA. */
#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"
/* This takes a token stream that hasn't decided much about types and
tries to figure out as much as it can, with excessive lookahead and
- backtracking. */
+ backtracking. */
-/* fifo of tokens recognized and available to parser. */
+/* fifo of tokens recognized and available to parser. */
struct token {
/* The values for YYCHAR will fit in a short. */
short yychar;
@@ -45,7 +45,9 @@ struct token {
YYSTYPE yylval;
};
-static int do_aggr ();
+static int do_aggr PROTO((void));
+static int probe_obstack PROTO((struct obstack *, tree, unsigned int));
+static void scan_tokens PROTO((int));
/* From lex.c: */
/* the declaration found for the last IDENTIFIER token read in.
@@ -68,49 +70,54 @@ static int debug_yychar ();
#endif
/* Initialize token_obstack. Called once, from init_lex. */
+
void
init_spew ()
{
- gcc_obstack_init(&token_obstack);
+ gcc_obstack_init (&token_obstack);
}
#ifdef SPEW_DEBUG
/* Use functions for debugging... */
-/* Return the number of tokens available on the fifo. */
+/* Return the number of tokens available on the fifo. */
+
static int
num_tokens ()
{
- return (obstack_object_size(&token_obstack)/sizeof(struct token))
+ return (obstack_object_size (&token_obstack) / sizeof (struct token))
- first_token;
}
-/* Fetch the token N down the line from the head of the fifo. */
+/* Fetch the token N down the line from the head of the fifo. */
+
static struct token*
nth_token (n)
int n;
{
/* could just have this do slurp_ implicitly, but this way is easier
- * to debug... */
- my_friendly_assert (n < num_tokens(), 298);
- return ((struct token*)obstack_base(&token_obstack))+n+first_token;
+ to debug... */
+ my_friendly_assert (n < num_tokens (), 298);
+ return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
}
-/* Add a token to the token fifo. */
+/* Add a token to the token fifo. */
+
static void
add_token (t)
struct token* t;
{
- obstack_grow(&token_obstack,t,sizeof (struct token));
+ obstack_grow (&token_obstack, t, sizeof (struct token));
}
/* Consume the next token out of the fifo. */
+
static void
-consume_token()
+consume_token ()
{
- if (num_tokens() == 1)
+ if (num_tokens () == 1)
{
- obstack_free(&token_obstack, obstack_base (&token_obstack));
+ obstack_free (&token_obstack, obstack_base (&token_obstack));
first_token = 0;
}
else
@@ -121,15 +128,15 @@ consume_token()
/* ...otherwise use macros. */
#define num_tokens() \
- ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
+ ((obstack_object_size (&token_obstack) / sizeof (struct token)) - first_token)
#define nth_token(N) \
- (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
+ (((struct token*)obstack_base (&token_obstack))+(N)+first_token)
-#define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
+#define add_token(T) obstack_grow (&token_obstack, (T), sizeof (struct token))
#define consume_token() \
- (num_tokens() == 1 \
+ (num_tokens () == 1 \
? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
(first_token = 0)) \
: first_token++)
@@ -158,11 +165,11 @@ scan_tokens (n)
goto pad_tokens;
}
- while (num_tokens() <= n)
+ while (num_tokens () <= n)
{
- obstack_blank(&token_obstack,sizeof (struct token));
+ obstack_blank (&token_obstack, sizeof (struct token));
tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
- tmp->yychar = real_yylex();
+ tmp->yychar = real_yylex ();
tmp->end_of_file = end_of_file;
tmp->yylval = yylval;
end_of_file = 0;
@@ -173,7 +180,7 @@ scan_tokens (n)
pad_tokens:
while (num_tokens () <= n)
{
- obstack_blank(&token_obstack,sizeof (struct token));
+ obstack_blank (&token_obstack, sizeof (struct token));
tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
tmp->yychar = EMPTY;
tmp->end_of_file = 0;
@@ -182,35 +189,7 @@ scan_tokens (n)
}
}
-/* Create room for N tokens at the front of the fifo. This is used
- to insert new tokens into the stream ahead of the current token. */
-
-static void
-shift_tokens (n)
- int n;
-{
- if (first_token >= n)
- first_token -= n;
- else
- {
- int old_token_count = num_tokens ();
- char *tmp;
-
- obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));
- if (old_token_count)
- {
- tmp = (char *)alloca ((num_tokens () + (n-first_token))
- * sizeof (struct token));
- /* This move does not rely on the system being able to handle
- overlapping moves. */
- bcopy ((char *) nth_token (0), tmp,
- old_token_count * sizeof (struct token));
- bcopy (tmp, (char *) nth_token (n),
- old_token_count * sizeof (struct token));
- }
- first_token = 0;
- }
-}
+/* Like _obstack_allocated_p, but stop after checking NLEVELS chunks. */
static int
probe_obstack (h, obj, nlevels)
@@ -224,7 +203,7 @@ probe_obstack (h, obj, nlevels)
lp = (h)->chunk;
/* We use >= rather than > since the object cannot be exactly at
the beginning of the chunk but might be an empty object exactly
- at the end of an adjacent chunk. */
+ at the end of an adjacent chunk. */
for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
nlevels -= 1)
{
@@ -237,23 +216,24 @@ probe_obstack (h, obj, nlevels)
/* from lex.c: */
/* 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. */
+ Value is 0 if we treat this name in a default fashion. */
extern int looking_for_typename;
int looking_for_template;
+extern int do_snarf_defarg;
extern struct obstack *current_obstack, *saveable_obstack;
tree got_scope;
tree got_object;
int
-peekyylex()
+peekyylex ()
{
scan_tokens (0);
return nth_token (0)->yychar;
}
int
-yylex()
+yylex ()
{
struct token tmp_token;
tree trrr;
@@ -263,14 +243,24 @@ yylex()
if (spew_debug)
{
yylex_ctr ++;
- fprintf(stderr, "\t\t## %d ##",yylex_ctr);
+ fprintf (stderr, "\t\t## %d ##", yylex_ctr);
}
#endif
+ if (do_snarf_defarg)
+ {
+ my_friendly_assert (num_tokens () == 0, 2837);
+ tmp_token.yychar = DEFARG;
+ tmp_token.yylval.ttype = snarf_defarg ();
+ tmp_token.end_of_file = 0;
+ do_snarf_defarg = 0;
+ add_token (&tmp_token);
+ }
+
/* if we've got tokens, send them */
- if (num_tokens())
+ else if (num_tokens ())
{
- tmp_token= *nth_token(0);
+ tmp_token= *nth_token (0);
/* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
If we don't find it in CURRENT_OBSTACK's current or immediately
@@ -288,13 +278,13 @@ yylex()
tmp_token.yychar = real_yylex ();
tmp_token.yylval = yylval;
tmp_token.end_of_file = end_of_file;
- add_token(&tmp_token);
+ add_token (&tmp_token);
}
/* many tokens just need to be returned. At first glance, all we
- * have to do is send them back up, but some of them are needed to
- * figure out local context. */
- switch(tmp_token.yychar)
+ have to do is send them back up, but some of them are needed to
+ figure out local context. */
+ switch (tmp_token.yychar)
{
case EMPTY:
/* This is a lexical no-op. */
@@ -321,14 +311,14 @@ yylex()
switch (tmp_token.yychar)
{
case TYPENAME:
+ case SELFNAME:
lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
if (lastiddecl != trrr)
- {
- lastiddecl = trrr;
- if (got_scope || got_object)
- tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
- }
+ lastiddecl = trrr;
+ if (got_scope)
+ tmp_token.yylval.ttype = trrr;
break;
+ case PFUNCNAME:
case IDENTIFIER:
lastiddecl = trrr;
break;
@@ -337,7 +327,7 @@ yylex()
break;
case NSNAME:
lastiddecl = trrr;
- if (got_scope || got_object)
+ if (got_scope)
tmp_token.yylval.ttype = trrr;
break;
default:
@@ -347,7 +337,7 @@ yylex()
else
lastiddecl = trrr;
got_scope = NULL_TREE;
- /* and fall through to... */
+ /* and fall through to... */
case IDENTIFIER_DEFN:
case TYPENAME:
case TYPENAME_DEFN:
@@ -360,42 +350,49 @@ yylex()
break;
case SCSPEC:
- /* do_aggr needs to check if the previous token was RID_FRIEND,
- so just increment first_token instead of calling consume_token. */
- first_token++;
+ case NEW:
+ /* do_aggr needs to check if the previous token was RID_NEW,
+ so just increment first_token instead of calling consume_token. */
+ ++first_token;
break;
+
case TYPESPEC:
consume_token ();
break;
case AGGR:
- *nth_token(0) = tmp_token;
+ *nth_token (0) = tmp_token;
do_aggr ();
- /* fall through to output... */
+ /* fall through to output... */
case ENUM:
/* Set this again, in case we are rescanning. */
looking_for_typename = 1;
- /* fall through... */
+ /* fall through... */
default:
- consume_token();
+ consume_token ();
}
+ got_object = NULL_TREE;
yylval = tmp_token.yylval;
yychar = tmp_token.yychar;
end_of_file = tmp_token.end_of_file;
#ifdef SPEW_DEBUG
if (spew_debug)
- debug_yychar(yychar);
+ debug_yychar (yychar);
#endif
+
+ if (yychar == PFUNCNAME)
+ yylval.ttype = do_identifier (yylval.ttype, 1);
+
return yychar;
}
/* token[0] == AGGR (struct/union/enum)
- * Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
- * If token[2] == '{' or ':' then it's TYPENAME_DEFN.
- * It's also a definition if it's a forward declaration (as in 'struct Foo;')
- * which we can tell lf token[2] == ';' *and* token[-1] != FRIEND.
- */
+ Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
+ If token[2] == '{' or ':' then it's TYPENAME_DEFN.
+ It's also a definition if it's a forward declaration (as in 'struct Foo;')
+ which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW. */
+
static int
do_aggr ()
{
@@ -408,10 +405,16 @@ do_aggr ()
yc2 = nth_token (2)->yychar;
if (yc2 == ';')
{
- /* It's a forward declaration iff we were not preceded by 'friend'. */
- if (first_token > 0 && nth_token (-1)->yychar == SCSPEC
- && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
- return 0;
+ /* It's a forward declaration iff we were not preceded by
+ 'friend' or `new'. */
+ if (first_token > 0)
+ {
+ if (nth_token (-1)->yychar == SCSPEC
+ && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
+ return 0;
+ if (nth_token (-1)->yychar == NEW)
+ return 0;
+ }
}
else if (yc2 != '{' && yc2 != ':')
return 0;
@@ -434,7 +437,8 @@ do_aggr ()
}
#ifdef SPEW_DEBUG
-/* debug_yychar takes a yychar (token number) value and prints its name. */
+/* debug_yychar takes a yychar (token number) value and prints its name. */
+
static int
debug_yychar (yy)
int yy;
@@ -444,7 +448,7 @@ debug_yychar (yy)
int i;
- if(yy<256) {
+ if (yy<256) {
fprintf (stderr, "<%d: %c >\n", yy, yy);
return 0;
}
diff --git a/gnu/usr.bin/gcc/cp/tree.c b/gnu/usr.bin/gcc/cp/tree.c
index 7fb688ebd90..9d2589fec6d 100644
--- a/gnu/usr.bin/gcc/cp/tree.c
+++ b/gnu/usr.bin/gcc/cp/tree.c
@@ -1,5 +1,5 @@
/* Language-dependent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -26,6 +26,30 @@ Boston, MA 02111-1307, USA. */
#include "cp-tree.h"
#include "flags.h"
#include "rtl.h"
+#ifdef __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free PROTO((void *));
+#endif
+
+extern void compiler_error ();
+
+static tree get_identifier_list PROTO((tree));
+static tree bot_manip PROTO((tree));
+static tree perm_manip PROTO((tree));
+static tree build_cplus_array_type_1 PROTO((tree, tree));
+static void list_hash_add PROTO((int, tree));
+static int list_hash PROTO((tree, tree, tree));
+static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
+ tree));
#define CEIL(x,y) (((x) + (y) - 1) / (y))
@@ -43,17 +67,20 @@ real_lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
- if (ref == current_class_decl && flag_this_is_variable <= 0)
+ if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{
/* preincrements and predecrements are valid lvals, provided
- what they refer to are valid lvals. */
+ what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
+ case UNSAVE_EXPR:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
@@ -74,9 +101,6 @@ real_lvalue_p (ref)
return 1;
break;
- case WITH_CLEANUP_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 0));
-
/* A currently unresolved scope ref. */
case SCOPE_REF:
my_friendly_abort (103);
@@ -106,6 +130,8 @@ real_lvalue_p (ref)
return 0;
}
+/* This differs from real_lvalue_p in that class rvalues are considered
+ lvalues. */
int
lvalue_p (ref)
tree ref;
@@ -116,17 +142,22 @@ lvalue_p (ref)
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
- if (ref == current_class_decl && flag_this_is_variable <= 0)
+ if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0;
switch (TREE_CODE (ref))
{
/* preincrements and predecrements are valid lvals, provided
- what they refer to are valid lvals. */
+ what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
+ case UNSAVE_EXPR:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
@@ -147,9 +178,6 @@ lvalue_p (ref)
return 1;
break;
- case WITH_CLEANUP_EXPR:
- return lvalue_p (TREE_OPERAND (ref, 0));
-
case TARGET_EXPR:
return 1;
@@ -206,44 +234,27 @@ lvalue_or_else (ref, string)
Build an encapsulation of the initialization to perform
and return it so that it can be processed by language-independent
- and language-specific expression expanders.
+ and language-specific expression expanders. */
- If WITH_CLEANUP_P is nonzero, we build a cleanup for this expression.
- Otherwise, cleanups are not built here. For example, when building
- an initialization for a stack slot, since the called function handles
- the cleanup, we would not want to do it here. */
tree
-build_cplus_new (type, init, with_cleanup_p)
+build_cplus_new (type, init)
tree type;
tree init;
- int with_cleanup_p;
{
tree slot;
tree rval;
+ if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != NEW_EXPR)
+ return init;
+
slot = build (VAR_DECL, type);
layout_decl (slot, 0);
rval = build (NEW_EXPR, type,
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
- rval = build (TARGET_EXPR, type, slot, rval, 0);
+ rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
-#if 0
- if (with_cleanup_p && TYPE_NEEDS_DESTRUCTOR (type))
- {
- TREE_OPERAND (rval, 2) = error_mark_node;
- rval = build (WITH_CLEANUP_EXPR, type, rval, 0,
- build_delete (build_pointer_type (type),
- build_unary_op (ADDR_EXPR, slot, 0),
- integer_two_node,
- LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0));
- TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
- }
-#endif
return rval;
}
@@ -258,7 +269,7 @@ break_out_cleanups (exp)
if (TREE_CODE (tmp) == CALL_EXPR
&& TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (tmp)))
- return build_cplus_new (TREE_TYPE (tmp), tmp, 1);
+ return build_cplus_new (TREE_TYPE (tmp), tmp);
while (TREE_CODE (tmp) == NOP_EXPR
|| TREE_CODE (tmp) == CONVERT_EXPR
@@ -269,7 +280,7 @@ break_out_cleanups (exp)
{
TREE_OPERAND (tmp, 0)
= build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
- TREE_OPERAND (tmp, 0), 1);
+ TREE_OPERAND (tmp, 0));
break;
}
else
@@ -299,7 +310,7 @@ break_out_calls (exp)
if (code == CALL_EXPR)
return copy_node (exp);
- /* Don't try and defeat a save_expr, as it should only be done once. */
+ /* Don't try and defeat a save_expr, as it should only be done once. */
if (code == SAVE_EXPR)
return exp;
@@ -372,6 +383,7 @@ break_out_calls (exp)
extern struct obstack *current_obstack;
extern struct obstack permanent_obstack, class_obstack;
extern struct obstack *saveable_obstack;
+extern struct obstack *expression_obstack;
/* Here is how primitive or already-canonicalized types' hash
codes are made. MUST BE CONSISTENT WITH tree.c !!! */
@@ -380,6 +392,7 @@ extern struct obstack *saveable_obstack;
/* Construct, lay out and return the type of methods belonging to class
BASETYPE and whose arguments are described by ARGTYPES and whose values
are described by RETTYPE. If each type exists already, reuse it. */
+
tree
build_cplus_method_type (basetype, rettype, argtypes)
tree basetype, rettype, argtypes;
@@ -418,34 +431,8 @@ build_cplus_method_type (basetype, rettype, argtypes)
return t;
}
-tree
-build_cplus_staticfn_type (basetype, rettype, argtypes)
- tree basetype, rettype, argtypes;
-{
- register tree t;
- int hashcode;
-
- /* Make a node of the sort we want. */
- t = make_node (FUNCTION_TYPE);
-
- TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
- TREE_TYPE (t) = rettype;
-
- TYPE_ARG_TYPES (t) = argtypes;
-
- /* If we already have such a type, use the old one and free this one.
- Note that it also frees up the above cons cell if found. */
- hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
- t = type_hash_canon (hashcode, t);
-
- if (TYPE_SIZE (t) == 0)
- layout_type (t);
-
- return t;
-}
-
-tree
-build_cplus_array_type (elt_type, index_type)
+static tree
+build_cplus_array_type_1 (elt_type, index_type)
tree elt_type;
tree index_type;
{
@@ -462,7 +449,14 @@ build_cplus_array_type (elt_type, index_type)
saveable_obstack = &permanent_obstack;
}
- t = build_array_type (elt_type, index_type);
+ if (processing_template_decl)
+ {
+ t = make_node (ARRAY_TYPE);
+ TREE_TYPE (t) = elt_type;
+ TYPE_DOMAIN (t) = index_type;
+ }
+ else
+ t = build_array_type (elt_type, index_type);
/* Push these needs up so that initialization takes place
more easily. */
@@ -472,6 +466,24 @@ build_cplus_array_type (elt_type, index_type)
saveable_obstack = ambient_saveable_obstack;
return t;
}
+
+tree
+build_cplus_array_type (elt_type, index_type)
+ tree elt_type;
+ tree index_type;
+{
+ tree t;
+ int constp = TYPE_READONLY (elt_type);
+ int volatilep = TYPE_VOLATILE (elt_type);
+ elt_type = TYPE_MAIN_VARIANT (elt_type);
+
+ t = build_cplus_array_type_1 (elt_type, index_type);
+
+ if (constp || volatilep)
+ t = cp_build_type_variant (t, constp, volatilep);
+
+ return t;
+}
/* Make a variant type in the proper way for C/C++, propagating qualifiers
down to the element type of an array. */
@@ -481,15 +493,18 @@ cp_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
+ if (type == error_mark_node)
+ return type;
+
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree real_main_variant = TYPE_MAIN_VARIANT (type);
push_obstacks (TYPE_OBSTACK (real_main_variant),
TYPE_OBSTACK (real_main_variant));
- type = build_cplus_array_type (cp_build_type_variant (TREE_TYPE (type),
- constp, volatilep),
- TYPE_DOMAIN (type));
+ type = build_cplus_array_type_1 (cp_build_type_variant
+ (TREE_TYPE (type), constp, volatilep),
+ TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
make a copy. (TYPE might have come from the hash table and
@@ -503,6 +518,7 @@ cp_build_type_variant (type, constp, volatilep)
TYPE_MAIN_VARIANT (type) = real_main_variant;
pop_obstacks ();
+ return type;
}
return build_type_variant (type, constp, volatilep);
}
@@ -513,6 +529,7 @@ cp_build_type_variant (type, constp, volatilep)
Note that we don't have to worry about having two paths to the
same base type, since this type owns its association list. */
+
void
propagate_binfo_offsets (binfo, offset)
tree binfo;
@@ -594,6 +611,7 @@ propagate_binfo_offsets (binfo, offset)
Returns the maximum number of virtual functions any of the virtual
baseclasses provide. */
+
int
layout_vbasetypes (rec, max)
tree rec;
@@ -618,7 +636,6 @@ layout_vbasetypes (rec, max)
register unsigned const_size = 0;
register tree var_size = 0;
int nonvirtual_const_size;
- tree nonvirtual_var_size;
CLASSTYPE_VBASECLASSES (rec) = vbase_types;
@@ -628,7 +645,6 @@ layout_vbasetypes (rec, max)
var_size = TYPE_SIZE (rec);
nonvirtual_const_size = const_size;
- nonvirtual_var_size = var_size;
while (vbase_types)
{
@@ -736,6 +752,7 @@ layout_vbasetypes (rec, max)
creates a list of base_binfos in TYPE_BINFO (REC) from BINFOS.
Returns list of virtual base classes in a FIELD_DECL chain. */
+
tree
layout_basetypes (rec, binfos)
tree rec, binfos;
@@ -753,7 +770,7 @@ layout_basetypes (rec, binfos)
/* Record size so far is CONST_SIZE + VAR_SIZE bits, where CONST_SIZE is
an integer and VAR_SIZE is a tree expression. If VAR_SIZE is null,
the size is just CONST_SIZE. Naturally we try to avoid using
- VAR_SIZE. And so far, we've been successful. */
+ VAR_SIZE. And so far, we've been successful. */
#if 0
register tree var_size = 0;
#endif
@@ -788,7 +805,7 @@ layout_basetypes (rec, binfos)
class A;
class B: private A { virtual void F(); };
- does not dump core when compiled. */
+ does not dump core when compiled. */
my_friendly_abort (121);
#endif
continue;
@@ -820,13 +837,14 @@ layout_basetypes (rec, binfos)
goto got_it;
}
sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
- decl = build_lang_decl (FIELD_DECL, get_identifier (name),
- build_pointer_type (basetype));
+ decl = build_lang_field_decl (FIELD_DECL, get_identifier (name),
+ build_pointer_type (basetype));
/* If you change any of the below, take a look at all the
other VFIELD_BASEs and VTABLE_BASEs in the code, and change
- them too. */
+ them too. */
DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE);
DECL_VIRTUAL_P (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = rec;
DECL_CLASS_CONTEXT (decl) = rec;
DECL_FCONTEXT (decl) = basetype;
@@ -837,20 +855,18 @@ layout_basetypes (rec, binfos)
BINFO_VPTR_FIELD (base_binfo) = decl;
vbase_decls = decl;
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s: virtual %s'",
- TYPE_NAME_STRING (rec),
- TYPE_NAME_STRING (basetype));
- }
got_it:
/* The space this decl occupies has already been accounted for. */
continue;
}
+ /* 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 (const_size == 0)
offset = integer_zero_node;
else
@@ -859,22 +875,6 @@ layout_basetypes (rec, binfos)
const_size = CEIL (const_size, TYPE_ALIGN (basetype))
* TYPE_ALIGN (basetype);
offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
-
-#if 0
- /* bpk: Disabled this check until someone is willing to
- claim it as theirs and explain exactly what circumstances
- warrant the warning. */
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s:%s %s'",
- TYPE_NAME_STRING (rec),
- TREE_VIA_VIRTUAL (base_binfo) ? " virtual" : "",
- TYPE_NAME_STRING (basetype));
- }
-#endif
}
BINFO_OFFSET (base_binfo) = offset;
if (CLASSTYPE_VSIZE (basetype))
@@ -932,27 +932,27 @@ struct list_hash
and the hash code is computed differently for each of these. */
#define TYPE_HASH_SIZE 59
-struct list_hash *list_hash_table[TYPE_HASH_SIZE];
+static struct list_hash *list_hash_table[TYPE_HASH_SIZE];
/* Compute a hash code for a list (chain of TREE_LIST nodes
with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the
TREE_COMMON slots), by adding the hash codes of the individual entries. */
-int
-list_hash (list)
- tree list;
+static int
+list_hash (purpose, value, chain)
+ tree purpose, value, chain;
{
register int hashcode = 0;
- if (TREE_CHAIN (list))
- hashcode += TYPE_HASH (TREE_CHAIN (list));
+ if (chain)
+ hashcode += TYPE_HASH (chain);
- if (TREE_VALUE (list))
- hashcode += TYPE_HASH (TREE_VALUE (list));
+ if (value)
+ hashcode += TYPE_HASH (value);
else
hashcode += 1007;
- if (TREE_PURPOSE (list))
- hashcode += TYPE_HASH (TREE_PURPOSE (list));
+ if (purpose)
+ hashcode += TYPE_HASH (purpose);
else
hashcode += 1009;
return hashcode;
@@ -961,31 +961,30 @@ list_hash (list)
/* Look in the type hash table for a type isomorphic to TYPE.
If one is found, return it. Otherwise return 0. */
-tree
-list_hash_lookup (hashcode, list)
- int hashcode;
- tree list;
+static tree
+list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+ purpose, value, chain)
+ int hashcode, via_public, via_virtual, via_protected;
+ tree purpose, value, chain;
{
register struct list_hash *h;
+
for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list)
- && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list)
- && TREE_VIA_PROTECTED (h->list) == TREE_VIA_PROTECTED (list)
- && TREE_PURPOSE (h->list) == TREE_PURPOSE (list)
- && TREE_VALUE (h->list) == TREE_VALUE (list)
- && TREE_CHAIN (h->list) == TREE_CHAIN (list))
- {
- my_friendly_assert (TREE_TYPE (h->list) == TREE_TYPE (list), 299);
- return h->list;
- }
+ && TREE_VIA_VIRTUAL (h->list) == via_virtual
+ && TREE_VIA_PUBLIC (h->list) == via_public
+ && TREE_VIA_PROTECTED (h->list) == via_protected
+ && TREE_PURPOSE (h->list) == purpose
+ && TREE_VALUE (h->list) == value
+ && TREE_CHAIN (h->list) == chain)
+ return h->list;
return 0;
}
/* Add an entry to the list-hash-table
for a list TYPE whose hash code is HASHCODE. */
-void
+static void
list_hash_add (hashcode, list)
int hashcode;
tree list;
@@ -1011,30 +1010,8 @@ list_hash_add (hashcode, list)
This function frees the list you pass in if it is a duplicate. */
/* Set to 1 to debug without canonicalization. Never set by program. */
-static int debug_no_list_hash = 0;
-
-tree
-list_hash_canon (hashcode, list)
- int hashcode;
- tree list;
-{
- tree t1;
-
- if (debug_no_list_hash)
- return list;
-
- t1 = list_hash_lookup (hashcode, list);
- if (t1 != 0)
- {
- obstack_free (&class_obstack, list);
- return t1;
- }
- /* If this is a new list, record it for later reuse. */
- list_hash_add (hashcode, list);
-
- return list;
-}
+static int debug_no_list_hash = 0;
tree
hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
@@ -1045,35 +1022,41 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
tree t;
int hashcode;
+ if (! debug_no_list_hash)
+ {
+ hashcode = list_hash (purpose, value, chain);
+ t = list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+ purpose, value, chain);
+ if (t)
+ return t;
+ }
+
current_obstack = &class_obstack;
+
t = tree_cons (purpose, value, chain);
TREE_VIA_PUBLIC (t) = via_public;
TREE_VIA_PROTECTED (t) = via_protected;
TREE_VIA_VIRTUAL (t) = via_virtual;
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
+
+ /* If this is a new list, record it for later reuse. */
+ if (! debug_no_list_hash)
+ list_hash_add (hashcode, t);
+
current_obstack = ambient_obstack;
return t;
}
/* Constructor for hashed lists. */
+
tree
hash_tree_chain (value, chain)
tree value, chain;
{
- struct obstack *ambient_obstack = current_obstack;
- tree t;
- int hashcode;
-
- current_obstack = &class_obstack;
- t = tree_cons (NULL_TREE, value, chain);
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
- current_obstack = ambient_obstack;
- return t;
+ return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */
+
tree
hash_chainon (list1, list2)
tree list1, list2;
@@ -1111,17 +1094,9 @@ get_identifier_list (value)
list = tree_cons (NULL_TREE, value, NULL_TREE);
else
{
- register tree id;
- /* This will return the correct thing for regular types,
- nested types, and templates. Yay! */
- if (TYPE_NESTED_NAME (type))
- id = TYPE_NESTED_NAME (type);
- else
- id = TYPE_IDENTIFIER (type);
-
- if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
+ if (! CLASSTYPE_ID_AS_LIST (type))
CLASSTYPE_ID_AS_LIST (type)
- = perm_tree_cons (NULL_TREE, id, NULL_TREE);
+ = perm_tree_cons (NULL_TREE, TYPE_IDENTIFIER (type), NULL_TREE);
list = CLASSTYPE_ID_AS_LIST (type);
}
}
@@ -1137,7 +1112,8 @@ get_decl_list (value)
if (TREE_CODE (value) == IDENTIFIER_NODE)
list = get_identifier_list (value);
else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value))
+ && TYPE_LANG_SPECIFIC (value)
+ && value == TYPE_MAIN_VARIANT (value))
list = CLASSTYPE_AS_LIST (value);
if (list != NULL_TREE)
@@ -1148,59 +1124,6 @@ get_decl_list (value)
return build_decl_list (NULL_TREE, value);
}
-
-/* Look in the type hash table for a type isomorphic to
- `build_tree_list (NULL_TREE, VALUE)'.
- If one is found, return it. Otherwise return 0. */
-
-tree
-list_hash_lookup_or_cons (value)
- tree value;
-{
- register int hashcode = TYPE_HASH (value);
- register struct list_hash *h;
- struct obstack *ambient_obstack;
- tree list = NULL_TREE;
-
- if (TREE_CODE (value) == IDENTIFIER_NODE)
- list = get_identifier_list (value);
- else if (TREE_CODE (value) == TYPE_DECL
- && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (TREE_TYPE (value)))
- list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value));
- else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value))
- list = CLASSTYPE_AS_LIST (value);
-
- if (list != NULL_TREE)
- {
- my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 302);
- return list;
- }
-
- if (debug_no_list_hash)
- return hash_tree_chain (value, NULL_TREE);
-
- for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
- if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == 0
- && TREE_VIA_PUBLIC (h->list) == 0
- && TREE_VIA_PROTECTED (h->list) == 0
- && TREE_PURPOSE (h->list) == 0
- && TREE_VALUE (h->list) == value)
- {
- my_friendly_assert (TREE_TYPE (h->list) == 0, 303);
- my_friendly_assert (TREE_CHAIN (h->list) == 0, 304);
- return h->list;
- }
-
- ambient_obstack = current_obstack;
- current_obstack = &class_obstack;
- list = build_tree_list (NULL_TREE, value);
- list_hash_add (hashcode, list);
- current_obstack = ambient_obstack;
- return list;
-}
/* Build an association between TYPE and some parameters:
@@ -1282,38 +1205,6 @@ reverse_path (path)
return prev;
}
-tree
-virtual_member (elem, list)
- tree elem;
- tree list;
-{
- tree t;
- tree rval, nval;
-
- for (t = list; t; t = TREE_CHAIN (t))
- if (elem == BINFO_TYPE (t))
- return t;
- rval = 0;
- for (t = list; t; t = TREE_CHAIN (t))
- {
- tree binfos = BINFO_BASETYPES (t);
- int i;
-
- if (binfos != NULL_TREE)
- for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)
- {
- nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
- if (nval)
- {
- if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval))
- my_friendly_abort (104);
- rval = nval;
- }
- }
- }
- return rval;
-}
-
void
debug_binfo (elem)
tree elem;
@@ -1378,20 +1269,6 @@ count_functions (t)
return 0;
}
-/* Like value_member, but for DECL_CHAINs. */
-tree
-decl_value_member (elem, list)
- tree elem, list;
-{
- while (list)
- {
- if (elem == list)
- return list;
- list = DECL_CHAIN (list);
- }
- return NULL_TREE;
-}
-
int
is_overloaded_fn (x)
tree x;
@@ -1399,6 +1276,9 @@ is_overloaded_fn (x)
if (TREE_CODE (x) == FUNCTION_DECL)
return 1;
+ if (TREE_CODE (x) == TEMPLATE_ID_EXPR)
+ return 1;
+
if (TREE_CODE (x) == TREE_LIST
&& (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
|| TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
@@ -1411,9 +1291,12 @@ int
really_overloaded_fn (x)
tree x;
{
+ if (TREE_CODE (x) == TEMPLATE_ID_EXPR)
+ return 1;
+
if (TREE_CODE (x) == TREE_LIST
&& (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
+ || DECL_FUNCTION_TEMPLATE_P (TREE_VALUE (x))))
return 1;
return 0;
@@ -1423,7 +1306,8 @@ tree
get_first_fn (from)
tree from;
{
- if (TREE_CODE (from) == FUNCTION_DECL)
+ if (TREE_CODE (from) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (from))
return from;
my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9);
@@ -1431,51 +1315,6 @@ get_first_fn (from)
return TREE_VALUE (from);
}
-tree
-fnaddr_from_vtable_entry (entry)
- tree entry;
-{
- if (flag_vtable_thunks)
- {
- tree func = entry;
- if (TREE_CODE (func) == ADDR_EXPR)
- func = TREE_OPERAND (func, 0);
- if (TREE_CODE (func) == THUNK_DECL)
- return DECL_INITIAL (func);
- else
- return entry;
- }
- else
- return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
-}
-
-void
-set_fnaddr_from_vtable_entry (entry, value)
- tree entry, value;
-{
- if (flag_vtable_thunks)
- abort ();
- else
- TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry)))) = value;
-}
-
-tree
-function_arg_chain (t)
- tree t;
-{
- return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t)));
-}
-
-int
-promotes_to_aggr_type (t, code)
- tree t;
- enum tree_code code;
-{
- if (TREE_CODE (t) == code)
- t = TREE_TYPE (t);
- return IS_AGGR_TYPE (t);
-}
-
int
is_aggr_type_2 (t1, t2)
tree t1, t2;
@@ -1484,30 +1323,13 @@ is_aggr_type_2 (t1, t2)
return 0;
return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
}
-
-/* Give message using types TYPE1 and TYPE2 as arguments.
- PFN is the function which will print the message;
- S is the format string for PFN to use. */
-void
-message_2_types (pfn, s, type1, type2)
- void (*pfn) ();
- char *s;
- tree type1, type2;
-{
- tree name1 = TYPE_NAME (type1);
- tree name2 = TYPE_NAME (type2);
- if (TREE_CODE (name1) == TYPE_DECL)
- name1 = DECL_NAME (name1);
- if (TREE_CODE (name2) == TYPE_DECL)
- name2 = DECL_NAME (name2);
- (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));
-}
#define PRINT_RING_SIZE 4
char *
-lang_printable_name (decl)
+lang_printable_name (decl, v)
tree decl;
+ int v;
{
static tree decl_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
@@ -1515,9 +1337,10 @@ lang_printable_name (decl)
int i;
/* Only cache functions. */
- if (TREE_CODE (decl) != FUNCTION_DECL
+ if (v < 2
+ || TREE_CODE (decl) != FUNCTION_DECL
|| DECL_LANG_SPECIFIC (decl) == 0)
- return decl_as_string (decl, 1);
+ return lang_decl_name (decl, v);
/* See if this print name is lying around. */
for (i = 0; i < PRINT_RING_SIZE; i++)
@@ -1541,50 +1364,30 @@ lang_printable_name (decl)
if (print_ring[ring_counter])
free (print_ring[ring_counter]);
- {
- int print_ret_type_p
- = (!DECL_CONSTRUCTOR_P (decl)
- && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
-
- char *name = (char *)decl_as_string (decl, print_ret_type_p);
- print_ring[ring_counter] = (char *)malloc (strlen (name) + 1);
- strcpy (print_ring[ring_counter], name);
- decl_ring[ring_counter] = decl;
- }
+ print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
+ decl_ring[ring_counter] = decl;
return print_ring[ring_counter];
}
-/* Comparison function for sorting identifiers in RAISES lists.
- Note that because IDENTIFIER_NODEs are unique, we can sort
- them by address, saving an indirection. */
-static int
-id_cmp (p1, p2)
- tree *p1, *p2;
-{
- return (HOST_WIDE_INT)TREE_VALUE (*p1) - (HOST_WIDE_INT)TREE_VALUE (*p2);
-}
-
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
+
tree
build_exception_variant (type, raises)
tree type;
tree raises;
{
- int i;
tree v = TYPE_MAIN_VARIANT (type);
- tree t, t2, cname;
- tree *a = (tree *)alloca ((list_length (raises)+1) * sizeof (tree));
int constp = TYPE_READONLY (type);
int volatilep = TYPE_VOLATILE (type);
- for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
+ for (; v; v = TYPE_NEXT_VARIANT (v))
{
if (TYPE_READONLY (v) != constp
|| TYPE_VOLATILE (v) != volatilep)
continue;
- /* @@ This should do set equality, not exact match. */
+ /* @@ This should do set equality, not exact match. */
if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
/* List of exceptions raised matches previously found list.
@@ -1594,9 +1397,8 @@ build_exception_variant (type, raises)
}
/* Need to build a new variant. */
- v = copy_node (type);
- TYPE_NEXT_VARIANT (v) = TYPE_NEXT_VARIANT (type);
- TYPE_NEXT_VARIANT (type) = v;
+ v = build_type_copy (type);
+
if (raises && ! TREE_PERMANENT (raises))
{
push_obstacks_nochange ();
@@ -1604,6 +1406,7 @@ build_exception_variant (type, raises)
raises = copy_list (raises);
pop_obstacks ();
}
+
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
}
@@ -1616,9 +1419,8 @@ build_exception_variant (type, raises)
tree
mapcar (t, func)
tree t;
- tree (*func)();
+ tree (*func) PROTO((tree));
{
- enum tree_code code;
tree tmp;
if (t == NULL_TREE)
@@ -1627,7 +1429,7 @@ mapcar (t, func)
if (tmp = func (t), tmp != NULL_TREE)
return tmp;
- switch (code = TREE_CODE (t))
+ switch (TREE_CODE (t))
{
case ERROR_MARK:
return error_mark_node;
@@ -1720,10 +1522,26 @@ mapcar (t, func)
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
+ case ARRAY_REF:
+ case SCOPE_REF:
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+ return t;
+
case CALL_EXPR:
t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+
+ /* tree.def says that operand two is RTL, but
+ build_call_declarator puts trees in there. */
+ if (TREE_OPERAND (t, 2)
+ && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
+ TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
+ else
+ TREE_OPERAND (t, 2) = NULL_TREE;
return t;
case CONVERT_EXPR:
@@ -1739,27 +1557,43 @@ mapcar (t, func)
return t;
case POINTER_TYPE:
- return build_pointer_type (mapcar (TREE_TYPE (t), func));
+ tmp = build_pointer_type (mapcar (TREE_TYPE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case REFERENCE_TYPE:
- return build_reference_type (mapcar (TREE_TYPE (t), func));
+ tmp = build_reference_type (mapcar (TREE_TYPE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case FUNCTION_TYPE:
- return build_function_type (mapcar (TREE_TYPE (t), func),
- mapcar (TYPE_ARG_TYPES (t), func));
+ tmp = build_function_type (mapcar (TREE_TYPE (t), func),
+ mapcar (TYPE_ARG_TYPES (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case ARRAY_TYPE:
- return build_array_type (mapcar (TREE_TYPE (t), func),
- mapcar (TYPE_DOMAIN (t), func));
+ tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func),
+ mapcar (TYPE_DOMAIN (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case INTEGER_TYPE:
- return build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
-
+ tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case OFFSET_TYPE:
- return build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func),
- mapcar (TREE_TYPE (t), func));
+ tmp = build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func),
+ mapcar (TREE_TYPE (t), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
case METHOD_TYPE:
- return build_method_type
- (mapcar (TYPE_METHOD_BASETYPE (t), func),
- build_function_type
- (mapcar (TREE_TYPE (t), func),
- mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func)));
+ tmp = build_cplus_method_type
+ (mapcar (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), func),
+ mapcar (TREE_TYPE (t), func),
+ mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func));
+ return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+
+ case COMPLEX_CST:
+ t = copy_node (t);
+ TREE_REALPART (t) = mapcar (TREE_REALPART (t), func);
+ TREE_IMAGPART (t) = mapcar (TREE_REALPART (t), func);
+ return t;
+
+ case CONSTRUCTOR:
+ t = copy_node (t);
+ CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func);
+ return t;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
@@ -1768,7 +1602,7 @@ mapcar (t, func)
/* else fall through */
/* This list is incomplete, but should suffice for now.
- It is very important that `sorry' does not call
+ It is very important that `sorry' not call
`report_error_function'. That could cause an infinite loop. */
default:
sorry ("initializer contains unrecognized tree code");
@@ -1786,50 +1620,63 @@ perm_manip (t)
{
if (TREE_PERMANENT (t))
return t;
+ /* Support `void f () { extern int i; A<&i> a; }' */
+ if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL)
+ && TREE_PUBLIC (t))
+ return copy_node (t);
return NULL_TREE;
}
/* Assuming T is a node built bottom-up, make it all exist on
permanent obstack, if it is not permanent already. */
+
tree
copy_to_permanent (t)
tree t;
{
register struct obstack *ambient_obstack = current_obstack;
register struct obstack *ambient_saveable_obstack = saveable_obstack;
- int resume;
+ register struct obstack *ambient_expression_obstack = expression_obstack;
if (t == NULL_TREE || TREE_PERMANENT (t))
return t;
saveable_obstack = &permanent_obstack;
current_obstack = saveable_obstack;
- resume = suspend_momentary ();
+ expression_obstack = saveable_obstack;
t = mapcar (t, perm_manip);
- resume_momentary (resume);
current_obstack = ambient_obstack;
saveable_obstack = ambient_saveable_obstack;
+ expression_obstack = ambient_expression_obstack;
return t;
}
+#ifdef GATHER_STATISTICS
+extern int depth_reached;
+#endif
+
void
print_lang_statistics ()
{
- extern struct obstack maybepermanent_obstack;
+ extern struct obstack decl_obstack;
print_obstack_statistics ("class_obstack", &class_obstack);
- print_obstack_statistics ("permanent_obstack", &permanent_obstack);
- print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
+ print_obstack_statistics ("decl_obstack", &decl_obstack);
print_search_statistics ();
print_class_statistics ();
+#ifdef GATHER_STATISTICS
+ fprintf (stderr, "maximum template instantiation depth reached: %d\n",
+ depth_reached);
+#endif
}
/* This is used by the `assert' macro. It is provided in libgcc.a,
which `cc' doesn't know how to link. Note that the C++ front-end
no longer actually uses the `assert' macro (instead, it calls
my_friendly_assert). But all of the back-end files still need this. */
+
void
__eprintf (string, expression, line, filename)
#ifdef __STDC__
@@ -1849,8 +1696,9 @@ __eprintf (string, expression, line, filename)
abort ();
}
-/* Return, as an INTEGER_CST node, the number of elements for
- TYPE (which is an ARRAY_TYPE). This counts only elements of the top array. */
+/* Return, as an INTEGER_CST node, the number of elements for TYPE
+ (which is an ARRAY_TYPE). This counts only elements of the top
+ array. */
tree
array_type_nelts_top (type)
@@ -1861,9 +1709,9 @@ array_type_nelts_top (type)
integer_one_node));
}
-/* Return, as an INTEGER_CST node, the number of elements for
- TYPE (which is an ARRAY_TYPE). This one is a recursive count of all
- ARRAY_TYPEs that are clumped together. */
+/* Return, as an INTEGER_CST node, the number of elements for TYPE
+ (which is an ARRAY_TYPE). This one is a recursive count of all
+ ARRAY_TYPEs that are clumped together. */
tree
array_type_nelts_total (type)
@@ -1888,12 +1736,26 @@ bot_manip (t)
if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t))
return t;
else if (TREE_CODE (t) == TARGET_EXPR)
- return build_cplus_new (TREE_TYPE (t),
- break_out_target_exprs (TREE_OPERAND (t, 1)), 0);
+ {
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == NEW_EXPR)
+ {
+ mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
+ return build_cplus_new
+ (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
+ }
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t));
+ layout_decl (TREE_OPERAND (t, 0), 0);
+ return t;
+ }
+ else if (TREE_CODE (t) == CALL_EXPR)
+ mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+
return NULL_TREE;
}
/* Actually, we'll just clean out the target exprs for the moment. */
+
tree
break_out_target_exprs (t)
tree t;
@@ -1901,95 +1763,356 @@ break_out_target_exprs (t)
return mapcar (t, bot_manip);
}
+/* Obstack used for allocating nodes in template function and variable
+ definitions. */
+
+/* Similar to `build_nt', except we build
+ on the permanent_obstack, regardless. */
+
tree
-unsave_expr (expr)
- tree expr;
+build_min_nt VPROTO((enum tree_code code, ...))
{
- tree t;
+#ifndef __STDC__
+ enum tree_code code;
+#endif
+ register struct obstack *ambient_obstack = expression_obstack;
+ va_list p;
+ register tree t;
+ register int length;
+ register int i;
+
+ VA_START (p, code);
+
+#ifndef __STDC__
+ code = va_arg (p, enum tree_code);
+#endif
+
+ expression_obstack = &permanent_obstack;
+
+ t = make_node (code);
+ length = tree_code_length[(int) code];
+ TREE_COMPLEXITY (t) = lineno;
- t = build1 (UNSAVE_EXPR, TREE_TYPE (expr), expr);
- TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
+ for (i = 0; i < length; i++)
+ {
+ tree x = va_arg (p, tree);
+ TREE_OPERAND (t, i) = copy_to_permanent (x);
+ }
+
+ va_end (p);
+ expression_obstack = ambient_obstack;
return t;
}
-/* Modify a tree in place so that all the evaluate only once things
- are cleared out. Return the EXPR given. */
+/* Similar to `build', except we build
+ on the permanent_obstack, regardless. */
+
tree
-unsave_expr_now (expr)
- tree expr;
+build_min VPROTO((enum tree_code code, tree tt, ...))
{
+#ifndef __STDC__
enum tree_code code;
+ tree tt;
+#endif
+ register struct obstack *ambient_obstack = expression_obstack;
+ va_list p;
+ register tree t;
+ register int length;
register int i;
- if (expr == NULL_TREE)
- return expr;
+ VA_START (p, tt);
+
+#ifndef __STDC__
+ code = va_arg (p, enum tree_code);
+ tt = va_arg (p, tree);
+#endif
+
+ expression_obstack = &permanent_obstack;
+
+ t = make_node (code);
+ length = tree_code_length[(int) code];
+ TREE_TYPE (t) = tt;
+ TREE_COMPLEXITY (t) = lineno;
+
+ for (i = 0; i < length; i++)
+ {
+ tree x = va_arg (p, tree);
+ TREE_OPERAND (t, i) = copy_to_permanent (x);
+ }
+
+ va_end (p);
+ expression_obstack = ambient_obstack;
+ return t;
+}
+
+/* Same as `tree_cons' but make a permanent object. */
+
+tree
+min_tree_cons (purpose, value, chain)
+ tree purpose, value, chain;
+{
+ register tree node;
+ register struct obstack *ambient_obstack = current_obstack;
+ current_obstack = &permanent_obstack;
+
+ node = tree_cons (copy_to_permanent (purpose),
+ copy_to_permanent (value), chain);
+ current_obstack = ambient_obstack;
+ return node;
+}
+
+tree
+get_type_decl (t)
+ tree t;
+{
+ if (TREE_CODE (t) == IDENTIFIER_NODE)
+ return identifier_typedecl_value (t);
+ if (TREE_CODE (t) == TYPE_DECL)
+ return t;
+ if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
+ return TYPE_STUB_DECL (t);
+
+ my_friendly_abort (42);
+}
+
+int
+can_free (obstack, t)
+ struct obstack *obstack;
+ tree t;
+{
+ int size;
+
+ if (TREE_CODE (t) == TREE_VEC)
+ size = (TREE_VEC_LENGTH (t)-1) * sizeof (tree) + sizeof (struct tree_vec);
+ else
+ my_friendly_abort (42);
+
+#define ROUND(x) ((x + obstack_alignment_mask (obstack)) \
+ & ~ obstack_alignment_mask (obstack))
+ if ((char *)t + ROUND (size) == obstack_next_free (obstack))
+ return 1;
+#undef ROUND
+
+ return 0;
+}
+
+/* Return first vector element whose BINFO_TYPE is ELEM.
+ Return 0 if ELEM is not in VEC. VEC may be NULL_TREE. */
+
+tree
+vec_binfo_member (elem, vec)
+ tree elem, vec;
+{
+ int i;
+
+ if (vec)
+ for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
+ if (comptypes (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i)), 1))
+ return TREE_VEC_ELT (vec, i);
+
+ return NULL_TREE;
+}
+
+/* Kludge around the fact that DECL_CONTEXT for virtual functions returns
+ the wrong thing for decl_function_context. Hopefully the uses in the
+ backend won't matter, since we don't need a static chain for local class
+ methods. FIXME! */
+
+tree
+hack_decl_function_context (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FUNCTION_MEMBER_P (decl))
+ return decl_function_context (TYPE_MAIN_DECL (DECL_CLASS_CONTEXT (decl)));
+ return decl_function_context (decl);
+}
+
+/* Return truthvalue of whether T1 is the same tree structure as T2.
+ Return 1 if they are the same.
+ Return 0 if they are understandably different.
+ Return -1 if either contains tree structure not understood by
+ this function. */
+
+int
+cp_tree_equal (t1, t2)
+ tree t1, t2;
+{
+ register enum tree_code code1, code2;
+ int cmp;
- code = TREE_CODE (expr);
- switch (code)
+ if (t1 == t2)
+ return 1;
+ if (t1 == 0 || t2 == 0)
+ return 0;
+
+ code1 = TREE_CODE (t1);
+ code2 = TREE_CODE (t2);
+
+ if (code1 == NOP_EXPR || code1 == CONVERT_EXPR || code1 == NON_LVALUE_EXPR)
+ if (code2 == NOP_EXPR || code2 == CONVERT_EXPR || code2 == NON_LVALUE_EXPR)
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ else
+ return cp_tree_equal (TREE_OPERAND (t1, 0), t2);
+ else if (code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ || code2 == NON_LVALUE_EXPR)
+ return cp_tree_equal (t1, TREE_OPERAND (t2, 0));
+
+ if (code1 != code2)
+ return 0;
+
+ switch (code1)
{
+ case INTEGER_CST:
+ return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
+ && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+
+ case REAL_CST:
+ return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
+
+ case STRING_CST:
+ return TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
+ && !bcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
+ TREE_STRING_LENGTH (t1));
+
+ case CONSTRUCTOR:
+ abort ();
+
case SAVE_EXPR:
- SAVE_EXPR_RTL (expr) = NULL_RTX;
- break;
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+
+ case CALL_EXPR:
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return simple_cst_list_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
case TARGET_EXPR:
- sorry ("TARGET_EXPR reused inside UNSAVE_EXPR");
- break;
-
- case RTL_EXPR:
- warning ("RTL_EXPR reused inside UNSAVE_EXPR");
- RTL_EXPR_SEQUENCE (expr) = NULL_RTX;
- break;
+ /* Special case: if either target is an unallocated VAR_DECL,
+ it means that it's going to be unified with whatever the
+ TARGET_EXPR is really supposed to initialize, so treat it
+ as being equivalent to anything. */
+ if ((TREE_CODE (TREE_OPERAND (t1, 0)) == VAR_DECL
+ && DECL_NAME (TREE_OPERAND (t1, 0)) == NULL_TREE
+ && DECL_RTL (TREE_OPERAND (t1, 0)) == 0)
+ || (TREE_CODE (TREE_OPERAND (t2, 0)) == VAR_DECL
+ && DECL_NAME (TREE_OPERAND (t2, 0)) == NULL_TREE
+ && DECL_RTL (TREE_OPERAND (t2, 0)) == 0))
+ cmp = 1;
+ else
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
- case CALL_EXPR:
- CALL_EXPR_RTL (expr) = NULL_RTX;
- if (TREE_OPERAND (expr, 1)
- && TREE_CODE (TREE_OPERAND (expr, 1)) == TREE_LIST)
- {
- tree exp = TREE_OPERAND (expr, 1);
- while (exp)
- {
- unsave_expr_now (TREE_VALUE (exp));
- exp = TREE_CHAIN (exp);
- }
- }
- break;
-
case WITH_CLEANUP_EXPR:
- warning ("WITH_CLEANUP_EXPR reused inside UNSAVE_EXPR");
- RTL_EXPR_RTL (expr) = NULL_RTX;
+ cmp = cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ if (cmp <= 0)
+ return cmp;
+ return cp_tree_equal (TREE_OPERAND (t1, 2), TREE_OPERAND (t1, 2));
+
+ case COMPONENT_REF:
+ if (TREE_OPERAND (t1, 1) == TREE_OPERAND (t2, 1))
+ return cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
+ return 0;
+
+ case VAR_DECL:
+ case PARM_DECL:
+ case CONST_DECL:
+ case FUNCTION_DECL:
+ return 0;
+
+ case TEMPLATE_CONST_PARM:
+ return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
+ && TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
+
+ case SIZEOF_EXPR:
+ if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
+ return 0;
+ if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't')
+ return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
break;
}
- switch (TREE_CODE_CLASS (code))
+ switch (TREE_CODE_CLASS (code1))
{
- case 'c': /* a constant */
- case 't': /* a type node */
- case 'x': /* something random, like an identifier or an ERROR_MARK. */
- case 'd': /* A decl node */
- case 'b': /* A block node */
- return expr;
+ int i;
+ case '1':
+ case '2':
+ case '<':
+ case 'e':
+ case 'r':
+ case 's':
+ cmp = 1;
+ for (i=0; i<tree_code_length[(int) code1]; ++i)
+ {
+ cmp = cp_tree_equal (TREE_OPERAND (t1, i), TREE_OPERAND (t2, i));
+ if (cmp <= 0)
+ return cmp;
+ }
+ return cmp;
+ }
- case 'e': /* an expression */
- case 'r': /* a reference */
- case 's': /* an expression with side effects */
- case '<': /* a comparison expression */
- case '2': /* a binary arithmetic expression */
- case '1': /* a unary arithmetic expression */
- for (i = tree_code_length[(int) code] - 1; i >= 0; i--)
- unsave_expr_now (TREE_OPERAND (expr, i));
- return expr;
+ return -1;
+}
- default:
- my_friendly_abort (999);
- }
+/* Similar to make_tree_vec, but build on a temporary obstack. */
+
+tree
+make_temp_vec (len)
+ int len;
+{
+ register tree node;
+ register struct obstack *ambient_obstack = current_obstack;
+ current_obstack = expression_obstack;
+ node = make_tree_vec (len);
+ current_obstack = ambient_obstack;
+ return node;
+}
+
+void
+push_expression_obstack ()
+{
+ push_obstacks_nochange ();
+ current_obstack = expression_obstack;
}
-/* Since cleanup may have SAVE_EXPRs in it, we protect it with an
- UNSAVE_EXPR as the backend cannot yet handle SAVE_EXPRs in cleanups
- by itself. */
+/* The type of ARG when used as an lvalue. */
+
+tree
+lvalue_type (arg)
+ tree arg;
+{
+ return cp_build_type_variant
+ (TREE_TYPE (arg), TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
+}
+
+/* The type of ARG for printing error messages; denote lvalues with
+ reference types. */
+
+tree
+error_type (arg)
+ tree arg;
+{
+ tree type = TREE_TYPE (arg);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ ;
+ else if (real_lvalue_p (arg))
+ type = build_reference_type (lvalue_type (arg));
+ else if (IS_AGGR_TYPE (type))
+ type = lvalue_type (arg);
+
+ return type;
+}
+
+/* Does FUNCTION use a variable-length argument list? */
+
int
-cp_expand_decl_cleanup (decl, cleanup)
- tree decl, cleanup;
+varargs_function_p (function)
+ tree function;
{
- return expand_decl_cleanup (decl, unsave_expr (cleanup));
+ tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+ for (; parm; parm = TREE_CHAIN (parm))
+ if (TREE_VALUE (parm) == void_type_node)
+ return 0;
+ return 1;
}
diff --git a/gnu/usr.bin/gcc/cp/typeck.c b/gnu/usr.bin/gcc/cp/typeck.c
index 9247bf084d8..304e92d3f7f 100644
--- a/gnu/usr.bin/gcc/cp/typeck.c
+++ b/gnu/usr.bin/gcc/cp/typeck.c
@@ -1,5 +1,5 @@
/* Build expressions with type checking for C++ compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-96, 1997 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -29,9 +29,6 @@ Boston, MA 02111-1307, USA. */
and to process initializations in declarations (since they work
like a strange sort of assignment). */
-extern void error ();
-extern void warning ();
-
#include "config.h"
#include <stdio.h>
#include "tree.h"
@@ -39,20 +36,32 @@ extern void warning ();
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
+#include "expr.h"
-int mark_addressable ();
-static tree convert_for_assignment ();
-/* static */ tree convert_for_initialization ();
-extern tree shorten_compare ();
-extern void binary_op_error ();
-static tree pointer_int_sum ();
-static tree pointer_diff ();
-static tree convert_sequence ();
-/* static */ tree unary_complex_lvalue ();
-static tree get_delta_difference PROTO((tree, tree, int));
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
-extern rtx original_result_rtx;
-extern int warn_synth;
+extern void compiler_error ();
+
+static tree convert_for_assignment PROTO((tree, tree, char*, tree,
+ int));
+static tree pointer_int_sum PROTO((enum tree_code, tree, tree));
+static tree rationalize_conditional_expr PROTO((enum tree_code, tree));
+static int comp_target_parms PROTO((tree, tree, int));
+static int comp_ptr_ttypes_real PROTO((tree, tree, int));
+static int comp_ptr_ttypes_const PROTO((tree, tree));
+static int comp_ptr_ttypes_reinterpret PROTO((tree, tree));
+static int comp_array_types PROTO((int (*) (tree, tree, int), tree,
+ tree, int));
+static tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, tree));
+static tree common_base_type PROTO((tree, tree));
+static tree convert_sequence PROTO((tree, tree));
+static tree lookup_anon_field PROTO((tree, tree));
+static tree pointer_diff PROTO((tree, tree));
+static tree qualify_type PROTO((tree, tree));
+static tree expand_target_expr PROTO((tree));
+static tree get_delta_difference PROTO((tree, tree, int));
/* Return the target type of TYPE, which meas return T for:
T*, T&, T[], T (...), and otherwise, just T. */
@@ -79,7 +88,12 @@ tree
require_complete_type (value)
tree value;
{
- tree type = TREE_TYPE (value);
+ tree type;
+
+ if (processing_template_decl)
+ return value;
+
+ type = TREE_TYPE (value);
/* First, detect a valid value with a complete type. */
if (TYPE_SIZE (type) != 0
@@ -93,23 +107,53 @@ require_complete_type (value)
not been laid out. Try to avoid an error by interpreting
it as this->X::Y, if reasonable. */
if (TREE_CODE (value) == OFFSET_REF
- && C_C_D != 0
- && TREE_OPERAND (value, 0) == C_C_D)
+ && current_class_ref != 0
+ && TREE_OPERAND (value, 0) == current_class_ref)
{
tree base, member = TREE_OPERAND (value, 1);
tree basetype = TYPE_OFFSET_BASETYPE (type);
my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);
- base = convert_pointer_to (basetype, current_class_decl);
+ base = convert_pointer_to (basetype, current_class_ptr);
value = build (COMPONENT_REF, TREE_TYPE (member),
build_indirect_ref (base, NULL_PTR), member);
return require_complete_type (value);
}
+ if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ {
+ instantiate_class_template (TYPE_MAIN_VARIANT (type));
+ if (TYPE_SIZE (type) != 0)
+ return value;
+ }
+
incomplete_type_error (value, type);
return error_mark_node;
}
+tree
+complete_type (type)
+ tree type;
+{
+ if (type == error_mark_node || TYPE_SIZE (type) != NULL_TREE)
+ ;
+ else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
+ {
+ tree t = complete_type (TREE_TYPE (type));
+ if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl)
+ layout_type (type);
+ TYPE_NEEDS_CONSTRUCTING (type)
+ = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
+ TYPE_NEEDS_DESTRUCTOR (type)
+ = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t));
+ }
+ else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type))
+ instantiate_class_template (TYPE_MAIN_VARIANT (type));
+
+ return type;
+}
+
/* Return truthvalue of whether type of EXP is instantiated. */
+
int
type_unknown_p (exp)
tree exp;
@@ -121,6 +165,7 @@ type_unknown_p (exp)
}
/* Return truthvalue of whether T is function (or pfn) type. */
+
int
fntype_p (t)
tree t;
@@ -134,6 +179,7 @@ fntype_p (t)
/* Do `exp = require_instantiated_type (type, exp);' to make sure EXP
does not have an uninstantiated type.
TYPE is type to instantiate with, if uninstantiated. */
+
tree
require_instantiated_type (type, exp, errval)
tree type, exp, errval;
@@ -309,9 +355,32 @@ common_type (t1, t2)
if (TREE_CODE (t2) == ENUMERAL_TYPE)
t2 = type_for_size (TYPE_PRECISION (t2), 1);
+ if (TYPE_PTRMEMFUNC_P (t1))
+ t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
+ if (TYPE_PTRMEMFUNC_P (t2))
+ t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+
code1 = TREE_CODE (t1);
code2 = TREE_CODE (t2);
+ /* If one type is complex, form the common type of the non-complex
+ components, then make that complex. Use T1 or T2 if it is the
+ required type. */
+ if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
+ {
+ tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
+ tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
+ tree subtype = common_type (subtype1, subtype2);
+
+ if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
+ return build_type_attribute_variant (t1, attributes);
+ else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
+ return build_type_attribute_variant (t2, attributes);
+ else
+ return build_type_attribute_variant (build_complex_type (subtype),
+ attributes);
+ }
+
switch (code1)
{
case INTEGER_TYPE:
@@ -382,6 +451,10 @@ common_type (t1, t2)
target = tt1;
else if (tt1 == void_type_node || tt2 == void_type_node)
target = void_type_node;
+ else if (tt1 == unknown_type_node)
+ target = tt2;
+ else if (tt2 == unknown_type_node)
+ target = tt1;
else
target = common_type (tt1, tt2);
@@ -397,15 +470,6 @@ common_type (t1, t2)
return t1;
}
-#if 0
- case POINTER_TYPE:
- t1 = build_pointer_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
- return build_type_attribute_variant (t1, attributes);
-
- case REFERENCE_TYPE:
- t1 = build_reference_type (common_type (TREE_TYPE (t1), TREE_TYPE (t2)));
- return build_type_attribute_variant (t1, attributes);
-#endif
case ARRAY_TYPE:
{
@@ -416,7 +480,8 @@ common_type (t1, t2)
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2))
return build_type_attribute_variant (t2, attributes);
/* Merge the element types, and have a size if either arg has one. */
- t1 = build_cplus_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
+ t1 = build_cplus_array_type
+ (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
return build_type_attribute_variant (t1, attributes);
}
@@ -480,7 +545,8 @@ common_type (t1, t2)
tree b1 = TYPE_OFFSET_BASETYPE (t1);
tree b2 = TYPE_OFFSET_BASETYPE (t2);
- if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))
+ if (comptypes (b1, b2, 1)
+ || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
basetype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t2)));
else
{
@@ -511,7 +577,8 @@ common_type (t1, t2)
tree b1 = TYPE_OFFSET_BASETYPE (t1);
tree b2 = TYPE_OFFSET_BASETYPE (t2);
- if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))
+ if (comptypes (b1, b2, 1)
+ || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)))
return build_type_attribute_variant (t2, attributes);
else if (binfo_or_else (b2, b1))
return build_type_attribute_variant (t1, attributes);
@@ -524,17 +591,17 @@ common_type (t1, t2)
}
/* Return 1 if TYPE1 and TYPE2 raise the same exceptions. */
+
int
-compexcepttypes (t1, t2, strict)
+compexcepttypes (t1, t2)
tree t1, t2;
- int strict;
{
return TYPE_RAISES_EXCEPTIONS (t1) == TYPE_RAISES_EXCEPTIONS (t2);
}
static int
comp_array_types (cmp, t1, t2, strict)
- register int (*cmp)();
+ register int (*cmp) PROTO((tree, tree, int));
tree t1, t2;
int strict;
{
@@ -587,6 +654,7 @@ comp_array_types (cmp, t1, t2, strict)
pointer to a base classes. These allowances do not commute. In this
case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to
be the derived class. */
+
int
comptypes (type1, type2, strict)
tree type1, type2;
@@ -620,6 +688,11 @@ comptypes (type1, type2, strict)
return 1;
}
+ if (TYPE_PTRMEMFUNC_P (t1))
+ t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
+ if (TYPE_PTRMEMFUNC_P (t2))
+ t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
+
/* Different classes of types can't be compatible. */
if (TREE_CODE (t1) != TREE_CODE (t2))
@@ -652,13 +725,15 @@ comptypes (type1, type2, strict)
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return 1;
-#ifdef COMP_TYPE_ATTRIBUTES
+ /* ??? COMP_TYPE_ATTRIBUTES is currently useless for variables as each
+ attribute is its own main variant (`val' will remain 0). */
+#ifndef COMP_TYPE_ATTRIBUTES
+#define COMP_TYPE_ATTRIBUTES(t1,t2) 1
+#endif
+
+ /* 1 if no need for warning yet, 2 if warning cause has been seen. */
if (! (attrval = COMP_TYPE_ATTRIBUTES (t1, t2)))
return 0;
-#else
- /* 1 if no need for warning yet, 2 if warning cause has been seen. */
- attrval = 1;
-#endif
/* 1 if no need for warning yet, 2 if warning cause has been seen. */
val = 0;
@@ -667,6 +742,28 @@ comptypes (type1, type2, strict)
{
case RECORD_TYPE:
case UNION_TYPE:
+ if (CLASSTYPE_TEMPLATE_INFO (t1) && CLASSTYPE_TEMPLATE_INFO (t2)
+ && CLASSTYPE_TI_TEMPLATE (t1) == CLASSTYPE_TI_TEMPLATE (t2))
+ {
+ int i = TREE_VEC_LENGTH (CLASSTYPE_TI_ARGS (t1));
+ tree *p1 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t1), 0);
+ tree *p2 = &TREE_VEC_ELT (CLASSTYPE_TI_ARGS (t2), 0);
+
+ while (i--)
+ {
+ if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
+ {
+ if (! comptypes (p1[i], p2[i], 1))
+ return 0;
+ }
+ else
+ {
+ if (simple_cst_equal (p1[i], p2[i]) <= 0)
+ return 0;
+ }
+ }
+ return 1;
+ }
if (strict <= 0)
goto look_hard;
return 0;
@@ -678,7 +775,7 @@ comptypes (type1, type2, strict)
break;
case METHOD_TYPE:
- if (! compexcepttypes (t1, t2, strict))
+ if (! compexcepttypes (t1, t2))
return 0;
/* This case is anti-symmetrical!
@@ -706,7 +803,7 @@ comptypes (type1, type2, strict)
{
int rval;
look_hard:
- rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2);
+ rval = t1 == t2 || DERIVED_FROM_P (t1, t2);
if (rval)
{
@@ -715,7 +812,7 @@ comptypes (type1, type2, strict)
}
if (strict < 0)
{
- val = UNIQUELY_DERIVED_FROM_P (t2, t1);
+ val = DERIVED_FROM_P (t2, t1);
break;
}
}
@@ -726,7 +823,7 @@ comptypes (type1, type2, strict)
break;
case FUNCTION_TYPE:
- if (! compexcepttypes (t1, t2, strict))
+ if (! compexcepttypes (t1, t2))
return 0;
val = ((TREE_TYPE (t1) == TREE_TYPE (t2)
@@ -740,31 +837,13 @@ comptypes (type1, type2, strict)
break;
case TEMPLATE_TYPE_PARM:
- return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2);
+ return TEMPLATE_TYPE_IDX (t1) == TEMPLATE_TYPE_IDX (t2)
+ && TEMPLATE_TYPE_LEVEL (t1) == TEMPLATE_TYPE_LEVEL (t2);
- case UNINSTANTIATED_P_TYPE:
- if (UPT_TEMPLATE (t1) != UPT_TEMPLATE (t2))
+ case TYPENAME_TYPE:
+ if (TYPE_IDENTIFIER (t1) != TYPE_IDENTIFIER (t2))
return 0;
- {
- int i = TREE_VEC_LENGTH (UPT_PARMS (t1));
- tree *p1 = &TREE_VEC_ELT (UPT_PARMS (t1), 0);
- tree *p2 = &TREE_VEC_ELT (UPT_PARMS (t2), 0);
-
- while (i--)
- {
- if (TREE_CODE_CLASS (TREE_CODE (p1[i])) == 't')
- {
- if (! comptypes (p1[i], p2[i], 1))
- return 0;
- }
- else
- {
- if (simple_cst_equal (p1[i], p2[i]) <= 0)
- return 0;
- }
- }
- }
- return 1;
+ return comptypes (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2), 1);
}
return attrval == 2 && val == 1 ? 2 : val;
}
@@ -796,7 +875,10 @@ comp_target_types (ttl, ttr, nptrs)
if (nptrs > 0)
{
- if (TREE_CODE (ttl) == VOID_TYPE
+ if (TREE_CODE (ttl) == UNKNOWN_TYPE
+ || TREE_CODE (ttr) == UNKNOWN_TYPE)
+ return 1;
+ else if (TREE_CODE (ttl) == VOID_TYPE
&& TREE_CODE (ttr) != FUNCTION_TYPE
&& TREE_CODE (ttr) != METHOD_TYPE
&& TREE_CODE (ttr) != OFFSET_TYPE)
@@ -892,11 +974,12 @@ comp_target_types (ttl, ttr, nptrs)
/* If two types share a common base type, return that basetype.
If there is not a unique most-derived base type, this function
returns ERROR_MARK_NODE. */
-tree
+
+static tree
common_base_type (tt1, tt2)
tree tt1, tt2;
{
- tree best = NULL_TREE, tmp;
+ tree best = NULL_TREE;
int i;
/* If one is a baseclass of another, that's good enough. */
@@ -905,15 +988,6 @@ common_base_type (tt1, tt2)
if (UNIQUELY_DERIVED_FROM_P (tt2, tt1))
return tt2;
-#if 0
- /* If they share a virtual baseclass, that's good enough. */
- for (tmp = CLASSTYPE_VBASECLASSES (tt1); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (binfo_member (BINFO_TYPE (tmp), CLASSTYPE_VBASECLASSES (tt2)))
- return BINFO_TYPE (tmp);
- }
-#endif
-
/* Otherwise, try to find a unique baseclass of TT1
that is shared by TT2, and follow that down. */
for (i = CLASSTYPE_N_BASECLASSES (tt1)-1; i >= 0; i--)
@@ -960,6 +1034,7 @@ common_base_type (tt1, tt2)
C++: See comment above about TYPE1, TYPE2, STRICT.
If STRICT == 3, it means checking is strict, but do not compare
default parameter values. */
+
int
compparms (parms1, parms2, strict)
tree parms1, parms2;
@@ -998,17 +1073,6 @@ compparms (parms1, parms2, strict)
return t2 == void_list_node && TREE_PURPOSE (t1);
return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);
}
-#if 0
- /* Default parms are not part of the type of a function. */
- if (strict != 3 && TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
- {
- int cmp = simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2));
- if (cmp < 0)
- my_friendly_abort (113);
- if (cmp == 0)
- return 0;
- }
-#endif
t1 = TREE_CHAIN (t1);
t2 = TREE_CHAIN (t2);
@@ -1017,7 +1081,8 @@ compparms (parms1, parms2, strict)
/* This really wants return whether or not parameter type lists
would make their owning functions assignment compatible or not. */
-int
+
+static int
comp_target_parms (parms1, parms2, strict)
tree parms1, parms2;
int strict;
@@ -1096,12 +1161,6 @@ comp_target_parms (parms1, parms2, strict)
}
if (strict != 0)
return 0;
-#if 0
- /* What good do these cases do? */
- if (strict == 0)
- return p2 == void_type_node && TREE_PURPOSE (t1);
- return TREE_PURPOSE (t1) || TREE_PURPOSE (t2);
-#endif
}
/* Target types are compatible--just make sure that if
we use parameter lists, that they are ok as well. */
@@ -1145,10 +1204,10 @@ self_promoting_args_p (parms)
if (TREE_CHAIN (t) == 0 && type != void_type_node)
return 0;
- if (TYPE_MAIN_VARIANT (type) == float_type_node)
+ if (type == 0)
return 0;
- if (type == 0)
+ if (TYPE_MAIN_VARIANT (type) == float_type_node)
return 0;
if (C_PROMOTING_INTEGER_TYPE_P (type))
@@ -1176,7 +1235,16 @@ unsigned_type (type)
return long_unsigned_type_node;
if (type1 == long_long_integer_type_node)
return long_long_unsigned_type_node;
- return type;
+ if (type1 == intDI_type_node)
+ return unsigned_intDI_type_node;
+ if (type1 == intSI_type_node)
+ return unsigned_intSI_type_node;
+ if (type1 == intHI_type_node)
+ return unsigned_intHI_type_node;
+ if (type1 == intQI_type_node)
+ return unsigned_intQI_type_node;
+
+ return signed_or_unsigned_type (1, type);
}
/* Return a signed type the same as TYPE in other respects. */
@@ -1196,7 +1264,16 @@ signed_type (type)
return long_integer_type_node;
if (type1 == long_long_unsigned_type_node)
return long_long_integer_type_node;
- return type;
+ if (type1 == unsigned_intDI_type_node)
+ return intDI_type_node;
+ if (type1 == unsigned_intSI_type_node)
+ return intSI_type_node;
+ if (type1 == unsigned_intHI_type_node)
+ return intHI_type_node;
+ if (type1 == unsigned_intQI_type_node)
+ return intQI_type_node;
+
+ return signed_or_unsigned_type (0, type);
}
/* Return a type the same as TYPE except unsigned or
@@ -1207,8 +1284,10 @@ signed_or_unsigned_type (unsignedp, type)
int unsignedp;
tree type;
{
- if (! INTEGRAL_TYPE_P (type))
+ if (! INTEGRAL_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;
if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
@@ -1223,6 +1302,8 @@ signed_or_unsigned_type (unsignedp, type)
return type;
}
+/* Compute the value of the `sizeof' operator. */
+
tree
c_sizeof (type)
tree type;
@@ -1230,6 +1311,9 @@ c_sizeof (type)
enum tree_code code = TREE_CODE (type);
tree t;
+ if (processing_template_decl)
+ return build_min (SIZEOF_EXPR, sizetype, type);
+
if (code == FUNCTION_TYPE)
{
if (pedantic || warn_pointer_arith)
@@ -1274,9 +1358,9 @@ c_sizeof (type)
return size_int (0);
}
- if (TYPE_SIZE (type) == 0)
+ if (TYPE_SIZE (complete_type (type)) == 0)
{
- error ("`sizeof' applied to an incomplete type");
+ cp_error ("`sizeof' applied to incomplete type `%T'", type);
return size_int (0);
}
@@ -1290,6 +1374,36 @@ c_sizeof (type)
}
tree
+expr_sizeof (e)
+ tree e;
+{
+ if (processing_template_decl)
+ return build_min (SIZEOF_EXPR, sizetype, e);
+
+ if (TREE_CODE (e) == COMPONENT_REF
+ && DECL_BIT_FIELD (TREE_OPERAND (e, 1)))
+ error ("sizeof applied to a bit-field");
+ /* ANSI says arrays and functions are converted inside comma.
+ But we can't really convert them in build_compound_expr
+ because that would break commas in lvalues.
+ So do the conversion here if operand was a comma. */
+ if (TREE_CODE (e) == COMPOUND_EXPR
+ && (TREE_CODE (TREE_TYPE (e)) == ARRAY_TYPE
+ || TREE_CODE (TREE_TYPE (e)) == FUNCTION_TYPE))
+ e = default_conversion (e);
+ else if (TREE_CODE (e) == TREE_LIST)
+ {
+ tree t = TREE_VALUE (e);
+ if (t != NULL_TREE
+ && ((TREE_TYPE (t)
+ && TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+ || is_overloaded_fn (t)))
+ pedwarn ("ANSI C++ forbids taking the sizeof a function type");
+ }
+ return c_sizeof (TREE_TYPE (e));
+}
+
+tree
c_sizeof_nowarn (type)
tree type;
{
@@ -1305,14 +1419,7 @@ c_sizeof_nowarn (type)
type = TREE_TYPE (type);
if (TYPE_SIZE (type) == 0)
- {
-#if 0
- /* ??? Tiemann, why have any diagnostic here?
- There is none in the corresponding function for C. */
- warning ("sizeof applied to an incomplete type");
-#endif
- return size_int (0);
- }
+ return size_int (0);
/* Convert in case a char is more than one unit. */
t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
@@ -1368,13 +1475,19 @@ decay_conversion (exp)
register tree type = TREE_TYPE (exp);
register enum tree_code code = TREE_CODE (type);
- if (code == OFFSET_TYPE /* || TREE_CODE (exp) == OFFSET_REF */ )
+ if (code == OFFSET_TYPE)
{
if (TREE_CODE (exp) == OFFSET_REF)
return decay_conversion (resolve_offset_ref (exp));
type = TREE_TYPE (type);
code = TREE_CODE (type);
+
+ if (type == unknown_type_node)
+ {
+ cp_pedwarn ("assuming & on overloaded member function");
+ return build_unary_op (ADDR_EXPR, exp, 0);
+ }
}
if (code == REFERENCE_TYPE)
@@ -1408,12 +1521,7 @@ decay_conversion (exp)
}
if (code == METHOD_TYPE)
{
- if (TREE_CODE (exp) == OFFSET_REF)
- {
- my_friendly_assert (TREE_CODE (TREE_OPERAND (exp, 1)) == FUNCTION_DECL,
- 308);
- return build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
- }
+ cp_pedwarn ("assuming & on `%E'", exp);
return build_unary_op (ADDR_EXPR, exp, 0);
}
if (code == ARRAY_TYPE)
@@ -1433,9 +1541,9 @@ decay_conversion (exp)
inner = build1 (CONVERT_EXPR,
build_pointer_type (TREE_TYPE (TREE_TYPE (inner))),
inner);
- TREE_REFERENCE_EXPR (inner) = 1;
+ TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0));
}
- return convert (build_pointer_type (TREE_TYPE (type)), inner);
+ return cp_convert (build_pointer_type (TREE_TYPE (type)), inner);
}
if (TREE_CODE (exp) == COMPOUND_EXPR)
@@ -1484,7 +1592,7 @@ decay_conversion (exp)
/* This way is better for a COMPONENT_REF since it can
simplify the offset for a component. */
adr = build_unary_op (ADDR_EXPR, exp, 1);
- return convert (ptrtype, adr);
+ return cp_convert (ptrtype, adr);
}
return exp;
@@ -1506,14 +1614,27 @@ default_conversion (exp)
{
tree t = type_promotes_to (type);
if (t != type)
- return convert (t, exp);
+ return cp_convert (t, exp);
}
- if (flag_traditional
- && TYPE_MAIN_VARIANT (type) == float_type_node)
- return convert (double_type_node, exp);
return exp;
}
+
+/* Take the address of an inline function without setting TREE_ADDRESSABLE
+ or TREE_USED. */
+
+tree
+inline_conversion (exp)
+ tree exp;
+{
+ if (TREE_CODE (exp) == FUNCTION_DECL)
+ {
+ tree type = build_type_variant
+ (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp));
+ exp = build1 (ADDR_EXPR, build_pointer_type (type), exp);
+ }
+ return exp;
+}
tree
build_object_ref (datum, basetype, field)
@@ -1532,107 +1653,107 @@ build_object_ref (datum, basetype, field)
basetype, field, dtype);
return error_mark_node;
}
- else if (IS_SIGNATURE (IDENTIFIER_TYPE_VALUE (basetype)))
+ else if (IS_SIGNATURE (basetype))
{
warning ("signature name in scope resolution ignored");
return build_component_ref (datum, field, NULL_TREE, 1);
}
- else if (is_aggr_typedef (basetype, 1))
+ else if (is_aggr_type (basetype, 1))
{
- tree real_basetype = IDENTIFIER_TYPE_VALUE (basetype);
- tree binfo = binfo_or_else (real_basetype, TREE_TYPE (datum));
+ tree binfo = binfo_or_else (basetype, dtype);
if (binfo)
- return build_component_ref (build_scoped_ref (datum, basetype),
- field, binfo, 1);
+ return build_x_component_ref (build_scoped_ref (datum, basetype),
+ field, binfo, 1);
}
return error_mark_node;
}
-/* Like `build_component_ref, but uses an already found field.
- Must compute access for C_C_D. Otherwise, ok. */
+/* Like `build_component_ref, but uses an already found field, and converts
+ from a reference. Must compute access for current_class_ref.
+ Otherwise, ok. */
+
tree
build_component_ref_1 (datum, field, protect)
tree datum, field;
int protect;
{
- register tree basetype = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (basetype);
- register tree ref;
-
- if (code == REFERENCE_TYPE)
- {
- datum = convert_from_reference (datum);
- basetype = TREE_TYPE (datum);
- code = TREE_CODE (basetype);
- }
+ return convert_from_reference
+ (build_component_ref (datum, field, NULL_TREE, protect));
+}
- if (! IS_AGGR_TYPE_CODE (code))
- {
- if (code != ERROR_MARK)
- cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
- field, datum, basetype);
- return error_mark_node;
- }
+/* Given a COND_EXPR, MIN_EXPR, or MAX_EXPR in T, return it in a form that we
+ can, for example, use as an lvalue. This code used to be in
+ unary_complex_lvalue, but we needed it to deal with `a = (d == c) ? b : c'
+ expressions, where we're dealing with aggregates. But now it's again only
+ called from unary_complex_lvalue. The case (in particular) that led to
+ this was with CODE == ADDR_EXPR, since it's not an lvalue when we'd
+ get it there. */
- if (TYPE_SIZE (basetype) == 0)
+static tree
+rationalize_conditional_expr (code, t)
+ enum tree_code code;
+ tree t;
+{
+ /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that
+ the first operand is always the one to be used if both operands
+ are equal, so we know what conditional expression this used to be. */
+ if (TREE_CODE (t) == MIN_EXPR || TREE_CODE (t) == MAX_EXPR)
{
- incomplete_type_error (0, basetype);
- return error_mark_node;
+ return
+ build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
+ ? LE_EXPR : GE_EXPR),
+ TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1)),
+ build_unary_op (code, TREE_OPERAND (t, 0), 0),
+ build_unary_op (code, TREE_OPERAND (t, 1), 0));
}
- /* Look up component name in the structure type definition. */
+ return
+ build_conditional_expr (TREE_OPERAND (t, 0),
+ build_unary_op (code, TREE_OPERAND (t, 1), 0),
+ build_unary_op (code, TREE_OPERAND (t, 2), 0));
+}
- if (field == error_mark_node)
- my_friendly_abort (115);
+/* Given the TYPE of an anonymous union field inside T, return the
+ FIELD_DECL for the field. If not found return NULL_TREE. Because
+ anonymous unions can nest, we must also search all anonymous unions
+ that are directly reachable. */
- if (TREE_STATIC (field))
- return field;
+static tree
+lookup_anon_field (t, type)
+ tree t, type;
+{
+ tree field;
- if (datum == C_C_D)
+ for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
{
- enum access_type access
- = compute_access (TYPE_BINFO (current_class_type), field);
+ if (TREE_STATIC (field))
+ continue;
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
- if (access == access_private)
+ /* If we find it directly, return the field. */
+ if (DECL_NAME (field) == NULL_TREE
+ && type == TREE_TYPE (field))
{
- cp_error ("field `%D' is private", field);
- return error_mark_node;
+ return field;
}
- else if (access == access_protected)
+
+ /* Otherwise, it could be nested, search harder. */
+ if (DECL_NAME (field) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{
- cp_error ("field `%D' is protected", field);
- return error_mark_node;
+ tree subfield = lookup_anon_field (TREE_TYPE (field), type);
+ if (subfield)
+ return subfield;
}
}
-
- ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field);
-
- if (TREE_READONLY (datum) || TREE_READONLY (field))
- TREE_READONLY (ref) = 1;
- if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field))
- TREE_THIS_VOLATILE (ref) = 1;
- if (DECL_MUTABLE_P (field))
- TREE_READONLY (ref) = 0;
-
- return ref;
+ return NULL_TREE;
}
-/* Given a COND_EXPR in T, return it in a form that we can, for
- example, use as an lvalue. This code used to be in unary_complex_lvalue,
- but we needed it to deal with `a = (d == c) ? b : c' expressions, where
- we're dealing with aggregates. So, we now call this in unary_complex_lvalue,
- and in build_modify_expr. The case (in particular) that led to this was
- with CODE == ADDR_EXPR, since it's not an lvalue when we'd get it there. */
-static tree
-rationalize_conditional_expr (code, t)
- enum tree_code code;
- tree t;
-{
- return
- build_conditional_expr (TREE_OPERAND (t, 0),
- build_unary_op (code, TREE_OPERAND (t, 1), 0),
- build_unary_op (code, TREE_OPERAND (t, 2), 0));
-}
+/* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT.
+ COMPONENT can be an IDENTIFIER_NODE that is the name of the member
+ that we are interested in, or it can be a FIELD_DECL. */
tree
build_component_ref (datum, component, basetype_path, protect)
@@ -1640,11 +1761,15 @@ build_component_ref (datum, component, basetype_path, protect)
int protect;
{
register tree basetype = TREE_TYPE (datum);
- register enum tree_code code = TREE_CODE (basetype);
+ register enum tree_code code;
register tree field = NULL;
register tree ref;
- /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it. */
+ if (processing_template_decl)
+ return build_min_nt (COMPONENT_REF, datum, component);
+
+ /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference
+ inside it. */
switch (TREE_CODE (datum))
{
case COMPOUND_EXPR:
@@ -1663,31 +1788,28 @@ build_component_ref (datum, component, basetype_path, protect)
basetype_path, protect));
}
+ code = TREE_CODE (basetype);
+
if (code == REFERENCE_TYPE)
{
-#if 0
- /* TREE_REFERENCE_EXPRs are not converted by `convert_from_reference'.
- @@ Maybe that is not right. */
- if (TREE_REFERENCE_EXPR (datum))
- datum = build1 (INDIRECT_REF, TREE_TYPE (basetype), datum);
- else
-#endif
- datum = convert_from_reference (datum);
+ datum = convert_from_reference (datum);
+ basetype = TREE_TYPE (datum);
+ code = TREE_CODE (basetype);
+ }
+ if (TREE_CODE (datum) == OFFSET_REF)
+ {
+ datum = resolve_offset_ref (datum);
basetype = TREE_TYPE (datum);
code = TREE_CODE (basetype);
}
- /* First, see if there is a field or component with name COMPONENT. */
+ /* First, see if there is a field or component with name COMPONENT. */
if (TREE_CODE (component) == TREE_LIST)
{
my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE
&& DECL_CHAIN (TREE_VALUE (component)) == NULL_TREE), 309);
return build (COMPONENT_REF, TREE_TYPE (component), datum, component);
}
-#if 0
- if (TREE_CODE (component) == TYPE_EXPR)
- return build_component_type_expr (datum, component, NULL_TREE, protect);
-#endif
if (! IS_AGGR_TYPE_CODE (code))
{
@@ -1697,7 +1819,7 @@ build_component_ref (datum, component, basetype_path, protect)
return error_mark_node;
}
- if (TYPE_SIZE (basetype) == 0)
+ if (TYPE_SIZE (complete_type (basetype)) == 0)
{
incomplete_type_error (0, basetype);
return error_mark_node;
@@ -1716,7 +1838,7 @@ build_component_ref (datum, component, basetype_path, protect)
cp_error ("type `%T' has no destructor", basetype);
return error_mark_node;
}
- return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
+ return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1);
}
/* Look up component name in the structure type definition. */
@@ -1726,12 +1848,20 @@ build_component_ref (datum, component, basetype_path, protect)
hierarchy, the compiler will abort (because vptr lookups are
not supposed to be ambiguous. */
field = CLASSTYPE_VFIELD (basetype);
+ else if (TREE_CODE (component) == FIELD_DECL
+ || TREE_CODE (component) == TYPE_DECL)
+ {
+ field = component;
+ }
else
{
+ tree name = component;
+ if (TREE_CODE (component) == VAR_DECL)
+ name = DECL_NAME (component);
if (basetype_path == NULL_TREE)
basetype_path = TYPE_BINFO (basetype);
- field = lookup_field (basetype_path, component,
- protect && ! VFIELD_NAME_P (component), 0);
+ field = lookup_field (basetype_path, name,
+ protect && !VFIELD_NAME_P (name), 0);
if (field == error_mark_node)
return error_mark_node;
@@ -1740,7 +1870,7 @@ build_component_ref (datum, component, basetype_path, protect)
/* Not found as a data field, look for it as a method. If found,
then if this is the only possible one, return it, else
report ambiguity error. */
- tree fndecls = lookup_fnfields (basetype_path, component, 1);
+ tree fndecls = lookup_fnfields (basetype_path, name, 1);
if (fndecls == error_mark_node)
return error_mark_node;
if (fndecls)
@@ -1748,28 +1878,31 @@ build_component_ref (datum, component, basetype_path, protect)
if (TREE_CHAIN (fndecls) == NULL_TREE
&& DECL_CHAIN (TREE_VALUE (fndecls)) == NULL_TREE)
{
- enum access_type access;
- tree fndecl;
+ tree access, fndecl;
/* Unique, so use this one now. */
basetype = TREE_PURPOSE (fndecls);
fndecl = TREE_VALUE (fndecls);
access = compute_access (TREE_PURPOSE (fndecls), fndecl);
- if (access == access_public)
+ if (access == access_public_node)
{
if (DECL_VINDEX (fndecl)
&& ! resolves_to_fixed_type_p (datum, 0))
{
tree addr = build_unary_op (ADDR_EXPR, datum, 0);
+ tree fntype = TREE_TYPE (fndecl);
+
addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr);
datum = build_indirect_ref (addr, NULL_PTR);
my_friendly_assert (datum != error_mark_node, 310);
fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl));
+ TREE_TYPE (fndecl) = build_pointer_type (fntype);
}
- assemble_external (fndecl);
- return fndecl;
+ else
+ mark_used (fndecl);
+ return build (OFFSET_REF, TREE_TYPE (fndecl), datum, fndecl);
}
- if (access == access_protected)
+ if (access == access_protected_node)
cp_error ("member function `%D' is protected", fndecl);
else
cp_error ("member function `%D' is private", fndecl);
@@ -1781,9 +1914,6 @@ build_component_ref (datum, component, basetype_path, protect)
not matter unless we're actually calling the function. */
tree t;
- for (t = TREE_VALUE (fndecls); t; t = DECL_CHAIN (t))
- assemble_external (t);
-
t = build_tree_list (error_mark_node, fndecls);
TREE_TYPE (t) = build_offset_type (basetype,
unknown_type_node);
@@ -1791,12 +1921,7 @@ build_component_ref (datum, component, basetype_path, protect)
}
}
-#if 0
- if (component == ansi_opname[(int) TYPE_EXPR])
- cp_error ("`%#T' has no such type conversion operator", basetype);
- else
-#endif
- cp_error ("`%#T' has no member named `%D'", basetype, component);
+ cp_error ("`%#T' has no member named `%D'", basetype, name);
return error_mark_node;
}
else if (TREE_TYPE (field) == error_mark_node)
@@ -1809,26 +1934,60 @@ build_component_ref (datum, component, basetype_path, protect)
cp_error ("invalid use of type decl `%#D' as expression", field);
return error_mark_node;
}
- if (DECL_RTL (field) != 0)
- assemble_external (field);
- TREE_USED (field) = 1;
+ else if (DECL_RTL (field) != 0)
+ mark_used (field);
+ else
+ TREE_USED (field) = 1;
return field;
}
}
- if (DECL_FIELD_CONTEXT (field) != basetype
- && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+ /* See if we have to do any conversions so that we pick up the field from the
+ right context. */
+ if (DECL_FIELD_CONTEXT (field) != basetype)
{
- tree addr = build_unary_op (ADDR_EXPR, datum, 0);
- if (integer_zerop (addr))
+ tree context = DECL_FIELD_CONTEXT (field);
+ tree base = context;
+ while (base != basetype && TYPE_NAME (base)
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (base)))
{
- error ("invalid reference to NULL ptr, use ptr-to-member instead");
- return error_mark_node;
+ base = TYPE_CONTEXT (base);
+ }
+
+ /* Handle base classes here... */
+ if (base != basetype && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+ {
+ tree addr = build_unary_op (ADDR_EXPR, datum, 0);
+ if (integer_zerop (addr))
+ {
+ error ("invalid reference to NULL ptr, use ptr-to-member instead");
+ return error_mark_node;
+ }
+ if (VBASE_NAME_P (DECL_NAME (field)))
+ {
+ /* It doesn't matter which vbase pointer we grab, just
+ find one of them. */
+ tree binfo = get_binfo (base,
+ TREE_TYPE (TREE_TYPE (addr)), 0);
+ addr = convert_pointer_to_real (binfo, addr);
+ }
+ else
+ addr = convert_pointer_to (base, addr);
+ datum = build_indirect_ref (addr, NULL_PTR);
+ my_friendly_assert (datum != error_mark_node, 311);
+ }
+ basetype = base;
+
+ /* Handle things from anon unions here... */
+ if (TYPE_NAME (context) && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
+ {
+ tree subfield = lookup_anon_field (basetype, context);
+ tree subdatum = build_component_ref (datum, subfield,
+ basetype_path, protect);
+ return build_component_ref (subdatum, field, basetype_path, protect);
}
- addr = convert_pointer_to (DECL_FIELD_CONTEXT (field), addr);
- datum = build_indirect_ref (addr, NULL_PTR);
- my_friendly_assert (datum != error_mark_node, 311);
}
+
ref = fold (build (COMPONENT_REF, TREE_TYPE (field),
break_out_cleanups (datum), field));
@@ -1841,6 +2000,22 @@ build_component_ref (datum, component, basetype_path, protect)
return ref;
}
+
+/* Variant of build_component_ref for use in expressions, which should
+ never have REFERENCE_TYPE. */
+
+tree
+build_x_component_ref (datum, component, basetype_path, protect)
+ tree datum, component, basetype_path;
+ int protect;
+{
+ tree t = build_component_ref (datum, component, basetype_path, protect);
+
+ if (! processing_template_decl)
+ t = convert_from_reference (t);
+
+ return t;
+}
/* Given an expression PTR for a pointer, return an expression
for the value pointed to.
@@ -1854,7 +2029,12 @@ build_x_indirect_ref (ptr, errorstring)
tree ptr;
char *errorstring;
{
- tree rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);
+ tree rval;
+
+ if (processing_template_decl)
+ return build_min_nt (INDIRECT_REF, ptr);
+
+ rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE);
if (rval)
return rval;
return build_indirect_ref (ptr, errorstring);
@@ -1865,12 +2045,17 @@ build_indirect_ref (ptr, errorstring)
tree ptr;
char *errorstring;
{
- register tree pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE ?
- ptr : default_conversion (ptr));
- register tree type = TREE_TYPE (pointer);
+ register tree pointer, type;
+
+ if (ptr == error_mark_node)
+ return error_mark_node;
+
+ pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
+ ? ptr : default_conversion (ptr));
+ type = TREE_TYPE (pointer);
- if (ptr == current_class_decl)
- return C_C_D;
+ if (ptr == current_class_ptr)
+ return current_class_ref;
if (IS_AGGR_TYPE (type))
{
@@ -1886,6 +2071,7 @@ build_indirect_ref (ptr, errorstring)
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
{
if (TREE_CODE (pointer) == ADDR_EXPR
+ && !flag_volatile
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (pointer, 0)))
== TYPE_MAIN_VARIANT (TREE_TYPE (type)))
&& (TREE_READONLY (TREE_OPERAND (pointer, 0))
@@ -1899,10 +2085,13 @@ build_indirect_ref (ptr, errorstring)
register tree ref = build1 (INDIRECT_REF,
TYPE_MAIN_VARIANT (t), pointer);
+ /* We *must* set TREE_READONLY when dereferencing a pointer to const,
+ so that we get the proper error message if the result is used
+ to assign to. Also, &* is supposed to be a no-op. */
TREE_READONLY (ref) = TYPE_READONLY (t);
- TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
TREE_SIDE_EFFECTS (ref)
- = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
+ = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer) || flag_volatile;
+ TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
return ref;
}
}
@@ -1937,21 +2126,9 @@ build_indirect_ref (ptr, errorstring)
will inherit the type of the array, which will be some pointer type. */
tree
-build_x_array_ref (array, index)
- tree array, index;
-{
- tree rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index, NULL_TREE);
- if (rval)
- return rval;
- return build_array_ref (array, index);
-}
-
-tree
build_array_ref (array, idx)
tree array, idx;
{
- tree itype;
-
if (idx == 0)
{
error ("subscript missing in array reference");
@@ -1962,8 +2139,6 @@ build_array_ref (array, idx)
|| TREE_TYPE (idx) == error_mark_node)
return error_mark_node;
- itype = TREE_TYPE (idx);
-
if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
&& TREE_CODE (array) != INDIRECT_REF)
{
@@ -2079,8 +2254,9 @@ build_array_ref (array, idx)
/* Build a function call to function FUNCTION with parameters PARAMS.
PARAMS is a list--a chain of TREE_LIST nodes--in which the
- TREE_VALUE of each node is a parameter-expression.
- FUNCTION's data type may be a function type or a pointer-to-function.
+ TREE_VALUE of each node is a parameter-expression. The PARAMS do
+ not include any object pointer that may be required. FUNCTION's
+ data type may be a function type or a pointer-to-function.
For C++: If FUNCTION's data type is a TREE_LIST, then the tree list
is the list of possible methods that FUNCTION could conceivably
@@ -2095,12 +2271,11 @@ build_array_ref (array, idx)
In the second case, TREE_PURPOSE (function) is the function's
name directly.
- DECL is the class instance variable, usually CURRENT_CLASS_DECL. */
+ DECL is the class instance variable, usually CURRENT_CLASS_REF.
+
+ When calling a TEMPLATE_DECL, we don't require a complete return
+ type. */
-/*
- * [eichin:19911015.1726EST] actually return a possibly incomplete
- * type
- */
tree
build_x_function_call (function, params, decl)
tree function, params, decl;
@@ -2111,7 +2286,27 @@ build_x_function_call (function, params, decl)
if (function == error_mark_node)
return error_mark_node;
+ if (processing_template_decl)
+ return build_min_nt (CALL_EXPR, function, params, NULL_TREE);
+
type = TREE_TYPE (function);
+
+ if (TREE_CODE (type) == OFFSET_TYPE
+ && TREE_TYPE (type) == unknown_type_node
+ && TREE_CODE (function) == TREE_LIST
+ && TREE_CHAIN (function) == NULL_TREE)
+ {
+ /* Undo (Foo:bar)()... */
+ type = TYPE_OFFSET_BASETYPE (type);
+ function = TREE_VALUE (function);
+ my_friendly_assert (TREE_CODE (function) == TREE_LIST, 999);
+ my_friendly_assert (TREE_CHAIN (function) == NULL_TREE, 999);
+ function = TREE_VALUE (function);
+ my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 999);
+ function = DECL_NAME (function);
+ return build_method_call (decl, function, params, TYPE_BINFO (type), LOOKUP_NORMAL);
+ }
+
is_method = ((TREE_CODE (function) == TREE_LIST
&& current_class_type != NULL_TREE
&& IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) == function)
@@ -2119,11 +2314,21 @@ build_x_function_call (function, params, decl)
|| TREE_CODE (type) == METHOD_TYPE
|| TYPE_PTRMEMFUNC_P (type));
+ if (TREE_CODE (function) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (function))
+ return build_member_call
+ (DECL_CONTEXT (function), DECL_NAME (function), params);
+
/* Handle methods, friends, and overloaded functions, respectively. */
if (is_method)
{
- if (TREE_CODE (function) == FUNCTION_DECL)
+ tree basetype = NULL_TREE;
+
+ if (TREE_CODE (function) == FUNCTION_DECL
+ || DECL_FUNCTION_TEMPLATE_P (function))
{
+ basetype = DECL_CLASS_CONTEXT (function);
+
if (DECL_NAME (function))
function = DECL_NAME (function);
else
@@ -2131,15 +2336,9 @@ build_x_function_call (function, params, decl)
}
else if (TREE_CODE (function) == TREE_LIST)
{
-#if 0
- if (TREE_CODE (TREE_VALUE (function)) == TREE_LIST)
- function = TREE_PURPOSE (TREE_VALUE (function));
- else
- function = TREE_PURPOSE (function);
-#else
my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312);
+ basetype = DECL_CLASS_CONTEXT (TREE_VALUE (function));
function = TREE_PURPOSE (function);
-#endif
}
else if (TREE_CODE (function) != IDENTIFIER_NODE)
{
@@ -2166,6 +2365,10 @@ build_x_function_call (function, params, decl)
must go through here in case it is a virtual function.
@@ Perhaps this could be optimized. */
+ if (basetype && (! current_class_type
+ || ! DERIVED_FROM_P (basetype, current_class_type)))
+ return build_member_call (basetype, function, params);
+
if (decl == NULL_TREE)
{
if (current_class_type == NULL_TREE)
@@ -2188,14 +2391,14 @@ build_x_function_call (function, params, decl)
{
/* Should we undo what was done in build_component_ref? */
if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC)
- /* Get the name that build_component_ref hid. */
+ /* Get the name that build_component_ref hid. */
function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1)));
else
function = TREE_PURPOSE (TREE_OPERAND (function, 1));
return build_method_call (decl, function, params,
NULL_TREE, LOOKUP_NORMAL);
}
- else if (TREE_CODE (function) == TREE_LIST)
+ else if (really_overloaded_fn (function))
{
if (TREE_VALUE (function) == NULL_TREE)
{
@@ -2207,12 +2410,15 @@ build_x_function_call (function, params, decl)
{
tree val = TREE_VALUE (function);
+ if (flag_ansi_overloading)
+ return build_new_function_call (function, params, NULL_TREE);
+
if (TREE_CODE (val) == TEMPLATE_DECL)
- return build_overload_call_maybe
- (function, params, LOOKUP_COMPLAIN, (struct candidate *)0);
+ return build_overload_call_real
+ (function, params, LOOKUP_COMPLAIN, (struct candidate *)0, 0);
else if (DECL_CHAIN (val) != NULL_TREE)
return build_overload_call
- (function, params, LOOKUP_COMPLAIN, (struct candidate *)0);
+ (function, params, LOOKUP_COMPLAIN);
else
my_friendly_abort (360);
}
@@ -2228,12 +2434,12 @@ build_x_function_call (function, params, decl)
if (TREE_OPERAND (function, 0))
decl = TREE_OPERAND (function, 0);
else
- decl = C_C_D;
+ decl = current_class_ref;
decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
function = get_member_function_from_ptrfunc (&decl_addr,
TREE_OPERAND (function, 1));
- params = tree_cons (NULL_TREE, decl_addr, params);
+ params = expr_tree_cons (NULL_TREE, decl_addr, params);
return build_function_call (function, params);
}
@@ -2243,7 +2449,7 @@ build_x_function_call (function, params, decl)
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
- if (TYPE_LANG_SPECIFIC (type) && TYPE_OVERLOADS_CALL_EXPR (type))
+ if (IS_AGGR_TYPE (type))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE);
}
@@ -2282,8 +2488,8 @@ build_x_function_call (function, params, decl)
decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl);
}
else
- decl = build_c_cast (ctypeptr, decl, 0);
- params = tree_cons (NULL_TREE, decl, params);
+ decl = build_c_cast (ctypeptr, decl);
+ params = expr_tree_cons (NULL_TREE, decl, params);
}
return build_function_call (function, params);
@@ -2304,7 +2510,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
- tree fntype, index, e1, delta, delta2, e2, e3, aref, vtbl;
+ tree fntype, idx, e1, delta, delta2, e2, e3, aref, vtbl;
tree instance;
tree instance_ptr = *instance_ptrptr;
@@ -2316,42 +2522,43 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
function = save_expr (function);
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
- index = save_expr (build_component_ref (function,
- index_identifier,
- 0, 0));
- e1 = build (GT_EXPR, boolean_type_node, index,
- convert (delta_type_node, integer_zero_node));
- delta = convert (ptrdiff_type_node,
- build_component_ref (function, delta_identifier, 0, 0));
+
+ /* Promoting idx before saving it improves performance on RISC
+ targets. Without promoting, the first compare used
+ load-with-sign-extend, while the second used normal load then
+ shift to sign-extend. An optimizer flaw, perhaps, but it's easier
+ to make this change. */
+ idx = save_expr (default_conversion
+ (build_component_ref (function,
+ index_identifier,
+ NULL_TREE, 0)));
+ e1 = build_binary_op (GT_EXPR, idx, integer_zero_node, 1);
+ delta = cp_convert (ptrdiff_type_node,
+ build_component_ref (function, delta_identifier, NULL_TREE, 0));
delta2 = DELTA2_FROM_PTRMEMFUNC (function);
- /* convert down to the right base, before using the instance. */
+ /* Convert down to the right base, before using the instance. */
instance
= convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
instance_ptr);
- if (instance == error_mark_node)
+ if (instance == error_mark_node && instance_ptr != error_mark_node)
return instance;
vtbl = convert_pointer_to (ptr_type_node, instance);
vtbl
= build (PLUS_EXPR,
build_pointer_type (build_pointer_type (vtable_entry_type)),
- vtbl, convert (ptrdiff_type_node, delta2));
+ vtbl, cp_convert (ptrdiff_type_node, delta2));
vtbl = build_indirect_ref (vtbl, NULL_PTR);
aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR,
- index,
+ idx,
integer_one_node, 1));
if (! flag_vtable_thunks)
{
aref = save_expr (aref);
- /* 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));
-
delta = build_binary_op (PLUS_EXPR,
- build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
+ build_conditional_expr (e1, build_component_ref (aref, delta_identifier, NULL_TREE, 0), integer_zero_node),
delta, 1);
}
@@ -2360,11 +2567,18 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
if (flag_vtable_thunks)
e2 = aref;
else
- e2 = build_component_ref (aref, pfn_identifier, 0, 0);
+ e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
e3 = PFN_FROM_PTRMEMFUNC (function);
TREE_TYPE (e2) = TREE_TYPE (e3);
- function = build_conditional_expr (e1, e2, e3);
+ e1 = build_conditional_expr (e1, e2, e3);
+
+ if (instance_ptr == error_mark_node
+ && TREE_CODE (e1) != ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL)
+ cp_error ("object missing in `%E'", function);
+
+ function = e1;
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
@@ -2400,7 +2614,7 @@ build_function_call_real (function, params, require_complete, flags)
GNU_xref_call (current_function_decl,
IDENTIFIER_POINTER (name ? name
: TYPE_IDENTIFIER (DECL_CLASS_CONTEXT (function))));
- assemble_external (function);
+ mark_used (function);
fndecl = function;
/* Convert anything with function type to a pointer-to-function. */
@@ -2424,43 +2638,27 @@ build_function_call_real (function, params, require_complete, flags)
needs to be separately compiled). */
if (DECL_INLINE (function))
- {
- /* 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);
-
- fntype = build_type_variant (TREE_TYPE (function),
- TREE_READONLY (function),
- TREE_THIS_VOLATILE (function));
- function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
- }
+ function = inline_conversion (function);
else
- {
- assemble_external (function);
- TREE_USED (function) = 1;
- function = default_conversion (function);
- }
+ function = build_addr_func (function);
}
else
{
fndecl = NULL_TREE;
- /* Convert anything with function type to a pointer-to-function. */
- if (function == error_mark_node)
- return error_mark_node;
- function = default_conversion (function);
+ function = build_addr_func (function);
}
+ if (function == error_mark_node)
+ return error_mark_node;
+
fntype = TREE_TYPE (function);
if (TYPE_PTRMEMFUNC_P (fntype))
{
- tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0);
- fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype);
- function = get_member_function_from_ptrfunc (&instance_ptr, function);
+ cp_error ("must use .* or ->* to call pointer-to-member function in `%E (...)'",
+ function);
+ return error_mark_node;
}
is_method = (TREE_CODE (fntype) == POINTER_TYPE
@@ -2468,7 +2666,8 @@ build_function_call_real (function, params, require_complete, flags)
if (!((TREE_CODE (fntype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (fntype)) == FUNCTION_TYPE)
- || is_method))
+ || is_method
+ || TREE_CODE (function) == TEMPLATE_ID_EXPR))
{
cp_error ("`%E' cannot be used as a function", function);
return error_mark_node;
@@ -2518,17 +2717,17 @@ build_function_call_real (function, params, require_complete, flags)
/* C++ */
value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
{
- register tree result =
- build (CALL_EXPR, value_type,
- function, coerced_params, NULL_TREE);
-
- TREE_SIDE_EFFECTS (result) = 1;
+ register tree result
+ = build_call (function, value_type, coerced_params);
- if (! require_complete)
- return convert_from_reference (result);
- if (value_type == void_type_node)
- return result;
- result = require_complete_type (result);
+ if (require_complete)
+ {
+ if (value_type == void_type_node)
+ return result;
+ result = require_complete_type (result);
+ }
+ if (IS_AGGR_TYPE (value_type))
+ result = build_cplus_new (value_type, result);
return convert_from_reference (result);
}
}
@@ -2539,14 +2738,6 @@ build_function_call (function, params)
{
return build_function_call_real (function, params, 1, LOOKUP_NORMAL);
}
-
-tree
-build_function_call_maybe (function, params)
- tree function, params;
-{
- return build_function_call_real (function, params, 0, 0);
-}
-
/* Convert the actual parameter expressions in the list VALUES
to the types in the list TYPELIST.
@@ -2576,7 +2767,6 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
tree return_loc, typelist, values, fndecl;
int flags;
{
- extern tree gc_protect_fndecl;
register tree typetail, valtail;
register tree result = NULL_TREE;
char *called_thing;
@@ -2585,6 +2775,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
if (! flag_elide_constructors)
return_loc = 0;
+ /* Argument passing is always copy-initialization. */
+ flags |= LOOKUP_ONLYCONVERTING;
+
if (fndecl)
{
if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE)
@@ -2613,9 +2806,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
{
if (fndecl)
{
- char *buf = (char *)alloca (40 + strlen (called_thing));
- sprintf (buf, "too many arguments to %s `%%s'", called_thing);
- error_with_decl (fndecl, buf);
+ cp_error_at ("too many arguments to %s `%+D'", called_thing,
+ fndecl);
error ("at this point in file");
}
else
@@ -2638,44 +2830,22 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* Strip the `&' from an overloaded FUNCTION_DECL. */
if (TREE_CODE (val) == ADDR_EXPR)
val = TREE_OPERAND (val, 0);
- if (TREE_CODE (val) == TREE_LIST
- && TREE_CHAIN (val) == NULL_TREE
- && TREE_TYPE (TREE_VALUE (val)) != NULL_TREE
- && (TREE_TYPE (val) == unknown_type_node
- || DECL_CHAIN (TREE_VALUE (val)) == NULL_TREE))
- /* Instantiates automatically. */
- val = TREE_VALUE (val);
+ if (really_overloaded_fn (val))
+ cp_error ("insufficient type information to resolve address of overloaded function `%D'",
+ DECL_NAME (get_first_fn (val)));
else
- {
- error ("insufficient type information in parameter list");
- val = integer_zero_node;
- }
+ error ("insufficient type information in parameter list");
+ val = integer_zero_node;
}
else if (TREE_CODE (val) == OFFSET_REF
&& TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
{
- /* This is unclean. Should be handled elsewhere. */
+ /* This is unclean. Should be handled elsewhere. */
val = build_unary_op (ADDR_EXPR, val, 0);
}
else if (TREE_CODE (val) == OFFSET_REF)
val = resolve_offset_ref (val);
- {
-#if 0
- /* This code forces the assumption that if we have a ptr-to-func
- type in an arglist, that every routine that wants to check
- its validity has done so, and thus we need not do any
- more conversion. I don't remember why this is necessary. */
- else if (TREE_CODE (ttype) == FUNCTION_TYPE
- && (type == NULL
- || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (type)) == VOID_TYPE))
- {
- type = build_pointer_type (ttype);
- }
-#endif
- }
-
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
if (TREE_CODE (val) == NOP_EXPR
@@ -2701,25 +2871,16 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
/* Formal parm type is specified by a function prototype. */
tree parmval;
- if (TYPE_SIZE (type) == 0)
+ if (TYPE_SIZE (complete_type (type)) == 0)
{
error ("parameter type of called function is incomplete");
parmval = val;
}
else
{
-#if 0 && defined (PROMOTE_PROTOTYPES)
- /* This breaks user-defined conversions. */
- /* Rather than truncating and then reextending,
- convert directly to int, if that's the type we will want. */
- if (! flag_traditional
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- type = integer_type_node;
-#endif
- parmval = convert_for_initialization (return_loc, type, val, flags,
- "argument passing", fndecl, i);
+ parmval = convert_for_initialization
+ (return_loc, type, val, flags,
+ "argument passing", fndecl, i);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
@@ -2731,7 +2892,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
if (parmval == error_mark_node)
return error_mark_node;
- result = tree_cons (NULL_TREE, parmval, result);
+ result = expr_tree_cons (NULL_TREE, parmval, result);
}
else
{
@@ -2742,30 +2903,19 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
&& (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node)))
/* Convert `float' to `double'. */
- result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
+ result = expr_tree_cons (NULL_TREE, cp_convert (double_type_node, val), result);
else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
&& ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
{
cp_warning ("cannot pass objects of type `%T' through `...'",
TREE_TYPE (val));
- result = tree_cons (NULL_TREE, val, result);
+ result = expr_tree_cons (NULL_TREE, val, result);
}
else
/* Convert `short' and `char' to full-size `int'. */
- result = tree_cons (NULL_TREE, default_conversion (val), result);
+ result = expr_tree_cons (NULL_TREE, default_conversion (val), result);
}
- if (flag_gc
- /* There are certain functions for which we don't need
- to protect our arguments. GC_PROTECT_FNDECL is one. */
- && fndecl != gc_protect_fndecl
- && type_needs_gc_entry (TREE_TYPE (TREE_VALUE (result)))
- && ! value_safe_from_gc (NULL_TREE, TREE_VALUE (result)))
- /* This will build a temporary variable whose cleanup is
- to clear the obstack entry. */
- TREE_VALUE (result) = protect_value_from_gc (NULL_TREE,
- TREE_VALUE (result));
-
if (typetail)
typetail = TREE_CHAIN (typetail);
}
@@ -2808,12 +2958,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
if (parmval == error_mark_node)
return error_mark_node;
- if (flag_gc
- && type_needs_gc_entry (TREE_TYPE (parmval))
- && ! value_safe_from_gc (NULL_TREE, parmval))
- parmval = protect_value_from_gc (NULL_TREE, parmval);
-
- result = tree_cons (0, parmval, result);
+ result = expr_tree_cons (0, parmval, result);
typetail = TREE_CHAIN (typetail);
/* ends with `...'. */
if (typetail == NULL_TREE)
@@ -2846,8 +2991,16 @@ build_x_binary_op (code, arg1, arg2)
enum tree_code code;
tree arg1, arg2;
{
- tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
- arg1, arg2, NULL_TREE);
+ tree rval;
+
+ if (processing_template_decl)
+ return build_min_nt (code, arg1, arg2);
+
+ if (flag_ansi_overloading)
+ return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
+
+ rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
+ arg1, arg2, NULL_TREE);
if (rval)
return build_opfncall (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
if (code == MEMBER_REF)
@@ -2869,7 +3022,6 @@ build_binary_op (code, arg1, arg2, convert_p)
if (convert_p)
{
- tree args_save [2];
tree type0, type1;
args[0] = decay_conversion (args[0]);
args[1] = decay_conversion (args[1]);
@@ -3045,8 +3197,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
{
if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
cp_warning ("division by zero in `%E / 0'", op0);
@@ -3155,7 +3309,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
}
@@ -3177,7 +3331,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
/* Avoid converting op1 to result_type later. */
converted = 1;
}
@@ -3202,15 +3356,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
/* Convert the shift-count to an integer, regardless of
size of value being shifted. */
if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
- op1 = convert (integer_type_node, op1);
+ op1 = cp_convert (integer_type_node, op1);
}
break;
case EQ_EXPR:
case NE_EXPR:
build_type = boolean_type_node;
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
+ || code0 == COMPLEX_TYPE)
+ && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
+ || code1 == COMPLEX_TYPE))
short_compare = 1;
else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)
{
@@ -3259,14 +3415,14 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
{
- op0 = build_component_ref (op0, index_identifier, 0, 0);
+ op0 = build_component_ref (op0, index_identifier, NULL_TREE, 0);
op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
{
- op0 = build_component_ref (op1, index_identifier, 0, 0);
+ op0 = build_component_ref (op1, index_identifier, NULL_TREE, 0);
op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
}
@@ -3280,8 +3436,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
&& ((op1.index != -1 && op0.delta2 == op1.delta2)
|| op0.pfn == op1.pfn)) */
- tree index0 = build_component_ref (op0, index_identifier, 0, 0);
- tree index1 = save_expr (build_component_ref (op1, index_identifier, 0, 0));
+ tree index0 = build_component_ref (op0, index_identifier, NULL_TREE, 0);
+ tree index1 = save_expr (build_component_ref (op1, index_identifier, NULL_TREE, 0));
tree pfn0 = PFN_FROM_PTRMEMFUNC (op0);
tree pfn1 = PFN_FROM_PTRMEMFUNC (op1);
tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0);
@@ -3302,7 +3458,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (TYPE_PTRMEMFUNC_P (type0)
&& TYPE_PTRMEMFUNC_FN_TYPE (type0) == type1)
{
- tree index0 = build_component_ref (op0, index_identifier, 0, 0);
+ tree index0 = build_component_ref (op0, index_identifier, NULL_TREE, 0);
tree index1;
tree pfn0 = PFN_FROM_PTRMEMFUNC (op0);
tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0);
@@ -3392,25 +3548,22 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
+ pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- if (pedantic)
- pedwarn ("ANSI C++ forbids comparison between pointer and integer");
- else if (! flag_traditional)
- warning ("comparison between pointer and integer");
+ pedwarn ("ANSI C++ forbids comparison between pointer and integer");
}
break;
}
- if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)
- && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))
+ if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ &&
+ (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE))
{
+ int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
+
if (shorten || common || short_compare)
result_type = common_type (type0, type1);
@@ -3425,7 +3578,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
Eg, (short)-1 | (unsigned short)-1 is (int)-1
but calculated in (unsigned short) it would be (unsigned short)-1. */
- if (shorten)
+ if (shorten && none_complex)
{
int unsigned0, unsigned1;
tree arg0 = get_narrower (op0, &unsigned0);
@@ -3511,7 +3664,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
it never happens because available widths are 2**N. */
&& (!TREE_UNSIGNED (final_type)
|| unsigned_arg
- || ((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0))
+ || (((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0)))
<= TYPE_PRECISION (result_type))))
{
/* Do an unsigned shift if the operand was zero-extended. */
@@ -3520,7 +3673,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
TREE_TYPE (arg0));
/* Convert value-to-be-shifted to that type. */
if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
+ op0 = cp_convert (result_type, op0);
converted = 1;
}
}
@@ -3539,13 +3692,13 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree val
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
- return convert (boolean_type_node, val);
+ return cp_convert (boolean_type_node, val);
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
}
- if (short_compare && extra_warnings)
+ if (short_compare && warn_sign_compare)
{
int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
@@ -3554,6 +3707,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
tree primop0 = get_narrower (op0, &unsignedp0);
tree primop1 = get_narrower (op1, &unsignedp1);
+ /* Check for comparison of different enum types. */
+ if (flag_int_enum_equivalence == 0
+ && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
+ && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
+ && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
+ {
+ cp_warning ("comparison between `%#T' and `%#T'",
+ TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
+ }
+
/* Give warnings for comparisons between signed and unsigned
quantities that may fail. */
/* Do the checking based on the original operand trees, so that
@@ -3595,8 +3759,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
have all bits set that are set in the ~ operand when it is
extended. */
- if (TREE_CODE (primop0) == BIT_NOT_EXPR
- ^ TREE_CODE (primop1) == BIT_NOT_EXPR)
+ if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
+ ^ (TREE_CODE (primop1) == BIT_NOT_EXPR))
{
if (TREE_CODE (primop0) == BIT_NOT_EXPR)
primop0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
@@ -3659,9 +3823,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (! converted)
{
if (TREE_TYPE (op0) != result_type)
- op0 = convert (result_type, op0);
+ op0 = cp_convert (result_type, op0);
if (TREE_TYPE (op1) != result_type)
- op1 = convert (result_type, op1);
+ op1 = cp_convert (result_type, op1);
}
if (build_type == NULL_TREE)
@@ -3675,7 +3839,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
if (final_type != 0)
- return convert (final_type, folded);
+ return cp_convert (final_type, folded);
return folded;
}
}
@@ -3717,12 +3881,12 @@ pointer_int_sum (resultcode, ptrop, intop)
}
else if (TREE_CODE (TREE_TYPE (result_type)) == OFFSET_TYPE)
{
- if (pedantic)
+ if (pedantic || warn_pointer_arith)
pedwarn ("ANSI C++ forbids using pointer to a member in arithmetic");
size_exp = integer_one_node;
}
else
- size_exp = size_in_bytes (TREE_TYPE (result_type));
+ size_exp = size_in_bytes (complete_type (TREE_TYPE (result_type)));
/* Needed to make OOPS V2R3 work. */
intop = folded;
@@ -3748,19 +3912,19 @@ pointer_int_sum (resultcode, ptrop, intop)
intop = 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))
+ intop = cp_convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop);
/* Replace the integer argument with a suitable product by the object size.
Do this multiplication as signed, then convert to the appropriate
pointer type (actually unsigned integral). */
- intop = convert (result_type,
- build_binary_op (MULT_EXPR, intop,
- convert (TREE_TYPE (intop), size_exp), 1));
+ intop = cp_convert (result_type,
+ build_binary_op (MULT_EXPR, intop,
+ cp_convert (TREE_TYPE (intop), size_exp), 1));
/* Create the sum or difference. */
@@ -3783,7 +3947,7 @@ pointer_diff (op0, op1)
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (TREE_TYPE (op0));
- if (pedantic)
+ if (pedantic || warn_pointer_arith)
{
if (TREE_CODE (target_type) == VOID_TYPE)
pedwarn ("ANSI C++ forbids using pointer of type `void *' in subtraction");
@@ -3799,7 +3963,7 @@ pointer_diff (op0, op1)
then drop through to build the divide operator. */
op0 = build_binary_op (MINUS_EXPR,
- convert (restype, op0), convert (restype, op1), 1);
+ cp_convert (restype, op0), cp_convert (restype, op1), 1);
/* This generates an error if op1 is a pointer to an incomplete type. */
if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0)
@@ -3814,7 +3978,7 @@ pointer_diff (op0, op1)
/* Do the division. */
- result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1));
+ result = build (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
folded = fold (result);
if (folded == result)
@@ -3845,9 +4009,6 @@ build_component_addr (arg, argtype, msg)
return error_mark_node;
}
- if (flag_gc)
- cp_warning ("address of `%T::%D' taken", basetype, field);
-
if (TREE_CODE (field) == FIELD_DECL
&& TYPE_USES_COMPLEX_INHERITANCE (basetype))
{
@@ -3868,7 +4029,7 @@ build_component_addr (arg, argtype, msg)
size_int (BITS_PER_UNIT));
int flag = TREE_CONSTANT (rval);
rval = fold (build (PLUS_EXPR, argtype,
- rval, convert (argtype, offset)));
+ rval, cp_convert (argtype, offset)));
TREE_CONSTANT (rval) = flag;
}
return rval;
@@ -3883,21 +4044,44 @@ build_x_unary_op (code, xarg)
enum tree_code code;
tree xarg;
{
+ if (processing_template_decl)
+ return build_min_nt (code, xarg, NULL_TREE);
+
/* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
- error message. */
+ error message. */
if (code == ADDR_EXPR
+ && TREE_CODE (xarg) != TEMPLATE_ID_EXPR
&& ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
&& TYPE_SIZE (TREE_TYPE (xarg)) == NULL_TREE)
|| (TREE_CODE (xarg) == OFFSET_REF)))
/* don't look for a function */;
else
{
- tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
- NULL_TREE, NULL_TREE);
- if (rval)
- return build_opfncall (code, LOOKUP_NORMAL, xarg,
+ tree rval;
+
+ if (flag_ansi_overloading)
+ {
+ rval = build_new_op (code, LOOKUP_NORMAL, xarg,
NULL_TREE, NULL_TREE);
+ if (rval || code != ADDR_EXPR)
+ return rval;
+ }
+ else
+ {
+ rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
+ NULL_TREE, NULL_TREE);
+ if (rval)
+ return build_opfncall (code, LOOKUP_NORMAL, xarg,
+ NULL_TREE, NULL_TREE);
+ }
+ }
+
+ if (code == ADDR_EXPR)
+ {
+ if (TREE_CODE (xarg) == TARGET_EXPR)
+ warning ("taking address of temporary");
}
+
return build_unary_op (code, xarg, 0);
}
@@ -3907,7 +4091,10 @@ tree
condition_conversion (expr)
tree expr;
{
- tree t = convert (boolean_type_node, expr);
+ tree t;
+ if (processing_template_decl)
+ return expr;
+ t = cp_convert (boolean_type_node, expr);
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
return t;
}
@@ -3920,6 +4107,7 @@ condition_conversion (expr)
NOCONVERT nonzero suppresses the default promotions
(such as from short to int). */
+
tree
build_unary_op (code, xarg, noconvert)
enum tree_code code;
@@ -3960,7 +4148,14 @@ build_unary_op (code, xarg, noconvert)
break;
case BIT_NOT_EXPR:
- if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, arg, 1)))
+ if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ {
+ code = CONJ_EXPR;
+ if (!noconvert)
+ arg = default_conversion (arg);
+ }
+ else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM,
+ arg, 1)))
errstring = "wrong type argument to bit-complement";
else if (!noconvert)
arg = default_conversion (arg);
@@ -3973,8 +4168,16 @@ build_unary_op (code, xarg, noconvert)
arg = default_conversion (arg);
break;
+ case CONJ_EXPR:
+ /* Conjugating a real value is a no-op, but allow it anyway. */
+ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1)))
+ errstring = "wrong type argument to conjugation";
+ else if (!noconvert)
+ arg = default_conversion (arg);
+ break;
+
case TRUTH_NOT_EXPR:
- arg = convert (boolean_type_node, arg);
+ arg = cp_convert (boolean_type_node, arg);
val = invert_truthvalue (arg);
if (arg != error_mark_node)
return val;
@@ -3984,6 +4187,22 @@ build_unary_op (code, xarg, noconvert)
case NOP_EXPR:
break;
+ case REALPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_REALPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return arg;
+
+ case IMAGPART_EXPR:
+ if (TREE_CODE (arg) == COMPLEX_CST)
+ return TREE_IMAGPART (arg);
+ else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg));
+ else
+ return cp_convert (TREE_TYPE (arg), integer_zero_node);
+
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
@@ -3995,6 +4214,19 @@ build_unary_op (code, xarg, noconvert)
if (val != 0)
return val;
+ /* Increment or decrement the real part of the value,
+ and don't change the imaginary part. */
+ if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
+ {
+ tree real, imag;
+
+ arg = stabilize_reference (arg);
+ real = build_unary_op (REALPART_EXPR, arg, 1);
+ imag = build_unary_op (IMAGPART_EXPR, arg, 1);
+ return build (COMPLEX_EXPR, TREE_TYPE (arg),
+ build_unary_op (code, real, 1), imag);
+ }
+
/* Report invalid types. */
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER,
@@ -4038,7 +4270,7 @@ build_unary_op (code, xarg, noconvert)
if (TREE_CODE (argtype) == POINTER_TYPE)
{
enum tree_code tmp = TREE_CODE (TREE_TYPE (argtype));
- if (TYPE_SIZE (TREE_TYPE (argtype)) == 0)
+ if (TYPE_SIZE (complete_type (TREE_TYPE (argtype))) == 0)
cp_error ("cannot %s a pointer to incomplete type `%T'",
((code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
@@ -4054,7 +4286,7 @@ build_unary_op (code, xarg, noconvert)
else
inc = integer_one_node;
- inc = convert (argtype, inc);
+ inc = cp_convert (argtype, inc);
/* Handle incrementing a cast-expression. */
@@ -4068,7 +4300,7 @@ build_unary_op (code, xarg, noconvert)
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
{
- tree incremented, modify, value;
+ tree incremented, modify, value, compound;
if (! lvalue_p (arg) && pedantic)
pedwarn ("cast to non-reference type used as lvalue");
arg = stabilize_reference (arg);
@@ -4081,8 +4313,13 @@ build_unary_op (code, xarg, noconvert)
? PLUS_EXPR : MINUS_EXPR),
argtype, value, inc);
TREE_SIDE_EFFECTS (incremented) = 1;
+
modify = build_modify_expr (arg, NOP_EXPR, incremented);
- return build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+ compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+
+ /* Eliminate warning about unused result of + or -. */
+ TREE_NO_UNUSED_WARNING (compound) = 1;
+ return compound;
}
}
@@ -4124,7 +4361,7 @@ build_unary_op (code, xarg, noconvert)
val = build (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
- return convert (result_type, val);
+ return cp_convert (result_type, val);
}
case ADDR_EXPR:
@@ -4134,8 +4371,10 @@ build_unary_op (code, xarg, noconvert)
argtype = TREE_TYPE (arg);
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
+ arg = build1
+ (CONVERT_EXPR,
+ build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
+ TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
return arg;
}
else if (pedantic
@@ -4151,21 +4390,17 @@ build_unary_op (code, xarg, noconvert)
/* Let &* cancel out to simplify resulting code. */
if (TREE_CODE (arg) == INDIRECT_REF)
{
- /* We don't need to have `current_class_decl' wrapped in a
+ /* We don't need to have `current_class_ptr' wrapped in a
NON_LVALUE_EXPR node. */
- if (arg == C_C_D)
- return current_class_decl;
+ if (arg == current_class_ref)
+ return current_class_ptr;
- /* Keep `default_conversion' from converting if
- ARG is of REFERENCE_TYPE. */
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{
- if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg)
- && !TREE_SIDE_EFFECTS (DECL_INITIAL (arg)))
- arg = DECL_INITIAL (arg);
- arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_REFERENCE_EXPR (arg) = 1;
+ arg = build1
+ (CONVERT_EXPR,
+ build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
}
else if (lvalue_p (arg))
@@ -4210,6 +4445,27 @@ build_unary_op (code, xarg, noconvert)
0);
return build1 (ADDR_EXPR, unknown_type_node, arg);
}
+ else if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
+ {
+ tree targs;
+ tree fn;
+
+ /* We don't require a match here; it's possible that the
+ context (like a cast to a particular type) will resolve
+ the particular choice of template. */
+ fn = determine_explicit_specialization (arg, NULL_TREE,
+ &targs,
+ 0, 0);
+
+ if (fn)
+ {
+ fn = instantiate_template (fn, targs);
+ mark_addressable (fn);
+ return build_unary_op (ADDR_EXPR, fn, 0);
+ }
+
+ return build1 (ADDR_EXPR, unknown_type_node, arg);
+ }
/* Handle complex lvalues (when permitted)
by reduction to simpler cases. */
@@ -4271,6 +4527,14 @@ build_unary_op (code, xarg, noconvert)
function counts as a constant */
if (staticp (arg))
TREE_CONSTANT (addr) = 1;
+
+ if (TREE_CODE (argtype) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
+ {
+ build_ptrmemfunc_type (argtype);
+ addr = build_ptrmemfunc (argtype, addr, 0);
+ }
+
return addr;
}
}
@@ -4286,6 +4550,7 @@ build_unary_op (code, xarg, noconvert)
return error_mark_node;
}
+#if 0
/* If CONVERSIONS is a conversion expression or a nested sequence of such,
convert ARG with the same conversions in the same order
and return the result. */
@@ -4304,14 +4569,15 @@ convert_sequence (conversions, arg)
case FIX_FLOOR_EXPR:
case FIX_ROUND_EXPR:
case FIX_CEIL_EXPR:
- return convert (TREE_TYPE (conversions),
- convert_sequence (TREE_OPERAND (conversions, 0),
- arg));
+ return cp_convert (TREE_TYPE (conversions),
+ convert_sequence (TREE_OPERAND (conversions, 0),
+ arg));
default:
return arg;
}
}
+#endif
/* Apply unary lvalue-demanding operator CODE to the expression ARG
for certain kinds of expressions which are not really lvalues
@@ -4333,7 +4599,8 @@ unary_complex_lvalue (code, arg)
}
/* Handle (a ? b : c) used as an "lvalue". */
- if (TREE_CODE (arg) == COND_EXPR)
+ if (TREE_CODE (arg) == COND_EXPR
+ || TREE_CODE (arg) == MIN_EXPR || TREE_CODE (arg) == MAX_EXPR)
return rationalize_conditional_expr (code, arg);
if (TREE_CODE (arg) == MODIFY_EXPR
@@ -4351,15 +4618,9 @@ unary_complex_lvalue (code, arg)
|| TREE_CODE (arg) == INIT_EXPR)
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
- return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
- }
-
- if (TREE_CODE (arg) == WITH_CLEANUP_EXPR)
- {
- tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
- real_result = build (WITH_CLEANUP_EXPR, TREE_TYPE (real_result),
- real_result, 0, TREE_OPERAND (arg, 2));
- return real_result;
+ arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
+ TREE_NO_UNUSED_WARNING (arg) = 1;
+ return arg;
}
if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE
@@ -4370,7 +4631,6 @@ unary_complex_lvalue (code, arg)
is really the representation of a pointer to it.
Here give the representation its true type. */
tree t;
- tree offset;
my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313);
@@ -4379,12 +4639,15 @@ unary_complex_lvalue (code, arg)
t = TREE_OPERAND (arg, 1);
- if (TREE_CODE (t) == FUNCTION_DECL) /* Check all this code for right semantics. */
+ if (TREE_CODE (t) == FUNCTION_DECL) /* Check all this code for right semantics. */
return build_unary_op (ADDR_EXPR, t, 0);
if (TREE_CODE (t) == VAR_DECL)
return build_unary_op (ADDR_EXPR, t, 0);
else
{
+ tree type;
+ tree offset = integer_zero_node;
+
if (TREE_OPERAND (arg, 0)
&& (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR
|| TREE_OPERAND (TREE_OPERAND (arg, 0), 0) != error_mark_node))
@@ -4396,38 +4659,40 @@ unary_complex_lvalue (code, arg)
return error_mark_node;
}
- offset = get_delta_difference (DECL_FIELD_CONTEXT (t),
- TREE_TYPE (TREE_OPERAND (arg, 0)),
- 0);
+ type = TREE_TYPE (TREE_OPERAND (arg, 0));
+
+ if (TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE)
+ {
+ /* Add in the offset to the intermediate subobject, if any. */
+ offset = get_delta_difference (TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)),
+ type,
+ 0);
+ type = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg));
+ }
+
+ /* Now in the offset to the final subobject. */
+ offset = size_binop (PLUS_EXPR,
+ offset,
+ get_delta_difference (DECL_FIELD_CONTEXT (t),
+ type,
+ 0));
+
+ /* Add in the offset to the field. */
offset = size_binop (PLUS_EXPR, offset,
size_binop (EASY_DIV_EXPR,
DECL_FIELD_BITPOS (t),
size_int (BITS_PER_UNIT)));
- return convert (build_pointer_type (TREE_TYPE (arg)), offset);
- }
- }
-
- if (TREE_CODE (arg) == OFFSET_REF)
- {
- tree left = TREE_OPERAND (arg, 0), left_addr;
- tree right_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 1), 0);
- if (left == 0)
- if (current_class_decl)
- left_addr = current_class_decl;
- else
- {
- error ("no `this' for pointer to member");
- return error_mark_node;
- }
- else
- left_addr = build_unary_op (ADDR_EXPR, left, 0);
+ /* We offset all pointer to data members by 1 so that we can
+ distinguish between a null pointer to data member and the first
+ data member of a structure. */
+ offset = size_binop (PLUS_EXPR, offset, size_int (1));
- return build (PLUS_EXPR, build_pointer_type (TREE_TYPE (arg)),
- build1 (NOP_EXPR, integer_type_node, left_addr),
- build1 (NOP_EXPR, integer_type_node, right_addr));
+ return cp_convert (build_pointer_type (TREE_TYPE (arg)), offset);
+ }
}
+
/* We permit compiler to make function calls returning
objects of aggregate type look like lvalues. */
{
@@ -4441,24 +4706,13 @@ unary_complex_lvalue (code, arg)
if (TREE_CODE (arg) == SAVE_EXPR)
targ = arg;
else
- targ = build_cplus_new (TREE_TYPE (arg), arg, 1);
+ targ = build_cplus_new (TREE_TYPE (arg), arg);
return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), targ);
}
if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
return build (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
TREE_OPERAND (targ, 0), current_function_decl, NULL);
-
- /* We shouldn't wrap WITH_CLEANUP_EXPRs inside of SAVE_EXPRs, but in case
- we do, here's how to handle it. */
- if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == WITH_CLEANUP_EXPR)
- {
-#if 0
- /* Not really a bug, but something to turn on when testing. */
- compiler_error ("WITH_CLEANUP_EXPR wrapped in SAVE_EXPR");
-#endif
- return unary_complex_lvalue (ADDR_EXPR, targ);
- }
}
/* Don't let anything else be handled specially. */
@@ -4469,7 +4723,7 @@ unary_complex_lvalue (code, arg)
address of it; it should not be allocated in a register.
Value is 1 if successful.
- C++: we do not allow `current_class_decl' to be addressable. */
+ C++: we do not allow `current_class_ptr' to be addressable. */
int
mark_addressable (exp)
@@ -4486,22 +4740,24 @@ mark_addressable (exp)
case ADDR_EXPR:
case COMPONENT_REF:
case ARRAY_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
x = TREE_OPERAND (x, 0);
break;
case PARM_DECL:
- if (x == current_class_decl)
+ if (x == current_class_ptr)
{
- error ("address of `this' not available");
+ if (! flag_this_is_variable)
+ error ("address of `this' not available");
TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
put_var_into_stack (x);
return 1;
}
case VAR_DECL:
- if (TREE_STATIC (x)
- && TREE_READONLY (x)
+ if (TREE_STATIC (x) && TREE_READONLY (x)
&& DECL_RTL (x) != 0
- && ! decl_in_memory_p (x))
+ && ! DECL_IN_MEMORY_P (x))
{
/* We thought this would make a good constant variable,
but we were wrong. */
@@ -4526,8 +4782,10 @@ mark_addressable (exp)
case CONST_DECL:
case RESULT_DECL:
- /* For C++, we don't warn about taking the address of a register
- variable for CONST_DECLs; ARM p97 explicitly says it's okay. */
+ if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)
+ && !DECL_ARTIFICIAL (x) && extra_warnings)
+ cp_warning ("address requested for `%D', which is declared `register'",
+ x);
put_var_into_stack (x);
TREE_ADDRESSABLE (x) = 1;
return 1;
@@ -4537,20 +4795,20 @@ mark_addressable (exp)
be non-zero in the case of processing a default function.
The second may be non-zero in the case of a template function. */
x = DECL_MAIN_VARIANT (x);
- if ((DECL_THIS_INLINE (x) || DECL_PENDING_INLINE_INFO (x))
- && (DECL_CONTEXT (x) == NULL_TREE
- || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (x))) != 't'
- || ! CLASSTYPE_INTERFACE_ONLY (DECL_CONTEXT (x))))
- {
- mark_inline_for_output (x);
- if (x == current_function_decl)
- DECL_EXTERNAL (x) = 0;
- }
+ if (DECL_TEMPLATE_INFO (x) && !DECL_TEMPLATE_SPECIALIZATION (x))
+ mark_used (x);
TREE_ADDRESSABLE (x) = 1;
TREE_USED (x) = 1;
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
- if (asm_out_file)
- assemble_external (x);
+ return 1;
+
+ case CONSTRUCTOR:
+ TREE_ADDRESSABLE (x) = 1;
+ return 1;
+
+ case TARGET_EXPR:
+ TREE_ADDRESSABLE (x) = 1;
+ mark_addressable (TREE_OPERAND (x, 0));
return 1;
default:
@@ -4566,6 +4824,12 @@ build_x_conditional_expr (ifexp, op1, op2)
{
tree rval = NULL_TREE;
+ if (processing_template_decl)
+ return build_min_nt (COND_EXPR, ifexp, op1, op2);
+
+ if (flag_ansi_overloading)
+ return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
+
/* See comments in `build_x_binary_op'. */
if (op1 != 0)
rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2);
@@ -4584,7 +4848,6 @@ build_conditional_expr (ifexp, op1, op2)
register enum tree_code code1;
register enum tree_code code2;
register tree result_type = NULL_TREE;
- 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. */
@@ -4595,7 +4858,7 @@ build_conditional_expr (ifexp, op1, op2)
ifexp = op1 = save_expr (ifexp);
}
- ifexp = convert (boolean_type_node, ifexp);
+ ifexp = cp_convert (boolean_type_node, ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
@@ -4626,17 +4889,12 @@ build_conditional_expr (ifexp, op1, op2)
code2 = TREE_CODE (type2);
}
-#if 1 /* Produces wrong result if within sizeof. Sorry. */
/* Don't promote the operands separately if they promote
the same way. Return the unpromoted type and let the combined
value get promoted if necessary. */
if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)
&& code2 != ARRAY_TYPE
-#if 0
- /* For C++, let the enumeral type come through. */
- && code2 != ENUMERAL_TYPE
-#endif
&& code2 != FUNCTION_TYPE
&& code2 != METHOD_TYPE)
{
@@ -4665,9 +4923,17 @@ build_conditional_expr (ifexp, op1, op2)
result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
if (TREE_TYPE (result) != type1)
result = build1 (NOP_EXPR, type1, result);
+ /* Expand both sides into the same slot,
+ hopefully the target of the ?: expression. */
+ if (TREE_CODE (op1) == TARGET_EXPR && TREE_CODE (op2) == TARGET_EXPR)
+ {
+ tree slot = build (VAR_DECL, TREE_TYPE (result));
+ layout_decl (slot, 0);
+ result = build (TARGET_EXPR, TREE_TYPE (result),
+ slot, result, NULL_TREE, NULL_TREE);
+ }
return result;
}
-#endif
/* They don't match; promote them both and then try to reconcile them.
But don't permit mismatching enum types. */
@@ -4739,16 +5005,14 @@ build_conditional_expr (ifexp, op1, op2)
pedwarn ("ANSI C++ forbids conditional expr with only one void side");
result_type = void_type_node;
}
+ else if (code1 == POINTER_TYPE && null_ptr_cst_p (op2))
+ result_type = qualify_type (type1, type2);
+ else if (code2 == POINTER_TYPE && null_ptr_cst_p (op1))
+ result_type = qualify_type (type2, type1);
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
if (comp_target_types (type1, type2, 1))
result_type = common_type (type1, type2);
- else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
- && TREE_CODE (orig_op1) != NOP_EXPR)
- result_type = qualify_type (type2, type1);
- else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node
- && TREE_CODE (orig_op2) != NOP_EXPR)
- result_type = qualify_type (type1, type2);
else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
{
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
@@ -4793,30 +5057,12 @@ build_conditional_expr (ifexp, op1, op2)
}
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
- if (!integer_zerop (op2))
- pedwarn ("pointer/integer type mismatch in conditional expression");
- else
- {
- op2 = null_pointer_node;
-#if 0 /* Sez who? */
- if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
-#endif
- }
+ pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type1;
}
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
- if (!integer_zerop (op1))
- pedwarn ("pointer/integer type mismatch in conditional expression");
- else
- {
- op1 = null_pointer_node;
-#if 0 /* Sez who? */
- if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
- pedwarn ("ANSI C++ forbids conditional expr between 0 and function pointer");
-#endif
- }
+ pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type2;
}
@@ -4829,30 +5075,52 @@ build_conditional_expr (ifexp, op1, op2)
cp_error ("aggregate mismatch in conditional expression: `%T' vs `%T'", type1, type2);
return error_mark_node;
}
+ /* Warning: this code assumes that conversion between cv-variants of
+ a type is done using NOP_EXPRs. */
if (code1 == RECORD_TYPE && TYPE_HAS_CONVERSION (type1))
{
- tree tmp = build_type_conversion (CONVERT_EXPR, type2, op1, 0);
+ /* There are other types besides pointers and records. */
+ tree tmp;
+ if (code2 == POINTER_TYPE)
+ tmp = build_pointer_type
+ (build_type_variant (TREE_TYPE (type2), 1, 1));
+ else
+ tmp = type2;
+ tmp = build_type_conversion (CONVERT_EXPR, tmp, op1, 0);
if (tmp == NULL_TREE)
{
- cp_error ("aggregate type `%T' could not convert on lhs of `:'", type1);
+ cp_error ("incompatible types `%T' and `%T' in `?:'",
+ type1, type2);
return error_mark_node;
}
if (tmp == error_mark_node)
error ("ambiguous pointer conversion");
- result_type = type2;
+ else
+ STRIP_NOPS (tmp);
+ result_type = common_type (type2, TREE_TYPE (tmp));
op1 = tmp;
}
else if (code2 == RECORD_TYPE && TYPE_HAS_CONVERSION (type2))
{
- tree tmp = build_type_conversion (CONVERT_EXPR, type1, op2, 0);
+ tree tmp;
+ if (code1 == POINTER_TYPE)
+ tmp = build_pointer_type
+ (build_type_variant (TREE_TYPE (type1), 1, 1));
+ else
+ tmp = type1;
+
+ tmp = build_type_conversion (CONVERT_EXPR, tmp, op2, 0);
if (tmp == NULL_TREE)
{
- cp_error ("aggregate type `%T' could not convert on rhs of `:'", type2);
+ cp_error ("incompatible types `%T' and `%T' in `?:'",
+ type1, type2);
return error_mark_node;
}
if (tmp == error_mark_node)
error ("ambiguous pointer conversion");
- result_type = type1;
+ else
+ STRIP_NOPS (tmp);
+ result_type = common_type (type1, TREE_TYPE (tmp));
op2 = tmp;
}
else if (flag_cond_mismatch)
@@ -4869,46 +5137,11 @@ build_conditional_expr (ifexp, op1, op2)
result_type = build_ptrmemfunc_type (result_type);
if (result_type != TREE_TYPE (op1))
- op1 = convert_and_check (result_type, op1);
+ op1 = convert_for_initialization
+ (NULL_TREE, result_type, op1, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
if (result_type != TREE_TYPE (op2))
- op2 = convert_and_check (result_type, op2);
-
-#if 0
- /* XXX delete me, I've been here for years. */
- if (IS_AGGR_TYPE_CODE (code1))
- {
- result_type = TREE_TYPE (op1);
- if (TREE_CONSTANT (ifexp))
- return (integer_zerop (ifexp) ? op2 : op1);
-
- if (TYPE_MODE (result_type) == BLKmode)
- {
- register tree tempvar
- = build_decl (VAR_DECL, NULL_TREE, result_type);
- register tree xop1 = build_modify_expr (tempvar, NOP_EXPR, op1);
- register tree xop2 = build_modify_expr (tempvar, NOP_EXPR, op2);
- register tree result = fold (build (COND_EXPR, result_type,
- ifexp, xop1, xop2));
-
- layout_decl (tempvar, 0);
- /* No way to handle variable-sized objects here.
- I fear that the entire handling of BLKmode conditional exprs
- needs to be redone. */
- my_friendly_assert (TREE_CONSTANT (DECL_SIZE (tempvar)), 315);
- DECL_RTL (tempvar)
- = assign_stack_local (DECL_MODE (tempvar),
- (TREE_INT_CST_LOW (DECL_SIZE (tempvar))
- + BITS_PER_UNIT - 1)
- / BITS_PER_UNIT,
- 0);
-
- TREE_SIDE_EFFECTS (result)
- = TREE_SIDE_EFFECTS (ifexp) | TREE_SIDE_EFFECTS (op1)
- | TREE_SIDE_EFFECTS (op2);
- return build (COMPOUND_EXPR, result_type, result, tempvar);
- }
- }
-#endif /* 0 */
+ op2 = convert_for_initialization
+ (NULL_TREE, result_type, op2, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
if (TREE_CONSTANT (ifexp))
return integer_zerop (ifexp) ? op2 : op1;
@@ -4919,6 +5152,7 @@ build_conditional_expr (ifexp, op1, op2)
/* Handle overloading of the ',' operator when needed. Otherwise,
this function just builds an expression list. */
+
tree
build_x_compound_expr (list)
tree list;
@@ -4926,13 +5160,16 @@ build_x_compound_expr (list)
tree rest = TREE_CHAIN (list);
tree result;
+ if (processing_template_decl)
+ return build_min_nt (COMPOUND_EXPR, list, NULL_TREE);
+
if (rest == NULL_TREE)
return build_compound_expr (list);
result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL,
TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE);
if (result)
- return build_x_compound_expr (tree_cons (NULL_TREE, result, TREE_CHAIN (rest)));
+ return build_x_compound_expr (expr_tree_cons (NULL_TREE, result, TREE_CHAIN (rest)));
if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)))
{
@@ -4949,8 +5186,8 @@ build_x_compound_expr (list)
warn_if_unused_value (TREE_VALUE(list));
#endif
- return build_compound_expr (tree_cons (NULL_TREE, TREE_VALUE (list),
- build_tree_list (NULL_TREE, build_x_compound_expr (rest))));
+ return build_compound_expr (expr_tree_cons (NULL_TREE, TREE_VALUE (list),
+ build_expr_list (NULL_TREE, build_x_compound_expr (rest))));
}
/* Given a list of expressions, return a compound expression
@@ -4990,127 +5227,259 @@ build_compound_expr (list)
break_out_cleanups (TREE_VALUE (list)), rest);
}
-#ifdef __GNUC__
-__inline
-#endif
-int
-null_ptr_cst_p (t)
- tree t;
-{
- return (TREE_CODE (t) == INTEGER_CST && integer_zerop (t));
-}
-
-tree build_static_cast (type, expr)
+tree
+build_static_cast (type, expr)
tree type, expr;
{
- return build_c_cast (type, expr, 0);
+ tree intype, binfo;
+ int ok;
+
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
+
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
+
+ if (processing_template_decl)
+ {
+ tree t = build_min (STATIC_CAST_EXPR, type, expr);
+ return t;
+ }
+
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (type) != REFERENCE_TYPE
+ && TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
+
+ if (TREE_CODE (type) == VOID_TYPE)
+ return build1 (CONVERT_EXPR, type, expr);
+
+ if (type_unknown_p (expr))
+ {
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
+ }
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ return (convert_from_reference
+ (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
+ LOOKUP_COMPLAIN, NULL_TREE)));
+
+ if (IS_AGGR_TYPE (type))
+ return build_cplus_new
+ (type, (build_method_call
+ (NULL_TREE, ctor_identifier, build_expr_list (NULL_TREE, expr),
+ TYPE_BINFO (type), LOOKUP_NORMAL)));
+
+ expr = decay_conversion (expr);
+ intype = TREE_TYPE (expr);
+
+ /* FIXME handle casting to array type. */
+
+ ok = 0;
+ if (can_convert_arg (type, intype, expr))
+ ok = 1;
+ else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype))
+ {
+ tree binfo;
+ if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
+ && (TYPE_READONLY (TREE_TYPE (type))
+ >= TYPE_READONLY (TREE_TYPE (intype)))
+ && (TYPE_VOLATILE (TREE_TYPE (type))
+ >= TYPE_VOLATILE (TREE_TYPE (intype)))
+ && (binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 0))
+ && ! TREE_VIA_VIRTUAL (binfo))
+ ok = 1;
+ }
+ else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ {
+ if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))),
+ TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))), 1)
+ && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (type)))
+ >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype))))
+ && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type)))
+ >= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype))))
+ && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (intype),
+ TYPE_OFFSET_BASETYPE (type), 0))
+ && ! TREE_VIA_VIRTUAL (binfo))
+ ok = 1;
+ }
+ else if (TREE_CODE (intype) != BOOLEAN_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE
+ && TREE_CODE (type) != FUNCTION_TYPE
+ && can_convert (intype, type))
+ ok = 1;
+
+ if (ok)
+ return build_c_cast (type, expr);
+
+ cp_error ("static_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
}
-tree build_reinterpret_cast (type, expr)
+tree
+build_reinterpret_cast (type, expr)
tree type, expr;
{
- tree intype = TREE_TYPE (expr);
+ tree intype;
+
+ if (type == error_mark_node || expr == error_mark_node)
+ return error_mark_node;
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
- if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE)
+ if (processing_template_decl)
{
- cp_error ("reinterpret_cast cannot convert to type `%T'", type);
- return error_mark_node;
+ tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
+ return t;
}
- if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE)
+
+ if (TREE_CODE (type) != REFERENCE_TYPE)
{
- cp_error ("reinterpret_cast cannot convert from type `%T'", type);
- return error_mark_node;
+ expr = decay_conversion (expr);
+
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
}
- if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+
+ if (type_unknown_p (expr))
{
- cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'",
- intype, type);
- return error_mark_node;
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
}
- if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE)
+
+ intype = TREE_TYPE (expr);
+
+ if (TREE_CODE (type) == REFERENCE_TYPE)
{
- cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'",
- intype, type);
- return error_mark_node;
+ if (! real_lvalue_p (expr))
+ {
+ cp_error ("reinterpret_cast from `%T' rvalue to `%T'", intype, type);
+ return error_mark_node;
+ }
+ expr = build_unary_op (ADDR_EXPR, expr, 0);
+ if (expr != error_mark_node)
+ expr = build_reinterpret_cast
+ (build_pointer_type (TREE_TYPE (type)), expr);
+ if (expr != error_mark_node)
+ expr = build_indirect_ref (expr, 0);
+ return expr;
}
+ else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ return build_static_cast (type, expr);
- if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE)
- expr = convert (ptr_type_node, expr);
+ if (TYPE_PTR_P (type) && (TREE_CODE (intype) == INTEGER_TYPE
+ || TREE_CODE (intype) == ENUMERAL_TYPE))
+ /* OK */;
+ else if (TREE_CODE (type) == INTEGER_TYPE && TYPE_PTR_P (intype))
+ {
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (intype))
+ cp_pedwarn ("reinterpret_cast from `%T' to `%T' loses precision",
+ intype, type);
+ }
+ else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
+ || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+ {
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+ else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
+ {
+ if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype)))
+ cp_pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)",
+ intype, type);
- return build_c_cast (type, expr, 0);
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+ else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
+ || (TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype)))
+ {
+ pedwarn ("ANSI C++ forbids casting between pointers to functions and objects");
+ if (TREE_READONLY_DECL_P (expr))
+ expr = decl_constant_value (expr);
+ return fold (build1 (NOP_EXPR, type, expr));
+ }
+ else
+ {
+ cp_error ("reinterpret_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
+ }
+
+ return cp_convert (type, expr);
}
-tree build_const_cast (type, expr)
+tree
+build_const_cast (type, expr)
tree type, expr;
{
- tree intype = TREE_TYPE (expr);
- tree t1, t2;
+ tree intype;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
- if (TYPE_PTRMEMFUNC_P (type))
- type = TYPE_PTRMEMFUNC_FN_TYPE (type);
- if (TYPE_PTRMEMFUNC_P (intype))
- intype = TYPE_PTRMEMFUNC_FN_TYPE (intype);
+ if (TREE_CODE (expr) == OFFSET_REF)
+ expr = resolve_offset_ref (expr);
- if (! POINTER_TYPE_P (type))
- {
- cp_error ("const_cast cannot convert to non-pointer type `%T'", type);
- return error_mark_node;
- }
- if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr))
+ if (processing_template_decl)
{
- cp_error ("const_cast cannot convert rvalue to type `%T'", type);
- return error_mark_node;
+ tree t = build_min (CONST_CAST_EXPR, type, expr);
+ return t;
}
- if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE)
+
+ if (TREE_CODE (type) != REFERENCE_TYPE)
{
- cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'",
- intype, type);
- return error_mark_node;
+ expr = decay_conversion (expr);
+
+ /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
+ Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */
+ if (TREE_CODE (expr) == NOP_EXPR
+ && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
+ expr = TREE_OPERAND (expr, 0);
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
+ if (type_unknown_p (expr))
{
- t1 = TREE_TYPE (type);
- t2 = intype;
+ expr = instantiate_type (type, expr, 1);
+ if (expr == error_mark_node)
+ return error_mark_node;
}
- else
- {
- t1 = TREE_TYPE (type);
- t2 = TREE_TYPE (intype);
- for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE;
- t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2))
- ;
- }
+ intype = TREE_TYPE (expr);
- if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE)
+ if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
+ return build_static_cast (type, expr);
+ else if (TREE_CODE (type) == REFERENCE_TYPE)
{
- if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2))
+ if (! real_lvalue_p (expr))
{
- cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'",
- TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1));
+ cp_error ("const_cast from `%T' rvalue to `%T'", intype, type);
return error_mark_node;
}
- t1 = TREE_TYPE (t1);
- t2 = TREE_TYPE (t2);
- }
- if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2))
- {
- cp_error ("const_cast cannot convert unrelated type `%T' to `%T'",
- t2, t1);
- return error_mark_node;
+ if (comp_ptr_ttypes_const (TREE_TYPE (type), intype))
+ return (convert_from_reference
+ (convert_to_reference (type, expr, CONV_CONST|CONV_IMPLICIT,
+ LOOKUP_COMPLAIN, NULL_TREE)));
}
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (intype) == POINTER_TYPE
+ && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype)))
+ return cp_convert (type, expr);
- return build_c_cast (type, expr, 0);
+ cp_error ("const_cast from `%T' to `%T'", intype, type);
+ return error_mark_node;
}
/* Build an expression representing a cast to type TYPE of expression EXPR.
@@ -5119,10 +5488,8 @@ tree build_const_cast (type, expr)
when doing the cast. */
tree
-build_c_cast (type, expr, allow_nonconverting)
- register tree type;
- tree expr;
- int allow_nonconverting;
+build_c_cast (type, expr)
+ tree type, expr;
{
register tree value = expr;
@@ -5172,11 +5539,12 @@ build_c_cast (type, expr, allow_nonconverting)
return error_mark_node;
}
- /* If there's only one function in the overloaded space,
- just take it. */
- if (TREE_CODE (value) == TREE_LIST
- && TREE_CHAIN (value) == NULL_TREE)
- value = TREE_VALUE (value);
+ if (processing_template_decl)
+ {
+ tree t = build_min (CAST_EXPR, type,
+ min_tree_cons (NULL_TREE, value, NULL_TREE));
+ return t;
+ }
if (TREE_CODE (type) == VOID_TYPE)
value = build1 (CONVERT_EXPR, type, value);
@@ -5191,13 +5559,16 @@ build_c_cast (type, expr, allow_nonconverting)
else
{
tree otype;
- int flag;
/* Convert functions and arrays to pointers and
convert references to their expanded types,
but don't convert any other types. */
if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+ || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE
+ /* Don't do the default conversion if we want a
+ pointer to a function. */
+ && ! (TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
|| TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
value = default_conversion (value);
@@ -5229,6 +5600,8 @@ build_c_cast (type, expr, allow_nonconverting)
warning ("cast increases required alignment of target type");
#if 0
+ /* We should see about re-enabling these, they seem useful to
+ me. */
if (TREE_CODE (type) == INTEGER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE
&& TYPE_PRECISION (type) != TYPE_PRECISION (otype))
@@ -5243,11 +5616,9 @@ build_c_cast (type, expr, allow_nonconverting)
warning ("cast to pointer from integer of different size");
#endif
- flag = allow_nonconverting ? CONV_NONCONVERTING : 0;
-
if (TREE_CODE (type) == REFERENCE_TYPE)
value = (convert_from_reference
- (convert_to_reference (type, value, CONV_OLD_CONVERT|flag,
+ (convert_to_reference (type, value, CONV_C_CAST,
LOOKUP_COMPLAIN, NULL_TREE)));
else
{
@@ -5257,7 +5628,7 @@ build_c_cast (type, expr, allow_nonconverting)
value = decl_constant_value (value);
ovalue = value;
- value = convert_force (type, value, flag);
+ value = convert_force (type, value, CONV_C_CAST);
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
@@ -5269,313 +5640,45 @@ build_c_cast (type, expr, allow_nonconverting)
}
/* Always produce some operator for an explicit cast,
- so we can tell (for -pedantic) that the cast is no lvalue.
- Also, pedantically, don't let (void *) (FOO *) 0 be a null
- pointer constant. */
- if (TREE_CODE (type) != REFERENCE_TYPE
- && (value == expr
- || (pedantic
- && TREE_CODE (value) == INTEGER_CST
- && TREE_CODE (expr) == INTEGER_CST
- && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE)))
+ so we can tell (for -pedantic) that the cast is no lvalue. */
+ if (TREE_CODE (type) != REFERENCE_TYPE && value == expr
+ && real_lvalue_p (value))
value = non_lvalue (value);
return value;
}
-#if 0
-/* Build an assignment expression of lvalue LHS from value RHS.
-
- In C++, if the left hand side of the assignment is a REFERENCE_TYPE,
- that reference becomes deferenced down to it base type. */
-
-/* Return a reference to the BASE_INDEX part of EXPR. TYPE is
- the type to which BASE_INDEX applies. */
-static tree
-get_base_ref (type, base_index, expr)
- tree type;
- int base_index;
- tree expr;
-{
- tree binfos = TYPE_BINFO_BASETYPES (type);
- tree base_binfo = TREE_VEC_ELT (binfos, base_index);
- tree ref;
-
- if (TREE_CODE (expr) == ARRAY_REF
- || ! BINFO_OFFSET_ZEROP (base_binfo)
- || TREE_VIA_VIRTUAL (base_binfo)
- || TYPE_MODE (type) != TYPE_MODE (BINFO_TYPE (base_binfo)))
- {
- tree addr = build_unary_op (ADDR_EXPR, expr, 0);
- ref = build_indirect_ref (convert_pointer_to (base_binfo, addr),
- NULL_PTR);
- }
- else
- {
- ref = copy_node (expr);
- TREE_TYPE (ref) = BINFO_TYPE (base_binfo);
- }
- return ref;
-}
-
-/* Build an assignment expression of lvalue LHS from value RHS.
- MODIFYCODE is the code for a binary operator that we use
- to combine the old value of LHS with RHS to get the new value.
- Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
-
- C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed.
-
- `build_modify_expr_1' implements recursive part of memberwise
- assignment operation. */
-static tree
-build_modify_expr_1 (lhs, modifycode, rhs, basetype_path)
- tree lhs, rhs;
- enum tree_code modifycode;
- tree basetype_path;
-{
- register tree result;
- tree newrhs = rhs;
- tree lhstype = TREE_TYPE (lhs);
- tree olhstype = lhstype;
-
- /* Avoid duplicate error messages from operands that had errors. */
- if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
- return error_mark_node;
-
- /* If a binary op has been requested, combine the old LHS value with the RHS
- producing the value we should actually store into the LHS. */
-
- if (modifycode == INIT_EXPR)
- ;
- else if (modifycode == NOP_EXPR)
- {
- /* must deal with overloading of `operator=' here. */
- if (TREE_CODE (lhstype) == REFERENCE_TYPE)
- lhstype = TREE_TYPE (lhstype);
- else
- lhstype = olhstype;
- }
- else
- {
- lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs, 1);
- modifycode = NOP_EXPR;
- }
-
- /* If storing into a structure or union member,
- it has probably been given type `int'.
- Compute the type that would go with
- the actual amount of storage the member occupies. */
-
- if (TREE_CODE (lhs) == COMPONENT_REF
- && (TREE_CODE (lhstype) == INTEGER_TYPE
- || TREE_CODE (lhstype) == REAL_TYPE
- || TREE_CODE (lhstype) == ENUMERAL_TYPE))
- lhstype = TREE_TYPE (get_unwidened (lhs, 0));
-
- /* C++: The semantics of C++ differ from those of C when an
- assignment of an aggregate is desired. Assignment in C++ is
- now defined as memberwise assignment of non-static members
- and base class objects. This rule applies recursively
- until a member of a built-in type is found.
-
- Also, we cannot do a bit-wise copy of aggregates which
- contain virtual function table pointers. Those
- pointer values must be preserved through the copy.
- However, this is handled in expand_expr, and not here.
- This is because much better code can be generated at
- that stage than this one. */
- if (TREE_CODE (lhstype) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (lhstype)
- && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
- {
- register tree elt;
- int i;
-
- /* Perform operation on object. */
- if (modifycode == INIT_EXPR && TYPE_HAS_INIT_REF (lhstype))
- {
- result = build_method_call (lhs, constructor_name_full (lhstype),
- build_tree_list (NULL_TREE, rhs),
- basetype_path, LOOKUP_NORMAL);
- return build_indirect_ref (result, NULL_PTR);
- }
- else if (modifycode == NOP_EXPR)
- {
- /* `operator=' is not an inheritable operator; see 13.4.3. */
- if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_HAS_ASSIGNMENT (lhstype))
- {
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
- if (result == NULL_TREE)
- return error_mark_node;
- return result;
- }
- }
-
- if (TYPE_USES_VIRTUAL_BASECLASSES (lhstype)
- || (modifycode == NOP_EXPR && TYPE_GETS_ASSIGNMENT (lhstype))
- || (modifycode == INIT_EXPR && TYPE_GETS_INIT_REF (lhstype)))
- {
- tree binfos = BINFO_BASETYPES (TYPE_BINFO (lhstype));
- result = NULL_TREE;
-
- if (binfos != NULL_TREE)
- /* Perform operation on each member, depth-first, left-right. */
- for (i = 0; i <= TREE_VEC_LENGTH (binfos)-1; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree base_lhs, base_rhs;
- tree new_result;
-
- /* Assignments from virtual baseclasses handled elsewhere. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- continue;
-
- base_lhs = get_base_ref (lhstype, i, lhs);
- base_rhs = get_base_ref (lhstype, i, newrhs);
-
- BINFO_INHERITANCE_CHAIN (base_binfo) = basetype_path;
- new_result
- = build_modify_expr_1 (base_lhs, modifycode, base_rhs,
- base_binfo);
-
- /* We either get back a compound stmt, or a simple one. */
- if (new_result && TREE_CODE (new_result) == TREE_LIST)
- new_result = build_compound_expr (new_result);
- result = tree_cons (NULL_TREE, new_result, result);
- }
-
- for (elt = TYPE_FIELDS (lhstype); elt; elt = TREE_CHAIN (elt))
- {
- tree vbases = NULL_TREE;
- tree elt_lhs, elt_rhs;
-
- if (TREE_CODE (elt) != FIELD_DECL)
- continue;
- if (DECL_NAME (elt)
- && (VFIELD_NAME_P (DECL_NAME (elt))
- || VBASE_NAME_P (DECL_NAME (elt))))
- continue;
-
- if (TREE_READONLY (elt)
- || TREE_CODE (TREE_TYPE (elt)) == REFERENCE_TYPE)
- {
- cp_error ("cannot generate default `%T::operator ='",
- lhstype);
- if (TREE_CODE (TREE_TYPE (elt)) == REFERENCE_TYPE)
- cp_error_at ("because member `%#D' is a reference", elt);
- else
- cp_error_at ("because member `%#D' is const", elt);
-
- return error_mark_node;
- }
-
- if (IS_AGGR_TYPE (TREE_TYPE (elt))
- && TYPE_LANG_SPECIFIC (TREE_TYPE (elt)))
- vbases = CLASSTYPE_VBASECLASSES (TREE_TYPE (elt));
-
- elt_lhs = build (COMPONENT_REF, TREE_TYPE (elt), lhs, elt);
- elt_rhs = build (COMPONENT_REF, TREE_TYPE (elt), newrhs, elt);
- /* It is not always safe to go through `build_modify_expr_1'
- when performing element-wise copying. This is because
- an element may be of ARRAY_TYPE, which will not
- be properly copied as a naked element. */
- if (TREE_CODE (TREE_TYPE (elt)) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (TREE_TYPE (elt)))
- basetype_path = TYPE_BINFO (TREE_TYPE (elt));
-
- while (vbases)
- {
- tree elt_lhs_addr = build_unary_op (ADDR_EXPR, elt_lhs, 0);
- tree elt_rhs_addr = build_unary_op (ADDR_EXPR, elt_rhs, 0);
-
- elt_lhs_addr = convert_pointer_to (vbases, elt_lhs_addr);
- elt_rhs_addr = convert_pointer_to (vbases, elt_rhs_addr);
- result
- = tree_cons (NULL_TREE,
- build_modify_expr_1
- (build_indirect_ref (elt_lhs_addr, NULL_PTR),
- modifycode,
- build_indirect_ref (elt_rhs_addr, NULL_PTR),
- basetype_path),
- result);
- if (TREE_VALUE (result) == error_mark_node)
- return error_mark_node;
- vbases = TREE_CHAIN (vbases);
- }
- elt_lhs = build_modify_expr_1 (elt_lhs, modifycode, elt_rhs,
- basetype_path);
- result = tree_cons (NULL_TREE, elt_lhs, result);
- }
-
- if (result)
- return build_compound_expr (result);
- /* No fields to move. */
- return integer_zero_node;
- }
- else
- {
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- void_type_node, lhs, rhs);
- TREE_SIDE_EFFECTS (result) = 1;
- return result;
- }
- }
-
- result = build_modify_expr (lhs, modifycode, newrhs);
- /* ARRAY_TYPEs cannot be converted to anything meaningful,
- and leaving it there screws up `build_compound_expr' when
- it tries to defaultly convert everything. */
- if (TREE_CODE (TREE_TYPE (result)) == ARRAY_TYPE)
- TREE_TYPE (result) = void_type_node;
- return result;
-}
-#endif
-
-/* Taken from expr.c:
- Subroutine of expand_expr:
- record the non-copied parts (LIST) of an expr (LHS), and return a list
- which specifies the initial values of these parts. */
-
static tree
-init_noncopied_parts (lhs, list)
- tree lhs;
- tree list;
-{
- tree tail;
- tree parts = 0;
-
- for (tail = list; tail; tail = TREE_CHAIN (tail))
- if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
- parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
- else
- {
- tree part = TREE_VALUE (tail);
- tree part_type = TREE_TYPE (part);
- tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part);
- parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts);
- }
- return parts;
-}
-
-tree
expand_target_expr (t)
tree t;
{
+ extern int temp_slot_level;
+ extern int target_temp_slot_level;
+ int old_temp_level = target_temp_slot_level;
+
tree xval = make_node (RTL_EXPR);
rtx rtxval;
+ /* Any TARGET_EXPR temps live only as long as the outer temp level.
+ Since they are preserved in this new inner level, we know they
+ will make it into the outer level. */
+ push_temp_slots ();
+ target_temp_slot_level = temp_slot_level;
+
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (xval);
emit_note (0, -1);
- rtxval = expand_expr (t, NULL, VOIDmode, 0);
+ rtxval = expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
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 (t);
+
+ pop_temp_slots ();
+ target_temp_slot_level = old_temp_level;
+
return xval;
}
@@ -5584,8 +5687,8 @@ expand_target_expr (t)
to combine the old value of LHS with RHS to get the new value.
Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
- C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed.
-*/
+ C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed. */
+
tree
build_modify_expr (lhs, modifycode, rhs)
tree lhs;
@@ -5599,24 +5702,18 @@ build_modify_expr (lhs, modifycode, rhs)
tree olhs = lhs;
/* Avoid duplicate error messages from operands that had errors. */
- if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK)
+ if (lhs == error_mark_node || rhs == error_mark_node)
return error_mark_node;
/* Types that aren't fully specified cannot be used in assignments. */
lhs = require_complete_type (lhs);
- /* Decide early if we are going to protect RHS from GC
- before assigning it to LHS. */
- if (type_needs_gc_entry (TREE_TYPE (rhs))
- && ! value_safe_from_gc (lhs, rhs))
- rhs = protect_value_from_gc (lhs, rhs);
-
newrhs = rhs;
/* Handle assignment to signature pointers/refs. */
- if (TYPE_LANG_SPECIFIC (lhstype) &&
- (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype)))
+ if (TYPE_LANG_SPECIFIC (lhstype)
+ && (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype)))
{
return build_signature_pointer_constructor (lhs, rhs);
}
@@ -5630,7 +5727,8 @@ build_modify_expr (lhs, modifycode, rhs)
case PREINCREMENT_EXPR:
if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)))
lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs),
- stabilize_reference (TREE_OPERAND (lhs, 0)));
+ stabilize_reference (TREE_OPERAND (lhs, 0)),
+ TREE_OPERAND (lhs, 1));
return build (COMPOUND_EXPR, lhstype,
lhs,
build_modify_expr (TREE_OPERAND (lhs, 0),
@@ -5640,14 +5738,14 @@ build_modify_expr (lhs, modifycode, rhs)
case COMPOUND_EXPR:
newrhs = build_modify_expr (TREE_OPERAND (lhs, 1),
modifycode, rhs);
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype,
TREE_OPERAND (lhs, 0), newrhs);
case MODIFY_EXPR:
newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs);
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
return build (COMPOUND_EXPR, lhstype, lhs, newrhs);
@@ -5660,18 +5758,18 @@ build_modify_expr (lhs, modifycode, rhs)
so the code to compute it is only emitted once. */
tree cond
= build_conditional_expr (TREE_OPERAND (lhs, 0),
- build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)),
+ build_modify_expr (cp_convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)),
modifycode, rhs),
- build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
+ build_modify_expr (cp_convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)),
modifycode, rhs));
- if (TREE_CODE (cond) == ERROR_MARK)
+ if (cond == error_mark_node)
return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
return build (COMPOUND_EXPR, TREE_TYPE (lhs),
/* Case to void to suppress warning
from warn_if_unused_value. */
- convert (void_type_node, rhs), cond);
+ cp_convert (void_type_node, rhs), cond);
}
}
@@ -5719,9 +5817,9 @@ build_modify_expr (lhs, modifycode, rhs)
/* Do the default thing */;
else
{
- result = build_method_call (lhs, constructor_name_full (lhstype),
- build_tree_list (NULL_TREE, rhs),
- NULL_TREE, LOOKUP_NORMAL);
+ result = build_method_call (lhs, ctor_identifier,
+ build_expr_list (NULL_TREE, rhs),
+ TYPE_BINFO (lhstype), LOOKUP_NORMAL);
if (result == NULL_TREE)
return error_mark_node;
return result;
@@ -5729,7 +5827,6 @@ build_modify_expr (lhs, modifycode, rhs)
}
else if (modifycode == NOP_EXPR)
{
-#if 1
/* `operator=' is not an inheritable operator. */
if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */;
@@ -5741,10 +5838,8 @@ build_modify_expr (lhs, modifycode, rhs)
else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype)
&& TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs)))
{
- if (warn_synth)
- /* If we care about this, do overload resolution. */
- build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
+ build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
+ lhs, rhs, make_node (NOP_EXPR));
/* Do the default thing */;
}
@@ -5756,46 +5851,6 @@ build_modify_expr (lhs, modifycode, rhs)
return error_mark_node;
return result;
}
-#else
- /* Treat `operator=' as an inheritable operator. */
- if (TYPE_LANG_SPECIFIC (lhstype) && TYPE_GETS_ASSIGNMENT (lhstype))
- {
- tree orig_lhstype = lhstype;
- while (! TYPE_HAS_ASSIGNMENT (lhstype))
- {
- int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (lhstype);
- tree basetype = NULL_TREE;
- for (i = 0; i < n_baseclasses; i++)
- if (TYPE_GETS_ASSIGNMENT (TYPE_BINFO_BASETYPE (lhstype, i)))
- {
- if (basetype != NULL_TREE)
- {
- message_2_types (error, "base classes `%s' and `%s' both have operator ='",
- basetype,
- TYPE_BINFO_BASETYPE (lhstype, i));
- return error_mark_node;
- }
- basetype = TYPE_BINFO_BASETYPE (lhstype, i);
- }
- lhstype = basetype;
- }
- if (orig_lhstype != lhstype)
- {
- lhs = build_indirect_ref (convert_pointer_to (lhstype,
- build_unary_op (ADDR_EXPR, lhs, 0)), NULL_PTR);
- if (lhs == error_mark_node)
- {
- cp_error ("conversion to private basetype `%T'", lhstype);
- return error_mark_node;
- }
- }
- result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
- if (result == NULL_TREE)
- return error_mark_node;
- return result;
- }
-#endif
lhstype = olhstype;
}
else if (PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE))
@@ -5807,13 +5862,13 @@ build_modify_expr (lhs, modifycode, rhs)
if (build_default_binary_type_conversion (modifycode, &lhs_tmp, &rhs_tmp))
{
lhs = stabilize_reference (lhs_tmp);
- /* Forget is was ever anything else. */
+ /* Forget it was ever anything else. */
olhstype = lhstype = TREE_TYPE (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs_tmp, 1);
}
else
{
- cp_error ("no match for `%O(%#T, %#T)'", modifycode,
+ cp_error ("no match for `%Q(%#T, %#T)'", modifycode,
TREE_TYPE (lhs), TREE_TYPE (rhs));
return error_mark_node;
}
@@ -5822,6 +5877,12 @@ build_modify_expr (lhs, modifycode, rhs)
{
lhs = stabilize_reference (lhs);
newrhs = build_binary_op (modifycode, lhs, rhs, 1);
+ if (newrhs == error_mark_node)
+ {
+ cp_error (" in evaluation of `%Q(%#T, %#T)'", modifycode,
+ TREE_TYPE (lhs), TREE_TYPE (rhs));
+ return error_mark_node;
+ }
}
/* Handle a cast used as an "lvalue".
@@ -5848,15 +5909,18 @@ build_modify_expr (lhs, modifycode, rhs)
{
tree inner_lhs = TREE_OPERAND (lhs, 0);
tree result;
- if (! lvalue_p (lhs) && pedantic)
- pedwarn ("cast to non-reference type used as lvalue");
+
+ /* WP 5.4.1: The result is an lvalue if T is a reference type,
+ otherwise the result is an rvalue. */
+ if (! lvalue_p (lhs))
+ pedwarn ("ANSI C++ forbids cast to non-reference type used as lvalue");
result = build_modify_expr (inner_lhs, NOP_EXPR,
- convert (TREE_TYPE (inner_lhs),
- convert (lhstype, newrhs)));
- if (TREE_CODE (result) == ERROR_MARK)
+ cp_convert (TREE_TYPE (inner_lhs),
+ cp_convert (lhstype, newrhs)));
+ if (result == error_mark_node)
return result;
- return convert (TREE_TYPE (lhs), result);
+ return cp_convert (TREE_TYPE (lhs), result);
}
}
@@ -5907,7 +5971,7 @@ build_modify_expr (lhs, modifycode, rhs)
}
/* check to see if there is an assignment to `this' */
- if (lhs == current_class_decl)
+ if (lhs == current_class_ptr)
{
if (flag_this_is_variable > 0
&& DECL_NAME (current_function_decl) != NULL_TREE
@@ -5959,104 +6023,6 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_SIDE_EFFECTS (newrhs))
newrhs = stabilize_reference (newrhs);
-#if 0
- /* This is now done by generating X(X&) and operator=(X&). */
- /* C++: The semantics of C++ differ from those of C when an
- assignment of an aggregate is desired. Assignment in C++ is
- now defined as memberwise assignment of non-static members
- and base class objects. This rule applies recursively
- until a member of a built-in type is found.
-
- Also, we cannot do a bit-wise copy of aggregates which
- contain virtual function table pointers. Those
- pointer values must be preserved through the copy.
- However, this is handled in expand_expr, and not here.
- This is because much better code can be generated at
- that stage than this one. */
- if (TREE_CODE (lhstype) == RECORD_TYPE
- && ! TYPE_PTRMEMFUNC_P (lhstype)
- && (TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))
- || (TREE_CODE (TREE_TYPE (newrhs)) == RECORD_TYPE
- && UNIQUELY_DERIVED_FROM_P (lhstype, TREE_TYPE (newrhs)))))
- {
- tree vbases = CLASSTYPE_VBASECLASSES (lhstype);
- tree lhs_addr = build_unary_op (ADDR_EXPR, lhs, 0);
- tree rhs_addr;
-
- /* Memberwise assignment would cause NEWRHS to be
- evaluated for every member that gets assigned.
- By wrapping side-effecting exprs in a SAVE_EXPR,
- NEWRHS will only be evaluated once. */
- if (IS_AGGR_TYPE (TREE_TYPE (newrhs))
- && TREE_SIDE_EFFECTS (newrhs)
- /* This are things we don't have to save. */
- && TREE_CODE (newrhs) != COND_EXPR
- && TREE_CODE (newrhs) != TARGET_EXPR
- && TREE_CODE (newrhs) != WITH_CLEANUP_EXPR)
- /* Call `break_out_cleanups' on NEWRHS in case there are cleanups.
- If NEWRHS is a CALL_EXPR that needs a cleanup, failure to do so
- will result in expand_expr expanding the call without knowing
- that it should run the cleanup. */
- newrhs = save_expr (break_out_cleanups (newrhs));
-
- if (TREE_CODE (newrhs) == COND_EXPR)
- rhs_addr = rationalize_conditional_expr (ADDR_EXPR, newrhs);
- else
- rhs_addr = build_unary_op (ADDR_EXPR, newrhs, 0);
-
- result = tree_cons (NULL_TREE,
- convert (build_reference_type (lhstype), lhs),
- NULL_TREE);
-
- if (! comptypes (TREE_TYPE (lhs_addr), TREE_TYPE (rhs_addr), 1))
- rhs_addr = convert_pointer_to (TREE_TYPE (TREE_TYPE (lhs_addr)), rhs_addr);
- {
- tree noncopied_parts = NULL_TREE;
-
- if (TYPE_NONCOPIED_PARTS (lhstype) != 0)
- noncopied_parts = init_noncopied_parts (lhs,
- TYPE_NONCOPIED_PARTS (lhstype));
- while (noncopied_parts != 0)
- {
- result = tree_cons (NULL_TREE,
- build_modify_expr (convert (ptr_type_node, TREE_VALUE (noncopied_parts)),
- NOP_EXPR,
- TREE_PURPOSE (noncopied_parts)),
- result);
- noncopied_parts = TREE_CHAIN (noncopied_parts);
- }
- }
- /* Once we have our hands on an address, we must change NEWRHS
- to work from there. Otherwise we can get multiple evaluations
- of NEWRHS. */
- if (TREE_CODE (newrhs) != SAVE_EXPR)
- newrhs = build_indirect_ref (rhs_addr, NULL_PTR);
-
- while (vbases)
- {
- tree elt_lhs = convert_pointer_to (vbases, lhs_addr);
- tree elt_rhs = convert_pointer_to (vbases, rhs_addr);
- result
- = tree_cons (NULL_TREE,
- build_modify_expr_1 (build_indirect_ref (elt_lhs, NULL_PTR),
- modifycode,
- build_indirect_ref (elt_rhs, NULL_PTR),
- TYPE_BINFO (lhstype)),
- result);
- if (TREE_VALUE (result) == error_mark_node)
- return error_mark_node;
- vbases = TREE_CHAIN (vbases);
- }
- result = tree_cons (NULL_TREE,
- build_modify_expr_1 (lhs,
- modifycode,
- newrhs,
- TYPE_BINFO (lhstype)),
- result);
- return build_compound_expr (result);
- }
-#endif
-
/* Convert new value to destination type. */
if (TREE_CODE (lhstype) == ARRAY_TYPE)
@@ -6115,16 +6081,7 @@ build_modify_expr (lhs, modifycode, rhs)
}
else
{
-#if 0
- if (IS_AGGR_TYPE (lhstype))
- {
- if (result = build_opfncall (MODIFY_EXPR,
- LOOKUP_NORMAL, lhs, newrhs,
- make_node (NOP_EXPR)))
- return result;
- }
-#endif
- /* Avoid warnings on enum bit fields. */
+ /* Avoid warnings on enum bit fields. */
if (TREE_CODE (olhstype) == ENUMERAL_TYPE
&& TREE_CODE (lhstype) == INTEGER_TYPE)
{
@@ -6137,17 +6094,18 @@ build_modify_expr (lhs, modifycode, rhs)
NULL_TREE, 0);
if (TREE_CODE (newrhs) == CALL_EXPR
&& TYPE_NEEDS_CONSTRUCTING (lhstype))
- newrhs = build_cplus_new (lhstype, newrhs, 0);
+ newrhs = build_cplus_new (lhstype, newrhs);
/* Can't initialize directly from a TARGET_EXPR, since that would
cause the lhs to be constructed twice, and possibly result in
accidental self-initialization. So we force the TARGET_EXPR to be
- expanded. expand_expr should really do this by itself. */
+ expanded without a target. */
if (TREE_CODE (newrhs) == TARGET_EXPR)
- newrhs = expand_target_expr (newrhs);
+ newrhs = build (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs,
+ TREE_OPERAND (newrhs, 0));
}
- if (TREE_CODE (newrhs) == ERROR_MARK)
+ if (newrhs == error_mark_node)
return error_mark_node;
if (TREE_CODE (newrhs) == COND_EXPR)
@@ -6158,7 +6116,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (TREE_SIDE_EFFECTS (lhs))
cond = build_compound_expr (tree_cons
(NULL_TREE, lhs,
- build_tree_list (NULL_TREE, cond)));
+ build_expr_list (NULL_TREE, cond)));
/* Cannot have two identical lhs on this one tree (result) as preexpand
calls will rip them out and fill in RTL for them, but when the
@@ -6178,45 +6136,17 @@ build_modify_expr (lhs, modifycode, rhs)
result
= build (COND_EXPR, result_type, cond,
build_modify_expr (lhs, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 1))),
+ cp_convert (result_type,
+ TREE_OPERAND (newrhs, 1))),
build_modify_expr (lhs1, modifycode,
- convert (result_type,
- TREE_OPERAND (newrhs, 2))));
+ cp_convert (result_type,
+ TREE_OPERAND (newrhs, 2))));
}
}
- else if (modifycode != INIT_EXPR && TREE_CODE (newrhs) == WITH_CLEANUP_EXPR)
- {
- tree cleanup = TREE_OPERAND (newrhs, 2);
- tree slot;
-
- /* Finish up by running cleanups and having the "value" of the lhs. */
- tree exprlist = tree_cons (NULL_TREE, cleanup,
- build_tree_list (NULL_TREE, lhs));
- newrhs = TREE_OPERAND (newrhs, 0);
- if (TREE_CODE (newrhs) == TARGET_EXPR)
- slot = TREE_OPERAND (newrhs, 0);
- else if (TREE_CODE (newrhs) == ADDR_EXPR)
- {
- /* Bad but valid. */
- slot = newrhs;
- warning ("address taken of temporary object");
- }
- else
- my_friendly_abort (118);
-
- /* Copy the value computed in SLOT into LHS. */
- exprlist = tree_cons (NULL_TREE,
- build_modify_expr (lhs, modifycode, slot),
- exprlist);
- /* Evaluate the expression that needs CLEANUP. This will
- compute the value into SLOT. */
- exprlist = tree_cons (NULL_TREE, newrhs, exprlist);
- result = convert (lhstype, build_compound_expr (exprlist));
- }
else
result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
lhstype, lhs, newrhs);
+
TREE_SIDE_EFFECTS (result) = 1;
/* If we got the LHS in a different type for storing in,
@@ -6227,7 +6157,7 @@ build_modify_expr (lhs, modifycode, rhs)
if (olhstype == TREE_TYPE (result))
return result;
/* Avoid warnings converting integral types back into enums
- for enum bit fields. */
+ for enum bit fields. */
if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
&& TREE_CODE (olhstype) == ENUMERAL_TYPE)
{
@@ -6239,6 +6169,25 @@ build_modify_expr (lhs, modifycode, rhs)
NULL_TREE, 0);
}
+tree
+build_x_modify_expr (lhs, modifycode, rhs)
+ tree lhs;
+ enum tree_code modifycode;
+ tree rhs;
+{
+ if (processing_template_decl)
+ return build_min_nt (MODOP_EXPR, lhs,
+ build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs);
+
+ if (modifycode != NOP_EXPR)
+ {
+ tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
+ make_node (modifycode));
+ if (rval)
+ return rval;
+ }
+ return build_modify_expr (lhs, modifycode, rhs);
+}
/* Return 0 if EXP is not a valid lvalue in this language
even though `lvalue_or_else' would accept it. */
@@ -6253,6 +6202,7 @@ language_lvalue_valid (exp)
/* Get difference in deltas for different pointer to member function
types. Return integer_zero_node, if FROM cannot be converted to a
TO type. If FORCE is true, then allow reverse conversions as well. */
+
static tree
get_delta_difference (from, to, force)
tree from, to;
@@ -6280,27 +6230,34 @@ get_delta_difference (from, to, force)
if (!force)
{
error_not_base_type (from, to);
- error (" in pointer to member function conversion");
+ error (" in pointer to member conversion");
return delta;
}
binfo = get_binfo (to, from, 1);
if (binfo == error_mark_node)
{
- error (" in pointer to member function conversion");
+ if (!force)
+ error (" in pointer to member conversion");
return delta;
}
if (binfo == 0)
{
- error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
+ if (!force)
+ cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
return delta;
}
if (TREE_VIA_VIRTUAL (binfo))
{
+ binfo = binfo_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (from));
warning ("pointer to member conversion to virtual base class will only work if you are very careful");
}
+ delta = BINFO_OFFSET (binfo);
+ delta = cp_convert (ptrdiff_type_node, delta);
+
return build_binary_op (MINUS_EXPR,
integer_zero_node,
- BINFO_OFFSET (binfo), 1);
+ delta, 1);
}
if (TREE_VIA_VIRTUAL (binfo))
{
@@ -6309,6 +6266,79 @@ get_delta_difference (from, to, force)
return BINFO_OFFSET (binfo);
}
+static tree
+build_ptrmemfunc1 (type, delta, idx, pfn, delta2)
+ tree type, delta, idx, pfn, delta2;
+{
+ tree u;
+
+#if 0
+ /* This is the old way we did it. We want to avoid calling
+ digest_init, so that it can give an error if we use { } when
+ initializing a pointer to member function. */
+
+ if (pfn)
+ {
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ expr_tree_cons (pfn_identifier, pfn, NULL_TREE));
+ }
+ else
+ {
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ expr_tree_cons (delta2_identifier, delta2, NULL_TREE));
+ }
+
+ u = build_nt (CONSTRUCTOR, NULL_TREE,
+ expr_tree_cons (NULL_TREE, delta,
+ expr_tree_cons (NULL_TREE, idx,
+ expr_tree_cons (NULL_TREE, u, NULL_TREE))));
+
+ return digest_init (type, u, (tree*)0);
+#else
+ tree delta_field, idx_field, pfn_or_delta2_field, pfn_field, delta2_field;
+ tree subtype;
+ int allconstant, allsimple;
+
+ delta_field = TYPE_FIELDS (type);
+ idx_field = TREE_CHAIN (delta_field);
+ pfn_or_delta2_field = TREE_CHAIN (idx_field);
+ subtype = TREE_TYPE (pfn_or_delta2_field);
+ pfn_field = TYPE_FIELDS (subtype);
+ delta2_field = TREE_CHAIN (pfn_field);
+
+ if (pfn)
+ {
+ allconstant = TREE_CONSTANT (pfn);
+ allsimple = !! initializer_constant_valid_p (pfn, TREE_TYPE (pfn));
+ u = expr_tree_cons (pfn_field, pfn, NULL_TREE);
+ }
+ else
+ {
+ delta2 = convert_and_check (delta_type_node, delta2);
+ allconstant = TREE_CONSTANT (delta2);
+ allsimple = !! initializer_constant_valid_p (delta2, TREE_TYPE (delta2));
+ u = expr_tree_cons (delta2_field, delta2, NULL_TREE);
+ }
+
+ delta = convert_and_check (delta_type_node, delta);
+ idx = convert_and_check (delta_type_node, idx);
+
+ allconstant = allconstant && TREE_CONSTANT (delta) && TREE_CONSTANT (idx);
+ allsimple = allsimple
+ && initializer_constant_valid_p (delta, TREE_TYPE (delta))
+ && initializer_constant_valid_p (idx, TREE_TYPE (idx));
+
+ u = build (CONSTRUCTOR, subtype, NULL_TREE, u);
+ u = expr_tree_cons (delta_field, delta,
+ expr_tree_cons (idx_field, idx,
+ expr_tree_cons (pfn_or_delta2_field, u, NULL_TREE)));
+ u = build (CONSTRUCTOR, type, NULL_TREE, u);
+ TREE_CONSTANT (u) = allconstant;
+ TREE_STATIC (u) = allconstant && allsimple;
+ return u;
+#endif
+}
+
/* Build a constructor for a pointer to member function. It can be
used to initialize global variables, local variable, or used
as a value in expressions. TYPE is the POINTER to METHOD_TYPE we
@@ -6325,131 +6355,81 @@ build_ptrmemfunc (type, pfn, force)
tree type, pfn;
int force;
{
- tree index = integer_zero_node;
+ tree idx = integer_zero_node;
tree delta = integer_zero_node;
tree delta2 = integer_zero_node;
tree vfield_offset;
- tree npfn;
- tree u;
+ tree npfn = NULL_TREE;
- /* Handle multiple conversions of pointer to member functions. */
+ /* Handle multiple conversions of pointer to member functions. */
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
{
- tree ndelta, ndelta2, nindex;
+ tree ndelta, ndelta2;
+ tree e1, e2, e3, n;
+
/* Is is already the right type? */
-#if 0
- /* Sorry, can't do this, the backend is too stupid. */
- if (TYPE_METHOD_BASETYPE (TREE_TYPE (type))
- == TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))))
- {
- if (type != TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
- {
- npfn = build1 (NOP_EXPR, TYPE_GET_PTRMEMFUNC_TYPE (type), pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- }
- return pfn;
- }
-#else
if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
return pfn;
-#endif
- if (TREE_CODE (pfn) != CONSTRUCTOR)
- {
- tree e1, e2, e3;
- ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, 0, 0));
- ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
- index = build_component_ref (pfn, index_identifier, 0, 0);
- delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
- TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
- force);
- delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
- delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1);
- e1 = fold (build (GT_EXPR, boolean_type_node, index, integer_zero_node));
+ ndelta = cp_convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0));
+ ndelta2 = cp_convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn));
+ idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0);
+
+ n = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
+ TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
+ force);
+
+ delta = build_binary_op (PLUS_EXPR, ndelta, n, 1);
+ delta2 = build_binary_op (PLUS_EXPR, ndelta2, n, 1);
+ e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, index,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e2 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ e2 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx,
+ NULL_TREE, delta2);
- pfn = PFN_FROM_PTRMEMFUNC (pfn);
- npfn = build1 (NOP_EXPR, type, pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+ pfn = PFN_FROM_PTRMEMFUNC (pfn);
+ npfn = build1 (NOP_EXPR, type, pfn);
+ TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
- u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, index,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
- return build_conditional_expr (e1, e2, e3);
- }
-
- ndelta = TREE_VALUE (CONSTRUCTOR_ELTS (pfn));
- nindex = TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn)));
- npfn = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn))));
- npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn));
- if (integer_zerop (nindex))
- pfn = integer_zero_node;
- else if (integer_zerop (fold (size_binop (PLUS_EXPR, nindex, integer_one_node))))
- {
- tree e3;
- delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
- TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
- force);
- delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1);
- pfn = build1 (NOP_EXPR, type, npfn);
- TREE_CONSTANT (pfn) = TREE_CONSTANT (npfn);
-
- u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, nindex,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
- return e3;
- }
- else
- {
- sorry ("value casting of variable nonnull pointer to member functions not supported");
- return error_mark_node;
- }
+ e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn,
+ NULL_TREE);
+ return build_conditional_expr (e1, e2, e3);
}
- /* Handle null pointer to member function conversions. */
+ /* Handle null pointer to member function conversions. */
if (integer_zerop (pfn))
{
- pfn = build_c_cast (type, integer_zero_node, 0);
- u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node,
- tree_cons (NULL_TREE, integer_zero_node,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ pfn = build_c_cast (type, integer_zero_node);
+ return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type),
+ integer_zero_node, integer_zero_node,
+ pfn, NULL_TREE);
}
if (TREE_CODE (pfn) == TREE_LIST
|| (TREE_CODE (pfn) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
- {
- pfn = instantiate_type (type, pfn, 1);
- if (pfn == error_mark_node)
- return error_mark_node;
- if (TREE_CODE (pfn) != ADDR_EXPR)
- pfn = build_unary_op (ADDR_EXPR, pfn, 0);
- }
+ return instantiate_type (type, pfn, 1);
- /* Allow pointer to member conversions here. */
+ /* Allow pointer to member conversions here. */
delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
force);
delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1);
+#if 0
+ /* We need to check the argument types to see if they are compatible
+ (any const or volatile violations. */
+ something like this:
+ comptype (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (type))),
+ TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))), ?);
+#endif
+
if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
warning ("assuming pointer to member function is non-virtual");
if (TREE_CODE (TREE_OPERAND (pfn, 0)) == FUNCTION_DECL
&& DECL_VINDEX (TREE_OPERAND (pfn, 0)))
{
- /* Find the offset to the vfield pointer in the object. */
+ /* Find the offset to the vfield pointer in the object. */
vfield_offset = get_binfo (DECL_CONTEXT (TREE_OPERAND (pfn, 0)),
DECL_CLASS_CONTEXT (TREE_OPERAND (pfn, 0)),
0);
@@ -6457,25 +6437,26 @@ build_ptrmemfunc (type, pfn, force)
delta2 = size_binop (PLUS_EXPR, vfield_offset, delta2);
/* Map everything down one to make room for the null pointer to member. */
- index = size_binop (PLUS_EXPR,
- DECL_VINDEX (TREE_OPERAND (pfn, 0)),
- integer_one_node);
- u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
+ idx = size_binop (PLUS_EXPR,
+ DECL_VINDEX (TREE_OPERAND (pfn, 0)),
+ integer_one_node);
}
else
{
- index = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+ idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
- npfn = build1 (NOP_EXPR, type, pfn);
- TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
-
- u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
+ if (type == TREE_TYPE (pfn))
+ {
+ npfn = pfn;
+ }
+ else
+ {
+ npfn = build1 (NOP_EXPR, type, pfn);
+ TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+ }
}
- u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
- tree_cons (NULL_TREE, index,
- tree_cons (NULL_TREE, u, NULL_TREE))));
- return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+ return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn, delta2);
}
/* Convert value RHS to type TYPE as preparation for an assignment
@@ -6561,8 +6542,10 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
/* Arithmetic types all interconvert. */
- if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE)
- && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE))
+ if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE
+ || codel == COMPLEX_TYPE)
+ && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE
+ || coder == COMPLEX_TYPE))
{
/* But we should warn if assigning REAL_TYPE to INTEGER_TYPE. */
if (coder == REAL_TYPE && codel == INTEGER_TYPE)
@@ -6600,7 +6583,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
|| (coder == ENUMERAL_TYPE
&& (INTEGRAL_CODE_P (codel) || codel == REAL_TYPE)))
{
- return cp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
+ return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
}
/* Conversions among pointers */
else if (codel == POINTER_TYPE
@@ -6676,13 +6659,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
- if (ctt < 0)
+ if (ctt < 0 && TYPE_MAIN_VARIANT (ttl) != TYPE_MAIN_VARIANT (ttr))
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
rhstype, type);
if (TYPE_MAIN_VARIANT (ttl) != void_type_node
&& TYPE_MAIN_VARIANT (ttr) == void_type_node
- && rhs != null_pointer_node)
+ && ! null_ptr_cst_p (rhs))
{
if (coder == RECORD_TYPE)
cp_pedwarn ("implicit conversion of signature pointer to type `%T'",
@@ -6733,31 +6716,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
}
}
}
- else if (TREE_CODE (ttr) == OFFSET_TYPE
- && TREE_CODE (ttl) != OFFSET_TYPE)
- {
- /* Normally, pointers to different type codes (other
- than void) are not compatible, but we perform
- some type instantiation if that resolves the
- ambiguity of (X Y::*) and (X *). */
-
- if (current_class_decl)
- {
- if (TREE_CODE (rhs) == INTEGER_CST)
- {
- rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)),
- current_class_decl, rhs);
- return convert_for_assignment (type, rhs,
- errtype, fndecl, parmnum);
- }
- }
- if (TREE_CODE (ttl) == METHOD_TYPE)
- error ("%s between pointer-to-method and pointer-to-member types",
- errtype);
- else
- error ("%s between pointer and pointer-to-member types", errtype);
- return error_mark_node;
- }
else
{
int add_quals = 0, const_parity = 0, volatile_parity = 0;
@@ -6769,8 +6727,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
for (; ; ttl = TREE_TYPE (ttl), ttr = TREE_TYPE (ttr))
{
nptrs -= 1;
- const_parity |= TYPE_READONLY (ttl) < TYPE_READONLY (ttr);
- volatile_parity |= TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr);
+ const_parity |= (TYPE_READONLY (ttl) < TYPE_READONLY (ttr));
+ volatile_parity |= (TYPE_VOLATILE (ttl) < TYPE_VOLATILE (ttr));
if (! left_const
&& (TYPE_READONLY (ttl) > TYPE_READONLY (ttr)
@@ -6849,24 +6807,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
cp_warning ("\t`%T' != `%T'", type, rhstype);
}
}
- else if (TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (119);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
- else if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
- {
- /* When does this happen? */
- my_friendly_abort (120);
- /* Conversion of a pointer-to-member type to void *. */
- rhs = build_unary_op (ADDR_EXPR, rhs, 0);
- TREE_TYPE (rhs) = type;
- return rhs;
- }
else
{
if (fndecl)
@@ -6877,7 +6817,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return error_mark_node;
}
}
- return convert (type, rhs);
+ return cp_convert (type, rhs);
}
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
{
@@ -6891,9 +6831,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
- return convert (type, rhs);
}
- return null_pointer_node;
+ return cp_convert (type, rhs);
}
else if (codel == INTEGER_TYPE
&& (coder == POINTER_TYPE
@@ -6908,7 +6847,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
- return convert (type, rhs);
+ return cp_convert (type, rhs);
}
else if (codel == BOOLEAN_TYPE
&& (coder == POINTER_TYPE
@@ -6916,7 +6855,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
&& (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
- return convert (type, rhs);
+ return cp_convert (type, rhs);
/* C++ */
else if (((coder == POINTER_TYPE
@@ -6936,7 +6875,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else if (ctt == 0)
cp_error ("%s to `%T' from `%T'", errtype, ttl, ttr);
- /* compatible pointer to member functions. */
+ /* compatible pointer to member functions. */
return build_ptrmemfunc (ttl, rhs, 0);
}
else if (codel == ERROR_MARK || coder == ERROR_MARK)
@@ -6954,7 +6893,14 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
return nrhs;
}
else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
- return convert (type, rhs);
+ return cp_convert (type, rhs);
+ /* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
+ else if (TREE_CODE (type) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
+ || TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
+ && TREE_TYPE (rhs)
+ && TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
+ return cp_convert (type, rhs);
cp_error ("%s to `%T' from `%T'", errtype, type, rhstype);
return error_mark_node;
@@ -6975,6 +6921,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
exist, an ambiguity exists.
If flags doesn't include LOOKUP_COMPLAIN, don't complain about anything. */
+
tree
convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
tree exp, type, rhs;
@@ -7029,12 +6976,6 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (coder == ERROR_MARK)
return error_mark_node;
-#if 0
- /* This is *not* the quick way out! It is the way to disaster. */
- if (type == rhstype)
- goto converted;
-#endif
-
/* We accept references to incomplete types, so we can
return here before checking if RHS is of complete type. */
@@ -7069,6 +7010,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (TREE_CODE (rhstype) == REFERENCE_TYPE)
rhstype = TREE_TYPE (rhstype);
+ type = complete_type (type);
+
if (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))
return build_signature_pointer_constructor (type, rhs);
@@ -7076,6 +7019,9 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (IS_AGGR_TYPE (type)
&& (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
{
+ if (flag_ansi_overloading)
+ return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
+
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
{
/* This is sufficient to perform initialization. No need,
@@ -7084,7 +7030,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
cleanups if it is used. */
if (TREE_CODE (rhs) == CALL_EXPR)
{
- rhs = build_cplus_new (type, rhs, 0);
+ rhs = build_cplus_new (type, rhs);
return rhs;
}
/* Handle the case of default parameter initialization and
@@ -7101,7 +7047,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
= build_unary_op (ADDR_EXPR, exp, 0);
}
else
- rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0), 0);
+ rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0));
return rhs;
}
else if (TYPE_HAS_TRIVIAL_INIT_REF (type))
@@ -7112,8 +7058,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
{
if (TYPE_HAS_INIT_REF (type))
{
- tree init = build_method_call (exp, constructor_name_full (type),
- build_tree_list (NULL_TREE, rhs),
+ tree init = build_method_call (exp, ctor_identifier,
+ build_expr_list (NULL_TREE, rhs),
TYPE_BINFO (type), LOOKUP_NORMAL);
if (init == error_mark_node)
@@ -7121,7 +7067,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (exp == 0)
{
- exp = build_cplus_new (type, init, 0);
+ exp = build_cplus_new (type, init);
return exp;
}
@@ -7145,7 +7091,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
return rhs;
}
- return cp_convert (type, rhs, CONV_OLD_CONVERT, flags);
+ return ocp_convert (type, rhs, CONV_OLD_CONVERT,
+ flags | LOOKUP_NO_CONVERSION);
}
if (type == TREE_TYPE (rhs))
@@ -7195,7 +7142,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)),
- const0_rtx, VOIDmode, 0);
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
free_temp_slots ();
}
/* Detect modification of read-only values.
@@ -7234,8 +7181,6 @@ c_expand_return (retval)
extern tree dtor_label, ctor_label;
tree result = DECL_RESULT (current_function_decl);
tree valtype = TREE_TYPE (result);
- register int use_temp = 0;
- int returns_value = 1;
if (TREE_THIS_VOLATILE (current_function_decl))
warning ("function declared `noreturn' has a `return' statement");
@@ -7246,6 +7191,12 @@ c_expand_return (retval)
return;
}
+ if (processing_template_decl)
+ {
+ add_tree (build_min_nt (RETURN_STMT, retval));
+ return;
+ }
+
if (retval == NULL_TREE)
{
/* A non-named return value does not count. */
@@ -7258,7 +7209,7 @@ c_expand_return (retval)
}
if (DECL_CONSTRUCTOR_P (current_function_decl))
- retval = current_class_decl;
+ retval = current_class_ptr;
else if (DECL_NAME (result) != NULL_TREE
&& TREE_CODE (valtype) != VOID_TYPE)
retval = result;
@@ -7283,82 +7234,29 @@ c_expand_return (retval)
}
}
else if (DECL_CONSTRUCTOR_P (current_function_decl)
- && retval != current_class_decl)
+ && retval != current_class_ptr)
{
- error ("return from a constructor: use `this = ...' instead");
- retval = current_class_decl;
+ if (flag_this_is_variable)
+ error ("return from a constructor: use `this = ...' instead");
+ else
+ error ("return from a constructor");
+ retval = current_class_ptr;
}
+ /* Effective C++ rule 15. See also start_function. */
+ if (warn_ecpp
+ && DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR]
+ && retval != current_class_ref)
+ cp_warning ("`operator=' should return a reference to `*this'");
+
if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
- /* We do this here so we'll avoid a warning about how the function
- "may or may not return a value" in finish_function. */
- returns_value = 0;
-
- if (retval)
+ if ((pedantic && ! DECL_ARTIFICIAL (current_function_decl))
+ || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("`return' with a value, in function returning void");
expand_return (retval);
- }
- /* Add some useful error checking for C++. */
- else if (TREE_CODE (valtype) == REFERENCE_TYPE)
- {
- tree whats_returned;
- tree tmp_result = result;
-
- /* Don't initialize directly into a non-BLKmode retval, since that
- could lose when being inlined by another caller. (GCC can't
- read the function return register in an inline function when
- the return value is being ignored). */
- if (result && TYPE_MODE (TREE_TYPE (tmp_result)) != BLKmode)
- tmp_result = 0;
-
- /* convert to reference now, so we can give error if we
- return an reference to a non-lvalue. */
- retval = convert_for_initialization (tmp_result, valtype, retval,
- LOOKUP_NORMAL, "return",
- NULL_TREE, 0);
-
- /* Sort through common things to see what it is
- we are returning. */
- whats_returned = retval;
- if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 1);
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- whats_returned = TREE_OPERAND (whats_returned, 0);
- }
- if (TREE_CODE (whats_returned) == ADDR_EXPR)
- {
- whats_returned = TREE_OPERAND (whats_returned, 0);
- while (TREE_CODE (whats_returned) == NEW_EXPR
- || TREE_CODE (whats_returned) == TARGET_EXPR
- || TREE_CODE (whats_returned) == WITH_CLEANUP_EXPR)
- {
- /* Get the target. */
- whats_returned = TREE_OPERAND (whats_returned, 0);
- warning ("returning reference to temporary");
- }
- }
-
- if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
- {
- if (TEMP_NAME_P (DECL_NAME (whats_returned)))
- warning ("reference to non-lvalue returned");
- else if (! TREE_STATIC (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned)))
- cp_warning_at ("reference to local variable `%D' returned", whats_returned);
- }
- }
- else if (TREE_CODE (retval) == ADDR_EXPR)
- {
- tree whats_returned = TREE_OPERAND (retval, 0);
-
- if (TREE_CODE (whats_returned) == VAR_DECL
- && DECL_NAME (whats_returned)
- && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
- && !TREE_STATIC (whats_returned))
- cp_warning_at ("address of local variable `%D' returned", whats_returned);
+ return;
}
/* Now deal with possible C++ hair:
@@ -7369,153 +7267,112 @@ c_expand_return (retval)
(3) If an X(X&) constructor is defined, the return
value must be returned via that. */
- /* If we're returning in a register, we can't initialize the
- return value from a TARGET_EXPR. */
- if (TREE_CODE (retval) == TARGET_EXPR
- && TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype)
- && ! current_function_returns_struct)
- retval = expand_target_expr (retval);
-
if (retval == result
- /* Watch out for constructors, which "return" aggregates
- via initialization, but which otherwise "return" a pointer. */
|| DECL_CONSTRUCTOR_P (current_function_decl))
+ /* It's already done for us. */;
+ else if (TREE_TYPE (retval) == void_type_node)
{
- /* This is just an error--it's already been reported. */
- if (TYPE_SIZE (valtype) == NULL_TREE)
- return;
-
- if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
- {
- retval = get_temp_regvar (valtype, retval);
- use_temp = obey_regdecls;
- }
- }
- else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct)
- {
- expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING);
- expand_cleanups_to (NULL_TREE);
- DECL_INITIAL (result) = NULL_TREE;
+ pedwarn ("return of void value in function returning non-void");
+ expand_expr_stmt (retval);
retval = 0;
}
else
{
- if (TYPE_MODE (valtype) == VOIDmode)
+ retval = convert_for_initialization
+ (NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING,
+ "return", NULL_TREE, 0);
+
+ if (retval == error_mark_node)
{
- if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode
- && warn_return_type)
- warning ("return of void value in function returning non-void");
- expand_expr_stmt (retval);
- retval = 0;
- result = 0;
+ /* Avoid warning about control reaching end of function. */
+ expand_null_return ();
+ return;
}
- else if (TYPE_MODE (valtype) != BLKmode
- && any_pending_cleanups (1))
+
+ /* We can't initialize a register from a NEW_EXPR. */
+ else if (! current_function_returns_struct
+ && TREE_CODE (retval) == TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (retval, 1)) == NEW_EXPR)
+ retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
+ TREE_OPERAND (retval, 0));
+
+ /* Add some useful error checking for C++. */
+ else if (TREE_CODE (valtype) == REFERENCE_TYPE)
{
- retval = get_temp_regvar (valtype, retval);
- expand_cleanups_to (NULL_TREE);
- use_temp = obey_regdecls;
- result = 0;
+ tree whats_returned;
+
+ /* Sort through common things to see what it is
+ we are returning. */
+ whats_returned = retval;
+ if (TREE_CODE (whats_returned) == COMPOUND_EXPR)
+ {
+ whats_returned = TREE_OPERAND (whats_returned, 1);
+ if (TREE_CODE (whats_returned) == ADDR_EXPR)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ }
+ while (TREE_CODE (whats_returned) == CONVERT_EXPR
+ || TREE_CODE (whats_returned) == NOP_EXPR)
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ if (TREE_CODE (whats_returned) == ADDR_EXPR)
+ {
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ while (TREE_CODE (whats_returned) == NEW_EXPR
+ || TREE_CODE (whats_returned) == TARGET_EXPR)
+ {
+ /* Get the target. */
+ whats_returned = TREE_OPERAND (whats_returned, 0);
+ warning ("returning reference to temporary");
+ }
+ }
+
+ if (TREE_CODE (whats_returned) == VAR_DECL && DECL_NAME (whats_returned))
+ {
+ if (TEMP_NAME_P (DECL_NAME (whats_returned)))
+ warning ("reference to non-lvalue returned");
+ else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE
+ && ! TREE_STATIC (whats_returned)
+ && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
+ && !TREE_PUBLIC (whats_returned))
+ cp_warning_at ("reference to local variable `%D' returned", whats_returned);
+ }
}
- else
+ else if (TREE_CODE (retval) == ADDR_EXPR)
{
- retval = convert_for_initialization (result, valtype, retval,
- LOOKUP_NORMAL,
- "return", NULL_TREE, 0);
- DECL_INITIAL (result) = NULL_TREE;
+ tree whats_returned = TREE_OPERAND (retval, 0);
+
+ if (TREE_CODE (whats_returned) == VAR_DECL
+ && DECL_NAME (whats_returned)
+ && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
+ && !TREE_STATIC (whats_returned)
+ && !TREE_PUBLIC (whats_returned))
+ cp_warning_at ("address of local variable `%D' returned", whats_returned);
}
- if (retval == error_mark_node)
- return;
}
- emit_queue ();
-
if (retval != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (retval)) == 'd'
&& cond_stack == 0 && loop_stack == 0 && case_stack == 0)
current_function_return_value = retval;
- if (result)
+ if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
{
- /* Everything's great--RETVAL is in RESULT. */
- if (original_result_rtx)
- {
- store_expr (result, original_result_rtx, 0);
- expand_cleanups_to (NULL_TREE);
- use_variable (DECL_RTL (result));
- if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
- expand_goto (ctor_label);
- else
- expand_null_return ();
- }
- else if (retval && retval != result)
- {
- /* Clear this out so the later call to decl_function_context
- won't end up bombing on us. */
- if (DECL_CONTEXT (result) == error_mark_node)
- DECL_CONTEXT (result) = NULL_TREE;
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result),
- retval));
- /* This part _must_ come second, because expand_return looks for
- the INIT_EXPR as the toplevel node only. :-( */
- retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (retval) = 1;
- expand_return (retval);
- }
- else
- expand_return (result);
+ /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */
+ expand_goto (ctor_label);
}
- else
+
+ if (retval && retval != result)
{
- /* We may still need to put RETVAL into RESULT. */
- result = DECL_RESULT (current_function_decl);
- if (original_result_rtx)
- {
- /* Here we have a named return value that went
- into memory. We can compute RETVAL into that. */
- if (retval)
- expand_assignment (result, retval, 0, 0);
- else
- store_expr (result, original_result_rtx, 0);
- result = make_tree (TREE_TYPE (result), original_result_rtx);
- }
- else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
- {
- /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do. */
- expand_goto (ctor_label);
- }
- else if (retval)
- {
- /* Here is where we finally get RETVAL into RESULT.
- `expand_return' does the magic of protecting
- RESULT from cleanups. */
- result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- TREE_SIDE_EFFECTS (result) = 1;
- expand_return (result);
- }
- else if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode)
- expand_return (result);
+ result = build (INIT_EXPR, TREE_TYPE (result), result, retval);
+ TREE_SIDE_EFFECTS (result) = 1;
}
- current_function_returns_value = returns_value;
-#if 0
- /* These wind up after the BARRIER, which causes problems for
- expand_end_binding. What purpose were they supposed to serve? */
- if (original_result_rtx)
- use_variable (original_result_rtx);
- if (use_temp)
- use_variable (DECL_RTL (DECL_RESULT (current_function_decl)));
-#endif
+ expand_start_target_temps ();
- /* One way to clear out cleanups that EXPR might
- generate. Note that this code will really be
- dead code, but that is ok--cleanups that were
- needed were handled by the magic of `return'. */
- expand_cleanups_to (NULL_TREE);
+ expand_return (result);
+
+ expand_end_target_temps ();
+
+ current_function_returns_value = 1;
}
/* Start a C switch statement, testing expression EXP.
@@ -7551,18 +7408,18 @@ c_expand_start_case (exp)
}
else
{
- tree index;
+ tree idx;
exp = default_conversion (exp);
type = TREE_TYPE (exp);
- index = get_unwidened (exp, 0);
+ idx = get_unwidened (exp, 0);
/* We can't strip a conversion from a signed type to an unsigned,
because if we did, int_fits_type_p would do the wrong thing
when checking case values for being in range,
and it's too hard to do the right thing. */
if (TREE_UNSIGNED (TREE_TYPE (exp))
- == TREE_UNSIGNED (TREE_TYPE (index)))
- exp = index;
+ == TREE_UNSIGNED (TREE_TYPE (idx)))
+ exp = idx;
}
expand_start_case
@@ -7574,7 +7431,8 @@ c_expand_start_case (exp)
/* CONSTP remembers whether or not all the intervening pointers in the `to'
type have been const. */
-int
+
+static int
comp_ptr_ttypes_real (to, from, constp)
tree to, from;
int constp;
@@ -7584,6 +7442,11 @@ comp_ptr_ttypes_real (to, from, constp)
if (TREE_CODE (to) != TREE_CODE (from))
return 0;
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to), 1))
+ continue;
+
/* Const and volatile mean something different for function types,
so the usual checks are not appropriate. */
if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
@@ -7607,9 +7470,92 @@ comp_ptr_ttypes_real (to, from, constp)
/* When comparing, say, char ** to char const **, this function takes the
'char *' and 'char const *'. Do not pass non-pointer types to this
function. */
+
int
comp_ptr_ttypes (to, from)
tree to, from;
{
return comp_ptr_ttypes_real (to, from, 1);
}
+
+/* Returns 1 if to and from are (possibly multi-level) pointers to the same
+ type or inheritance-related types, regardless of cv-quals. */
+
+int
+ptr_reasonably_similar (to, from)
+ tree to, from;
+{
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 0;
+
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (to),
+ TYPE_OFFSET_BASETYPE (from), -1))
+ continue;
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return comptypes
+ (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), -1);
+ }
+}
+
+/* Like comp_ptr_ttypes, for const_cast. */
+
+static int
+comp_ptr_ttypes_const (to, from)
+ tree to, from;
+{
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 0;
+
+ if (TREE_CODE (from) == OFFSET_TYPE
+ && comptypes (TYPE_OFFSET_BASETYPE (from),
+ TYPE_OFFSET_BASETYPE (to), 1))
+ continue;
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1);
+ }
+}
+
+/* Like comp_ptr_ttypes, for reinterpret_cast. */
+
+static int
+comp_ptr_ttypes_reinterpret (to, from)
+ tree to, from;
+{
+ int constp = 1;
+
+ for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from))
+ {
+ if (TREE_CODE (from) == OFFSET_TYPE)
+ from = TREE_TYPE (from);
+ if (TREE_CODE (to) == OFFSET_TYPE)
+ to = TREE_TYPE (to);
+
+ if (TREE_CODE (to) != TREE_CODE (from))
+ return 1;
+
+ /* Const and volatile mean something different for function types,
+ so the usual checks are not appropriate. */
+ if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
+ {
+ if (TYPE_READONLY (from) > TYPE_READONLY (to)
+ || TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
+ return 0;
+
+ if (! constp
+ && (TYPE_READONLY (to) > TYPE_READONLY (from)
+ || TYPE_VOLATILE (to) > TYPE_READONLY (from)))
+ return 0;
+ constp &= TYPE_READONLY (to);
+ }
+
+ if (TREE_CODE (to) != POINTER_TYPE)
+ return 1;
+ }
+}
diff --git a/gnu/usr.bin/gcc/cp/typeck2.c b/gnu/usr.bin/gcc/cp/typeck2.c
index 653d6a54dc5..df58f19b6e4 100644
--- a/gnu/usr.bin/gcc/cp/typeck2.c
+++ b/gnu/usr.bin/gcc/cp/typeck2.c
@@ -36,14 +36,14 @@ Boston, MA 02111-1307, USA. */
#include "cp-tree.h"
#include "flags.h"
-static tree process_init_constructor ();
-extern void pedwarn (), error ();
+static tree process_init_constructor PROTO((tree, tree, tree *));
extern int errorcount;
extern int sorrycount;
/* Print an error message stemming from an attempt to use
BASETYPE as a base class for TYPE. */
+
tree
error_not_base_type (basetype, type)
tree basetype, type;
@@ -71,33 +71,11 @@ binfo_or_else (parent_or_type, type)
return NULL_TREE;
}
-/* Print an error message stemming from an invalid use of an
- aggregate type.
-
- TYPE is the type or binfo which draws the error.
- MSG is the message to print.
- ARG is an optional argument which may provide more information. */
-void
-error_with_aggr_type (type, msg, arg)
- tree type;
- char *msg;
- HOST_WIDE_INT arg;
-{
- tree name;
-
- if (TREE_CODE (type) == TREE_VEC)
- type = BINFO_TYPE (type);
-
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NAME (name);
- error (msg, IDENTIFIER_POINTER (name), arg);
-}
-
/* According to ARM $7.1.6, "A `const' object may be initialized, but its
value may not be changed thereafter. Thus, we emit hard errors for these,
rather than just pedwarns. If `SOFT' is 1, then we just pedwarn. (For
example, conversions to references.) */
+
void
readonly_error (arg, string, soft)
tree arg;
@@ -108,46 +86,44 @@ readonly_error (arg, string, soft)
void (*fn)();
if (soft)
- fn = pedwarn;
+ fn = cp_pedwarn;
else
- fn = error;
+ fn = cp_error;
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- fmt = "%s of member `%s' in read-only structure";
+ fmt = "%s of member `%D' in read-only structure";
else
- fmt = "%s of read-only member `%s'";
- (*fn) (fmt, string, lang_printable_name (TREE_OPERAND (arg, 1)));
+ fmt = "%s of read-only member `%D'";
+ (*fn) (fmt, string, TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
{
if (DECL_LANG_SPECIFIC (arg)
&& DECL_IN_AGGR_P (arg)
&& !TREE_STATIC (arg))
- fmt = "%s of constant field `%s'";
+ fmt = "%s of constant field `%D'";
else
- fmt = "%s of read-only variable `%s'";
- (*fn) (fmt, string, lang_printable_name (arg));
+ fmt = "%s of read-only variable `%D'";
+ (*fn) (fmt, string, arg);
}
else if (TREE_CODE (arg) == PARM_DECL)
- (*fn) ("%s of read-only parameter `%s'", string,
- lang_printable_name (arg));
+ (*fn) ("%s of read-only parameter `%D'", string, arg);
else if (TREE_CODE (arg) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
&& (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
|| TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
- (*fn) ("%s of read-only reference `%s'",
- string, lang_printable_name (TREE_OPERAND (arg, 0)));
+ (*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0));
else if (TREE_CODE (arg) == RESULT_DECL)
- (*fn) ("%s of read-only named return value `%s'",
- string, lang_printable_name (arg));
+ (*fn) ("%s of read-only named return value `%D'", string, arg);
else
(*fn) ("%s of read-only location", string);
}
/* Print an error message for invalid use of a type which declares
virtual functions which are not inheritable. */
+
void
abstract_virtuals_error (decl, type)
tree decl;
@@ -193,6 +169,7 @@ abstract_virtuals_error (decl, type)
/* Print an error message for invalid use of a signature type.
Signatures are treated similar to abstract classes here, they
cannot be instantiated. */
+
void
signature_error (decl, type)
tree decl;
@@ -239,8 +216,7 @@ incomplete_type_error (value, type)
if (value != 0 && (TREE_CODE (value) == VAR_DECL
|| TREE_CODE (value) == PARM_DECL))
- error ("`%s' has an incomplete type",
- IDENTIFIER_POINTER (DECL_NAME (value)));
+ cp_error ("`%D' has incomplete type", value);
else
{
retry:
@@ -249,15 +225,9 @@ incomplete_type_error (value, type)
switch (TREE_CODE (type))
{
case RECORD_TYPE:
- errmsg = "invalid use of undefined type `struct %s'";
- break;
-
case UNION_TYPE:
- errmsg = "invalid use of undefined type `union %s'";
- break;
-
case ENUMERAL_TYPE:
- errmsg = "invalid use of undefined type `enum %s'";
+ errmsg = "invalid use of undefined type `%#T'";
break;
case VOID_TYPE:
@@ -281,11 +251,12 @@ incomplete_type_error (value, type)
my_friendly_abort (108);
}
- error_with_aggr_type (type, errmsg);
+ cp_error (errmsg, type);
}
}
/* Like error(), but don't call report_error_function(). */
+
static void
ack (s, v, v2)
char *s;
@@ -330,7 +301,7 @@ ack (s, v, v2)
silly. So instead, we just do the equivalent of a call to fatal in the
same situation (call exit). */
-/* First used: 0 (reserved), Last used: 366. Free: */
+/* First used: 0 (reserved), Last used: 369. Free: */
static int abortcount = 0;
@@ -468,8 +439,8 @@ initializer_constant_valid_p (value, endtype)
return 0;
case PLUS_EXPR:
- if (TREE_CODE (endtype) == INTEGER_TYPE
- && TYPE_PRECISION (endtype) < POINTER_SIZE)
+ if ((TREE_CODE (endtype) == INTEGER_TYPE)
+ && (TYPE_PRECISION (endtype) < POINTER_SIZE))
return 0;
{
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
@@ -485,8 +456,8 @@ initializer_constant_valid_p (value, endtype)
}
case MINUS_EXPR:
- if (TREE_CODE (endtype) == INTEGER_TYPE
- && TYPE_PRECISION (endtype) < POINTER_SIZE)
+ if ((TREE_CODE (endtype) == INTEGER_TYPE)
+ && (TYPE_PRECISION (endtype) < POINTER_SIZE))
return 0;
{
tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
@@ -569,8 +540,6 @@ store_init_value (decl, init)
if (TREE_CODE (init) == CONSTRUCTOR)
{
tree field;
- tree funcs;
- int func;
/* Check that we're really an aggregate as ARM 8.4.1 defines it. */
if (CLASSTYPE_N_BASECLASSES (type))
@@ -588,16 +557,11 @@ store_init_value (decl, init)
cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field);
}
- funcs = TYPE_METHODS (type);
- if (funcs)
- for (func = 0; func < TREE_VEC_LENGTH (funcs); func++)
+ for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
+ if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
{
- field = TREE_VEC_ELT (funcs, func);
- if (field && (TREE_PRIVATE (field) || TREE_PROTECTED (field)))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
+ cp_error_at ("initializer list construction invalid for `%D'", decl);
+ cp_error_at ("due to non-public access of member `%D'", field);
}
}
#endif
@@ -642,6 +606,10 @@ store_init_value (decl, init)
}
}
+ if (TYPE_PTRMEMFUNC_P (type) && TREE_CODE (init) == CONSTRUCTOR
+ && TREE_TYPE (init) == NULL_TREE)
+ cp_pedwarn ("initializer list for `%T'", type);
+
/* End of special C++ code. */
/* Digest the specified initializer into an expression. */
@@ -652,6 +620,11 @@ store_init_value (decl, init)
if (TREE_CODE (value) == ERROR_MARK)
;
+ /* Other code expects that initializers for objects of types that need
+ constructing never make it into DECL_INITIAL, and passes 'init' to
+ expand_aggr_init without checking DECL_INITIAL. So just return. */
+ else if (TYPE_NEEDS_CONSTRUCTING (type))
+ return value;
else if (TREE_STATIC (decl)
&& (! TREE_CONSTANT (value)
|| ! initializer_constant_valid_p (value, TREE_TYPE (value))
@@ -847,7 +820,7 @@ digest_init (type, init, tail)
if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE
|| code == ENUMERAL_TYPE || code == REFERENCE_TYPE
- || code == BOOLEAN_TYPE
+ || code == BOOLEAN_TYPE || code == COMPLEX_TYPE
|| (code == RECORD_TYPE && ! raw_constructor
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))))
{
@@ -860,7 +833,9 @@ digest_init (type, init, tail)
}
init = element;
}
- while (TREE_CODE (init) == CONSTRUCTOR)
+ while (TREE_CODE (init) == CONSTRUCTOR
+ && ! (TREE_TYPE (init)
+ && TYPE_PTRMEMFUNC_P (TREE_TYPE (init))))
{
cp_pedwarn ("braces around scalar initializer for `%T'", type);
init = CONSTRUCTOR_ELTS (init);
@@ -894,24 +869,21 @@ digest_init (type, init, tail)
return process_init_constructor (type, init, (tree *)0);
else if (TYPE_NON_AGGREGATE_CLASS (type))
{
- /* This can only be reached when caller is initializing
- ARRAY_TYPE. In that case, we don't want to convert
- INIT to TYPE. We will let `expand_vec_init' do it. */
- return init;
+ int flags = LOOKUP_NORMAL;
+ /* Initialization from { } is copy-initialization. */
+ if (tail)
+ flags |= LOOKUP_ONLYCONVERTING;
+ return convert_for_initialization (0, type, init, flags,
+ "initialization", NULL_TREE, 0);
}
else if (tail != 0)
{
*tail = old_tail_contents;
return process_init_constructor (type, 0, tail);
}
- else if (flag_traditional)
- /* Traditionally one can say `char x[100] = 0;'. */
- return process_init_constructor (type,
- build_nt (CONSTRUCTOR, 0,
- tree_cons (0, init, 0)),
- 0);
+
if (code != ARRAY_TYPE)
- return convert_for_initialization (0, type, init, LOOKUP_NORMAL,
+ return convert_for_initialization (NULL_TREE, type, init, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0);
}
@@ -1014,7 +986,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = tree_cons (NULL_TREE, next1, members);
+ members = expr_tree_cons (NULL_TREE, next1, members);
}
}
if (TREE_CODE (type) == RECORD_TYPE)
@@ -1049,7 +1021,7 @@ process_init_constructor (type, init, elts)
if (! DECL_NAME (field))
{
- members = tree_cons (field, integer_zero_node, members);
+ members = expr_tree_cons (field, integer_zero_node, members);
continue;
}
@@ -1078,7 +1050,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = tree_cons (field, next1, members);
+ members = expr_tree_cons (field, next1, members);
}
for (; field; field = TREE_CHAIN (field))
{
@@ -1095,7 +1067,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1)))
allsimple = 0;
- members = tree_cons (field, next1, members);
+ members = expr_tree_cons (field, next1, members);
}
else if (TREE_READONLY (field))
error ("uninitialized const member `%s'",
@@ -1117,7 +1089,8 @@ process_init_constructor (type, init, elts)
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
- while (field && DECL_NAME (field) == 0)
+ while (field && (DECL_NAME (field) == 0
+ || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */
@@ -1176,7 +1149,7 @@ process_init_constructor (type, init, elts)
allconstant = 0;
else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0)
allsimple = 0;
- members = tree_cons (field, next1, members);
+ members = expr_tree_cons (field, next1, members);
}
/* If arguments were specified as a list, just remove the ones we used. */
@@ -1200,7 +1173,7 @@ process_init_constructor (type, init, elts)
/* Given a structure or union value DATUM, construct and return
the structure or union component which results from narrowing
- that value by the types specified in TYPES. For example, given the
+ that value by the type specified in BASETYPE. For example, given the
hierarchy
class L { int ii; };
@@ -1214,23 +1187,14 @@ process_init_constructor (type, init, elts)
then the expression
- x::C::A::L::ii refers to the ii member of the L part of
+ x.A::ii refers to the ii member of the L part of
of A part of the C object named by X. In this case,
- DATUM would be x, and TYPES would be a SCOPE_REF consisting of
-
- SCOPE_REF
- SCOPE_REF
- C A
- L
-
- The last entry in the SCOPE_REF is always an IDENTIFIER_NODE.
-
-*/
+ DATUM would be x, and BASETYPE would be A. */
tree
-build_scoped_ref (datum, types)
+build_scoped_ref (datum, basetype)
tree datum;
- tree types;
+ tree basetype;
{
tree ref;
tree type = TREE_TYPE (datum);
@@ -1243,62 +1207,17 @@ build_scoped_ref (datum, types)
type = TYPE_MAIN_VARIANT (type);
- if (TREE_CODE (types) == SCOPE_REF)
- {
- /* We have some work to do. */
- struct type_chain
- { tree type; struct type_chain *next; }
- *chain = NULL, *head = NULL, scratch;
- ref = build_unary_op (ADDR_EXPR, datum, 0);
- while (TREE_CODE (types) == SCOPE_REF)
- {
- tree t = TREE_OPERAND (types, 1);
- if (is_aggr_typedef (t, 1))
- {
- head = (struct type_chain *)alloca (sizeof (struct type_chain));
- head->type = IDENTIFIER_TYPE_VALUE (t);
- head->next = chain;
- chain = head;
- types = TREE_OPERAND (types, 0);
- }
- else return error_mark_node;
- }
- if (! is_aggr_typedef (types, 1))
- return error_mark_node;
-
- head = &scratch;
- head->type = IDENTIFIER_TYPE_VALUE (types);
- head->next = chain;
- chain = head;
- while (chain)
- {
- tree binfo = chain->type;
- type = TREE_TYPE (TREE_TYPE (ref));
- if (binfo != TYPE_BINFO (type))
- {
- binfo = get_binfo (binfo, type, 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (binfo == 0)
- return error_not_base_type (chain->type, type);
- ref = convert_pointer_to (binfo, ref);
- }
- chain = chain->next;
- }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
- }
-
/* This is an easy conversion. */
- if (is_aggr_typedef (types, 1))
+ if (is_aggr_type (basetype, 1))
{
- tree binfo = TYPE_BINFO (IDENTIFIER_TYPE_VALUE (types));
+ tree binfo = TYPE_BINFO (basetype);
if (binfo != TYPE_BINFO (type))
{
binfo = get_binfo (binfo, type, 1);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == 0)
- return error_not_base_type (IDENTIFIER_TYPE_VALUE (types), type);
+ return error_not_base_type (basetype, type);
}
switch (TREE_CODE (datum))
@@ -1328,6 +1247,7 @@ build_scoped_ref (datum, types)
performed until an object which does not have the `->' operator
overloaded is found. An error is reported when circular pointer
delegation is detected. */
+
tree
build_x_arrow (datum)
tree datum;
@@ -1340,6 +1260,9 @@ build_x_arrow (datum)
if (type == error_mark_node)
return error_mark_node;
+ if (processing_template_decl)
+ return build_min_nt (ARROW_EXPR, rval);
+
if (TREE_CODE (rval) == OFFSET_REF)
{
rval = resolve_offset_ref (datum);
@@ -1352,7 +1275,7 @@ build_x_arrow (datum)
type = TREE_TYPE (rval);
}
- if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (type))
+ if (IS_AGGR_TYPE (type) && TYPE_OVERLOADS_ARROW (complete_type (type)))
{
while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, NULL_TREE, NULL_TREE)))
{
@@ -1403,6 +1326,7 @@ build_x_arrow (datum)
As a special case, if there is only one method by that name,
it is returned. Otherwise we return an expression which other
routines will have to know how to deal with later. */
+
tree
build_m_component_ref (datum, component)
tree datum, component;
@@ -1412,6 +1336,9 @@ build_m_component_ref (datum, component)
tree rettype;
tree binfo;
+ if (processing_template_decl)
+ return build_min_nt (DOTSTAR_EXPR, datum, component);
+
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component)))
{
type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component)));
@@ -1421,7 +1348,7 @@ build_m_component_ref (datum, component)
{
component = build_indirect_ref (component, NULL_PTR);
type = TREE_TYPE (component);
- rettype = TREE_TYPE (TREE_TYPE (component));
+ rettype = TREE_TYPE (type);
}
if (datum == error_mark_node || component == error_mark_node)
@@ -1454,14 +1381,14 @@ build_m_component_ref (datum, component)
else if (binfo == error_mark_node)
return error_mark_node;
- return build (OFFSET_REF, rettype, datum, component);
+ component = build (OFFSET_REF, rettype, datum, component);
+ if (TREE_CODE (type) == OFFSET_TYPE)
+ component = resolve_offset_ref (component);
+ return component;
}
-/* Return a tree node for the expression TYPENAME '(' PARMS ')'.
+/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */
- Because we cannot tell whether this construct is really a call to a
- constructor or a request for a type conversion, we try both, and
- report any ambiguities we find. */
tree
build_functional_cast (exp, parms)
tree exp;
@@ -1469,16 +1396,13 @@ build_functional_cast (exp, parms)
{
/* This is either a call to a constructor,
or a C cast in C++'s `functional' notation. */
- tree type, name = NULL_TREE;
- tree expr_as_ctor = NULL_TREE;
+ tree type;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
if (TREE_CODE (exp) == IDENTIFIER_NODE)
{
- name = exp;
-
if (IDENTIFIER_HAS_TYPE_VALUE (exp))
/* Either an enum or an aggregate type. */
type = IDENTIFIER_TYPE_VALUE (exp);
@@ -1487,35 +1411,26 @@ build_functional_cast (exp, parms)
type = lookup_name (exp, 1);
if (!type || TREE_CODE (type) != TYPE_DECL)
{
- cp_error ("`%T' fails to be a typedef or built-in type", name);
+ cp_error ("`%T' fails to be a typedef or built-in type", exp);
return error_mark_node;
}
type = TREE_TYPE (type);
}
}
+ else if (TREE_CODE (exp) == TYPE_DECL)
+ type = TREE_TYPE (exp);
else
type = exp;
+ if (processing_template_decl)
+ return build_min (CAST_EXPR, type, parms);
+
if (IS_SIGNATURE (type))
{
error ("signature type not allowed in cast or constructor expression");
return error_mark_node;
}
- /* Prepare to evaluate as a call to a constructor. If this expression
- is actually used, for example,
-
- return X (arg1, arg2, ...);
-
- then the slot being initialized will be filled in. */
-
- if (name == NULL_TREE)
- {
- name = TYPE_NAME (type);
- if (TREE_CODE (name) == TYPE_DECL)
- name = DECL_NESTED_TYPENAME (name);
- }
-
if (! IS_AGGR_TYPE (type))
{
/* this must build a C cast */
@@ -1528,29 +1443,37 @@ build_functional_cast (exp, parms)
parms = build_compound_expr (parms);
}
- return build_c_cast (type, parms, 1);
+ return build_c_cast (type, parms);
}
- if (TYPE_SIZE (type) == NULL_TREE)
+ /* Prepare to evaluate as a call to a constructor. If this expression
+ is actually used, for example,
+
+ return X (arg1, arg2, ...);
+
+ then the slot being initialized will be filled in. */
+
+ if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
{
cp_error ("type `%T' is not yet defined", type);
return error_mark_node;
}
if (parms && TREE_CHAIN (parms) == NULL_TREE)
- return build_c_cast (type, parms, 1);
+ return build_c_cast (type, TREE_VALUE (parms));
- expr_as_ctor = build_method_call (NULL_TREE, name, parms,
- NULL_TREE, LOOKUP_NORMAL);
+ exp = build_method_call (NULL_TREE, ctor_identifier, parms,
+ TYPE_BINFO (type), LOOKUP_NORMAL);
- if (expr_as_ctor == error_mark_node)
+ if (exp == error_mark_node)
return error_mark_node;
- return build_cplus_new (type, expr_as_ctor, 1);
+ return build_cplus_new (type, exp);
}
/* Return the character string for the name that encodes the
enumeral value VALUE in the domain TYPE. */
+
char *
enum_name_string (value, type)
tree value;
@@ -1582,6 +1505,7 @@ enum_name_string (value, type)
TYPE is the type of the switch index expression.
NEW is the new value that we were trying to add.
OLD is the old value that stopped us from adding it. */
+
void
report_case_error (code, type, new_value, old_value)
int code;
@@ -1679,3 +1603,12 @@ report_case_error (code, type, new_value, old_value)
}
}
#endif
+
+void
+check_for_new_type (string, inptree)
+ char *string;
+ flagged_type_tree inptree;
+{
+ if (pedantic && inptree.new_type_flag)
+ pedwarn ("ANSI C++ forbids defining types within %s",string);
+}
diff --git a/gnu/usr.bin/gcc/cp/xref.c b/gnu/usr.bin/gcc/cp/xref.c
index ec4b174b52c..40cdf42103f 100644
--- a/gnu/usr.bin/gcc/cp/xref.c
+++ b/gnu/usr.bin/gcc/cp/xref.c
@@ -1,5 +1,5 @@
/* Code for handling XREF output from GNU C++.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -28,10 +28,23 @@ Boston, MA 02111-1307, USA. */
#include <ctype.h>
-extern char *getpwd ();
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+extern char *getpwd PROTO((void));
-extern char *index ();
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef NEED_DECLARATION_RINDEX
extern char *rindex ();
+#endif
/* The character(s) used to join a directory specification (obtained with
getwd or equivalent) with a non-absolute file name. */
@@ -61,9 +74,6 @@ int flag_gnu_xref;
#ifndef FALSE
#define FALSE 0
#endif
-#ifndef NULL
-#define NULL 0
-#endif
#define PALLOC(typ) ((typ *) calloc(1,sizeof(typ)))
@@ -128,30 +138,14 @@ static tree last_fndecl = NULL;
/* Forward definitions */
/* */
/************************************************************************/
-
-extern void GNU_xref_begin();
-extern void GNU_xref_end();
-extern void GNU_xref_file();
-extern void GNU_xref_start_scope();
-extern void GNU_xref_end_scope();
-extern void GNU_xref_ref();
-extern void GNU_xref_decl();
-extern void GNU_xref_call();
-extern void GNU_xref_function();
-extern void GNU_xref_assign();
-extern void GNU_xref_hier();
-extern void GNU_xref_member();
-
-static void gen_assign();
-static XREF_FILE find_file();
-static char * filename();
-static char * fctname();
-static char * declname();
-static void simplify_type();
-static char * fixname();
-static void open_xref_file();
-
-extern char * type_as_string();
+static void gen_assign PROTO((XREF_FILE, tree));
+static XREF_FILE find_file PROTO((char *));
+static char * filename PROTO((XREF_FILE));
+static char * fctname PROTO((tree));
+static char * declname PROTO((tree));
+static void simplify_type PROTO((char *));
+static char * fixname PROTO((char *, char *));
+static void open_xref_file PROTO((char *));
/* Start cross referencing. FILE is the name of the file we xref. */
@@ -183,7 +177,7 @@ GNU_xref_end (ect)
if (xf == NULL) return;
while (cur_scope != NULL)
- GNU_xref_end_scope(cur_scope->gid,0,0,0,0);
+ GNU_xref_end_scope(cur_scope->gid,0,0,0);
doing_xref = 0;
@@ -275,10 +269,10 @@ GNU_xref_start_scope (id)
TRNS is ??? */
void
-GNU_xref_end_scope (id,inid,prm,keep,trns)
+GNU_xref_end_scope (id,inid,prm,keep)
HOST_WIDE_INT id;
HOST_WIDE_INT inid;
- int prm,keep,trns;
+ int prm,keep;
{
XREF_FILE xf;
XREF_SCOPE xs,lxs,oxs;
@@ -400,7 +394,7 @@ GNU_xref_decl (fndecl,decl)
}
else if (TREE_CODE (decl) == TEMPLATE_DECL)
{
- if (DECL_TEMPLATE_IS_CLASS (decl))
+ if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
cls = "CLASSTEMP";
else if (TREE_CODE (DECL_RESULT (decl)) == FUNCTION_DECL)
cls = "FUNCTEMP";
@@ -569,6 +563,7 @@ gen_assign(xf, name)
of CLS.
??? Needs to handle nested classes. */
+
void
GNU_xref_hier(cls, base, pub, virt, frnd)
char *cls;
@@ -599,7 +594,9 @@ GNU_xref_member(cls, fld)
char *prot;
int confg, pure;
char *d;
+#ifdef XREF_SHORT_MEMBER_NAMES
int i;
+#endif
char buf[1024], bufa[1024];
if (!doing_xref) return;
@@ -622,7 +619,9 @@ GNU_xref_member(cls, fld)
d = IDENTIFIER_POINTER(cls);
sprintf(buf, "%d%s", strlen(d), d);
+#ifdef XREF_SHORT_MEMBER_NAMES
i = strlen(buf);
+#endif
strcpy(bufa, declname(fld));
#ifdef XREF_SHORT_MEMBER_NAMES
@@ -643,7 +642,7 @@ GNU_xref_member(cls, fld)
filename(xf), fld->decl.linenum, d, bufa, prot,
(TREE_CODE (fld) == FUNCTION_DECL ? 0 : 1),
(DECL_INLINE (fld) ? 1 : 0),
- (DECL_FRIEND_P(fld) ? 1 : 0),
+ (DECL_LANG_SPECIFIC(fld) && DECL_FRIEND_P(fld) ? 1 : 0),
(DECL_VINDEX(fld) ? 1 : 0),
(TREE_STATIC(fld) ? 1 : 0),
pure, confg);
diff --git a/gnu/usr.bin/gcc/cplus-dem.c b/gnu/usr.bin/gcc/cplus-dem.c
index 3eb27cc9b84..ad4116bd5c5 100644
--- a/gnu/usr.bin/gcc/cplus-dem.c
+++ b/gnu/usr.bin/gcc/cplus-dem.c
@@ -1,5 +1,5 @@
/* Demangler for GNU C++
- Copyright 1989, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Copyright 1989, 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.uucp)
Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling
@@ -23,7 +23,10 @@ Boston, MA 02111-1307, USA. */
This file imports xmalloc and xrealloc, which are like malloc and
realloc except that they generate a fatal error if there is no
- available memory. */
+ available memory. */
+
+/* This file lives in both GCC and libiberty. When making changes, please
+ try not to break either. */
#include <ctype.h>
#include <string.h>
@@ -36,11 +39,13 @@ Boston, MA 02111-1307, USA. */
extern char *xmalloc PARAMS((unsigned));
extern char *xrealloc PARAMS((char *, unsigned));
-char *
+static const char *mystrstr PARAMS ((const char *, const char *));
+
+static const char *
mystrstr (s1, s2)
- char *s1, *s2;
+ const char *s1, *s2;
{
- register char *p = s1;
+ register const char *p = s1;
register int len = strlen (s2);
for (; (p = strchr (p, *s2)) != 0; p++)
@@ -67,7 +72,7 @@ mystrstr (s1, s2)
We could avoid this if we could just get g++ to tell us what the actual
cplus marker character is as part of the debug information, perhaps by
ensuring that it is the character that terminates the gcc<n>_compiled
- marker symbol (FIXME). */
+ marker symbol (FIXME). */
#if !defined (CPLUS_MARKER)
#define CPLUS_MARKER '$'
@@ -81,11 +86,11 @@ void
set_cplus_marker_for_demangling (ch)
int ch;
{
- cplus_markers[0] = ch;
+ cplus_markers[0] = ch;
}
/* Stuff that is shared between sub-routines.
- * Using a shared structure allows cplus_demangle to be reentrant. */
+ Using a shared structure allows cplus_demangle to be reentrant. */
struct work_stuff
{
@@ -97,6 +102,8 @@ struct work_stuff
int destructor;
int static_type; /* A static member function */
int const_type; /* A const member function */
+ char **tmpl_argvec; /* Template function arguments. */
+ int ntmpl_args; /* The number of template function arguments. */
};
#define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
@@ -190,7 +197,7 @@ static const struct optable
typedef struct string /* Beware: these aren't required to be */
-{ /* '\0' terminated. */
+{ /* '\0' terminated. */
char *b; /* pointer to start of string */
char *p; /* pointer after last character */
char *e; /* pointer after end of allocated space */
@@ -198,9 +205,9 @@ typedef struct string /* Beware: these aren't required to be */
#define STRING_EMPTY(str) ((str) -> b == (str) -> p)
#define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
- string_prepend(str, " ");}
+ string_prepend(str, " ");}
#define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \
- string_append(str, " ");}
+ string_append(str, " ");}
#define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */
#define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */
@@ -217,7 +224,17 @@ demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *))
static int
demangle_template PARAMS ((struct work_stuff *work, const char **, string *,
- string *));
+ string *, int));
+
+static int
+arm_pt PARAMS ((struct work_stuff *, const char *, int, const char **,
+ const char **));
+
+static void
+demangle_arm_pt PARAMS ((struct work_stuff *, const char **, int, string *));
+
+static int
+demangle_class_name PARAMS ((struct work_stuff *, const char **, string *));
static int
demangle_qualified PARAMS ((struct work_stuff *, const char **, string *,
@@ -279,6 +296,9 @@ get_count PARAMS ((const char **, int *));
static int
consume_count PARAMS ((const char **));
+static int
+consume_count_with_underscores PARAMS ((const char**));
+
static int
demangle_args PARAMS ((struct work_stuff *, const char **, string *));
@@ -304,26 +324,62 @@ string_prepends PARAMS ((string *, string *));
/* Translate count to integer, consuming tokens in the process.
Conversion terminates on the first non-digit character.
Trying to consume something that isn't a count results in
- no consumption of input and a return of 0. */
+ no consumption of input and a return of 0. */
static int
consume_count (type)
- const char **type;
+ const char **type;
{
- int count = 0;
+ int count = 0;
- while (isdigit (**type))
- {
- count *= 10;
- count += **type - '0';
- (*type)++;
- }
- return (count);
+ while (isdigit (**type))
+ {
+ count *= 10;
+ count += **type - '0';
+ (*type)++;
+ }
+ return (count);
+}
+
+
+/* Like consume_count, but for counts that are preceded and followed
+ by '_' if they are greater than 10. Also, -1 is returned for
+ failure, since 0 can be a valid value. */
+
+static int
+consume_count_with_underscores (mangled)
+ const char **mangled;
+{
+ int idx;
+
+ if (**mangled == '_')
+ {
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ return -1;
+
+ idx = consume_count (mangled);
+ if (**mangled != '_')
+ /* The trailing underscore was missing. */
+ return -1;
+
+ (*mangled)++;
+ }
+ else
+ {
+ if (**mangled < '0' || **mangled > '9')
+ return -1;
+
+ idx = **mangled - '0';
+ (*mangled)++;
+ }
+
+ return idx;
}
int
cplus_demangle_opname (opname, result, options)
- char *opname;
+ const char *opname;
char *result;
int options;
{
@@ -338,7 +394,7 @@ cplus_demangle_opname (opname, result, options)
work->options = options;
if (opname[0] == '_' && opname[1] == '_'
- && opname[2] == 'o' && opname[3] == 'p')
+ && opname[2] == 'o' && opname[3] == 'p')
{
/* ANSI. */
/* type conversion operator. */
@@ -374,7 +430,7 @@ cplus_demangle_opname (opname, result, options)
{
if (opname[2] == 'a' && opname[5] == '\0')
{
- /* Assignment. */
+ /* Assignment. */
for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
{
if (strlen (optable[i].in) == 3
@@ -390,9 +446,9 @@ cplus_demangle_opname (opname, result, options)
}
}
else if (len >= 3
- && opname[0] == 'o'
- && opname[1] == 'p'
- && strchr (cplus_markers, opname[2]) != NULL)
+ && opname[0] == 'o'
+ && opname[1] == 'p'
+ && strchr (cplus_markers, opname[2]) != NULL)
{
/* see if it's an assignment expression */
if (len >= 10 /* op$assign_ */
@@ -450,9 +506,9 @@ cplus_demangle_opname (opname, result, options)
If OPTIONS & DMGL_ANSI == 1, return the ANSI name;
if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */
-char *
+const char *
cplus_mangle_opname (opname, options)
- char *opname;
+ const char *opname;
int options;
{
int i;
@@ -464,26 +520,11 @@ cplus_mangle_opname (opname, options)
if (strlen (optable[i].out) == len
&& (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI)
&& memcmp (optable[i].out, opname, len) == 0)
- return ((char *)optable[i].in);
+ return optable[i].in;
}
return (0);
}
-/* check to see whether MANGLED can match TEXT in the first TEXT_LEN
- characters. */
-
-int cplus_match (mangled, text, text_len)
- const char *mangled;
- char *text;
- int text_len;
-{
- if (strncmp (mangled, text, text_len) != 0) {
- return(0); /* cannot match either */
- } else {
- return(1); /* matches mangled, may match demangled */
- }
-}
-
/* char *cplus_demangle (const char *mangled, int options)
If MANGLED is a mangled function name produced by GNU C++, then
@@ -536,7 +577,7 @@ cplus_demangle (mangled, options)
recognize one of the gnu special forms rather than looking for a
standard prefix. In particular, don't worry about whether there
is a "__" string in the mangled string. Consider "_$_5__foo" for
- example. */
+ example. */
if ((AUTO_DEMANGLING || GNU_DEMANGLING))
{
@@ -573,16 +614,26 @@ mop_up (work, declp, success)
{
char *demangled = NULL;
- /* Discard the remembered types, if any. */
+ /* Discard the remembered types, if any. */
forget_types (work);
if (work -> typevec != NULL)
{
free ((char *) work -> typevec);
}
-
+ if (work->tmpl_argvec)
+ {
+ int i;
+
+ for (i = 0; i < work->ntmpl_args; i++)
+ if (work->tmpl_argvec[i])
+ free ((char*) work->tmpl_argvec[i]);
+
+ free ((char*) work->tmpl_argvec);
+ }
+
/* If demangling was successful, ensure that the demangled string is null
- terminated and return it. Otherwise, free the demangling decl. */
+ terminated and return it. Otherwise, free the demangling decl. */
if (!success)
{
@@ -624,8 +675,7 @@ DESCRIPTION
Demangling GNU style mangled names is nasty because there is no
explicit token that marks the start of the outermost function
- argument list.
-*/
+ argument list. */
static int
demangle_signature (work, mangled, declp)
@@ -636,6 +686,7 @@ demangle_signature (work, mangled, declp)
int success = 1;
int func_done = 0;
int expect_func = 0;
+ int expect_return_type = 0;
const char *oldmangled = NULL;
string trawname;
string tname;
@@ -644,150 +695,182 @@ demangle_signature (work, mangled, declp)
{
switch (**mangled)
{
- case 'Q':
- oldmangled = *mangled;
- success = demangle_qualified (work, mangled, declp, 1, 0);
- if (success)
- {
- remember_type (work, oldmangled, *mangled - oldmangled);
- }
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- {
- expect_func = 1;
- }
- oldmangled = NULL;
- break;
+ case 'Q':
+ oldmangled = *mangled;
+ success = demangle_qualified (work, mangled, declp, 1, 0);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
- case 'S':
- /* Static member function */
- if (oldmangled == NULL)
- {
- oldmangled = *mangled;
- }
- (*mangled)++;
- work -> static_type = 1;
- break;
+ case 'S':
+ /* Static member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> static_type = 1;
+ break;
- case 'C':
- /* a const member function */
- if (oldmangled == NULL)
- {
- oldmangled = *mangled;
- }
- (*mangled)++;
- work -> const_type = 1;
- break;
+ case 'C':
+ /* a const member function */
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ (*mangled)++;
+ work -> const_type = 1;
+ break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (oldmangled == NULL)
- {
- oldmangled = *mangled;
- }
- success = demangle_class (work, mangled, declp);
- if (success)
- {
- remember_type (work, oldmangled, *mangled - oldmangled);
- }
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- {
- expect_func = 1;
- }
- oldmangled = NULL;
- break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ success = demangle_class (work, mangled, declp);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ expect_func = 1;
+ }
+ oldmangled = NULL;
+ break;
- case 'F':
- /* Function */
- /* ARM style demangling includes a specific 'F' character after
+ case 'F':
+ /* Function */
+ /* ARM style demangling includes a specific 'F' character after
the class name. For GNU style, it is just implied. So we can
safely just consume any 'F' at this point and be compatible
- with either style. */
+ with either style. */
- oldmangled = NULL;
- func_done = 1;
- (*mangled)++;
+ oldmangled = NULL;
+ func_done = 1;
+ (*mangled)++;
- /* For lucid/ARM style we have to forget any types we might
- have remembered up to this point, since they were not argument
- types. GNU style considers all types seen as available for
- back references. See comment in demangle_args() */
+ /* For lucid/ARM style we have to forget any types we might
+ have remembered up to this point, since they were not argument
+ types. GNU style considers all types seen as available for
+ back references. See comment in demangle_args() */
- if (LUCID_DEMANGLING || ARM_DEMANGLING)
- {
- forget_types (work);
- }
- success = demangle_args (work, mangled, declp);
- break;
+ if (LUCID_DEMANGLING || ARM_DEMANGLING)
+ {
+ forget_types (work);
+ }
+ success = demangle_args (work, mangled, declp);
+ break;
- case 't':
- /* G++ Template */
- string_init(&trawname);
- string_init(&tname);
- if (oldmangled == NULL)
- {
- oldmangled = *mangled;
- }
- success = demangle_template (work, mangled, &tname, &trawname);
- if (success)
- {
- remember_type (work, oldmangled, *mangled - oldmangled);
- }
- string_append(&tname, "::");
- string_prepends(declp, &tname);
- if (work -> destructor & 1)
- {
- string_prepend (&trawname, "~");
- string_appends (declp, &trawname);
- work->destructor -= 1;
- }
- if ((work->constructor & 1) || (work->destructor & 1))
- {
- string_appends (declp, &trawname);
- work->constructor -= 1;
- }
- string_delete(&trawname);
- string_delete(&tname);
- oldmangled = NULL;
- expect_func = 1;
- break;
+ case 't':
+ /* G++ Template */
+ string_init(&trawname);
+ string_init(&tname);
+ if (oldmangled == NULL)
+ {
+ oldmangled = *mangled;
+ }
+ success = demangle_template (work, mangled, &tname, &trawname, 1);
+ if (success)
+ {
+ remember_type (work, oldmangled, *mangled - oldmangled);
+ }
+ string_append(&tname, (work -> options & DMGL_JAVA) ? "." : "::");
+ string_prepends(declp, &tname);
+ if (work -> destructor & 1)
+ {
+ string_prepend (&trawname, "~");
+ string_appends (declp, &trawname);
+ work->destructor -= 1;
+ }
+ if ((work->constructor & 1) || (work->destructor & 1))
+ {
+ string_appends (declp, &trawname);
+ work->constructor -= 1;
+ }
+ string_delete(&trawname);
+ string_delete(&tname);
+ oldmangled = NULL;
+ expect_func = 1;
+ break;
+
+ case '_':
+ if (GNU_DEMANGLING && expect_return_type)
+ {
+ /* Read the return type. */
+ string return_type;
+ string_init (&return_type);
- case '_':
+ (*mangled)++;
+ success = do_type (work, mangled, &return_type);
+ APPEND_BLANK (&return_type);
+
+ string_prepends (declp, &return_type);
+ string_delete (&return_type);
+ break;
+ }
+ else
/* At the outermost level, we cannot have a return type specified,
so if we run into another '_' at this point we are dealing with
a mangled name that is either bogus, or has been mangled by
some algorithm we don't know how to deal with. So just
- reject the entire demangling. */
+ reject the entire demangling. */
success = 0;
- break;
+ break;
- default:
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
- {
- /* Assume we have stumbled onto the first outermost function
- argument token, and start processing args. */
- func_done = 1;
- success = demangle_args (work, mangled, declp);
- }
- else
- {
- /* Non-GNU demanglers use a specific token to mark the start
- of the outermost function argument tokens. Typically 'F',
- for ARM-demangling, for example. So if we find something
- we are not prepared for, it must be an error. */
- success = 0;
- }
- break;
- }
-/*
- if (AUTO_DEMANGLING || GNU_DEMANGLING)
-*/
- {
- if (success && expect_func)
+ case 'H':
+ if (GNU_DEMANGLING)
{
+ /* A G++ template function. Read the template arguments. */
+ success = demangle_template (work, mangled, declp, 0, 0);
+ expect_return_type = 1;
+ (*mangled)++;
+ break;
+ }
+ else
+ /* fall through */
+ ;
+
+ default:
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ {
+ /* Assume we have stumbled onto the first outermost function
+ argument token, and start processing args. */
func_done = 1;
success = demangle_args (work, mangled, declp);
}
+ else
+ {
+ /* Non-GNU demanglers use a specific token to mark the start
+ of the outermost function argument tokens. Typically 'F',
+ for ARM-demangling, for example. So if we find something
+ we are not prepared for, it must be an error. */
+ success = 0;
+ }
+ break;
}
+ /*
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+ */
+ {
+ if (success && expect_func)
+ {
+ func_done = 1;
+ success = demangle_args (work, mangled, declp);
+ /* Since template include the mangling of their return types,
+ we must set expect_func to 0 so that we don't try do
+ demangle more arguments the next time we get here. */
+ expect_func = 0;
+ }
+ }
}
if (success && !func_done)
{
@@ -798,7 +881,7 @@ demangle_signature (work, mangled, declp)
first case, and need to ensure that the '(void)' gets added to
the current declp. Note that with ARM, the first case
represents the name of a static data member 'foo::bar',
- which is in the current declp, so we leave it alone. */
+ which is in the current declp, so we leave it alone. */
success = demangle_args (work, mangled, declp);
}
}
@@ -839,11 +922,12 @@ demangle_method_args (work, mangled, declp)
#endif
static int
-demangle_template (work, mangled, tname, trawname)
+demangle_template (work, mangled, tname, trawname, is_type)
struct work_stuff *work;
const char **mangled;
string *tname;
string *trawname;
+ int is_type;
{
int i;
int is_pointer;
@@ -858,25 +942,43 @@ demangle_template (work, mangled, tname, trawname)
const char *old_p;
const char *start;
int symbol_len;
+ int is_java_array = 0;
string temp;
(*mangled)++;
- start = *mangled;
- /* get template name */
- if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
+ if (is_type)
{
- return (0);
+ start = *mangled;
+ /* get template name */
+ if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r)
+ {
+ return (0);
+ }
+ if (trawname)
+ string_appendn (trawname, *mangled, r);
+ is_java_array = (work -> options & DMGL_JAVA)
+ && strncmp (*mangled, "JArray1Z", 8) == 0;
+ if (! is_java_array)
+ {
+ string_appendn (tname, *mangled, r);
+ }
+ *mangled += r;
}
- if (trawname)
- string_appendn (trawname, *mangled, r);
- string_appendn (tname, *mangled, r);
- *mangled += r;
- string_append (tname, "<");
+ if (!is_java_array)
+ string_append (tname, "<");
/* get size of template parameter list */
if (!get_count (mangled, &r))
{
return (0);
}
+ if (!is_type)
+ {
+ /* Create an array for saving the template argument values. */
+ work->tmpl_argvec = (char**) xmalloc (r * sizeof (char *));
+ work->ntmpl_args = r;
+ for (i = 0; i < r; i++)
+ work->tmpl_argvec[i] = 0;
+ }
for (i = 0; i < r; i++)
{
if (need_comma)
@@ -892,6 +994,15 @@ demangle_template (work, mangled, tname, trawname)
if (success)
{
string_appends (tname, &temp);
+
+ if (!is_type)
+ {
+ /* Save the template argument. */
+ int len = temp.p - temp.b;
+ work->tmpl_argvec[i] = xmalloc (len + 1);
+ memcpy (work->tmpl_argvec[i], temp.b, len);
+ work->tmpl_argvec[i][len] = '\0';
+ }
}
string_delete(&temp);
if (!success)
@@ -901,122 +1012,163 @@ demangle_template (work, mangled, tname, trawname)
}
else
{
+ string param;
+ string* s;
+
/* otherwise, value parameter */
old_p = *mangled;
is_pointer = 0;
is_real = 0;
is_integral = 0;
is_char = 0;
+ is_bool = 0;
done = 0;
/* temp is initialized in do_type */
success = do_type (work, mangled, &temp);
-/*
- if (success)
+ /*
+ if (success)
{
- string_appends (tname, &temp);
+ string_appends (s, &temp);
}
-*/
+ */
string_delete(&temp);
if (!success)
{
break;
}
-/*
- string_append (tname, "=");
-*/
+ /*
+ string_append (s, "=");
+ */
+
+ if (!is_type)
+ {
+ s = &param;
+ string_init (s);
+ }
+ else
+ s = tname;
+
while (*old_p && !done)
{
switch (*old_p)
{
- case 'P':
- case 'p':
- case 'R':
- done = is_pointer = 1;
- break;
- case 'C': /* const */
- case 'S': /* explicitly signed [char] */
- case 'U': /* unsigned */
- case 'V': /* volatile */
- case 'F': /* function */
- case 'M': /* member function */
- case 'O': /* ??? */
- old_p++;
- continue;
- case 'Q': /* qualified name */
- done = is_integral = 1;
- break;
- case 'T': /* remembered type */
- abort ();
- break;
- case 'v': /* void */
- abort ();
- break;
- case 'x': /* long long */
- case 'l': /* long */
- case 'i': /* int */
- case 's': /* short */
- case 'w': /* wchar_t */
- done = is_integral = 1;
- break;
- case 'b': /* bool */
- done = is_bool = 1;
- break;
- case 'c': /* char */
- done = is_char = 1;
- break;
- case 'r': /* long double */
- case 'd': /* double */
- case 'f': /* float */
- done = is_real = 1;
- break;
- default:
- /* it's probably user defined type, let's assume
- it's integral, it seems hard to figure out
- what it really is */
- done = is_integral = 1;
+ case 'P':
+ case 'p':
+ case 'R':
+ done = is_pointer = 1;
+ break;
+ case 'C': /* const */
+ case 'S': /* explicitly signed [char] */
+ case 'U': /* unsigned */
+ case 'V': /* volatile */
+ case 'F': /* function */
+ case 'M': /* member function */
+ case 'O': /* ??? */
+ case 'J': /* complex */
+ old_p++;
+ continue;
+ case 'Q': /* qualified name */
+ done = is_integral = 1;
+ break;
+ case 'T': /* remembered type */
+ abort ();
+ break;
+ case 'v': /* void */
+ abort ();
+ break;
+ case 'x': /* long long */
+ case 'l': /* long */
+ case 'i': /* int */
+ case 's': /* short */
+ case 'w': /* wchar_t */
+ done = is_integral = 1;
+ break;
+ case 'b': /* bool */
+ done = is_bool = 1;
+ break;
+ case 'c': /* char */
+ done = is_char = 1;
+ break;
+ case 'r': /* long double */
+ case 'd': /* double */
+ case 'f': /* float */
+ done = is_real = 1;
+ break;
+ default:
+ /* it's probably user defined type, let's assume
+ it's integral, it seems hard to figure out
+ what it really is */
+ done = is_integral = 1;
}
}
- if (is_integral)
+ if (**mangled == 'Y')
+ {
+ /* The next argument is a template parameter. */
+ int idx;
+
+ (*mangled)++;
+ idx = consume_count_with_underscores (mangled);
+ if (idx == -1
+ || (work->tmpl_argvec && idx >= work->ntmpl_args)
+ || consume_count_with_underscores (mangled) == -1)
+ {
+ success = 0;
+ if (!is_type)
+ string_delete (s);
+ break;
+ }
+ if (work->tmpl_argvec)
+ string_append (s, work->tmpl_argvec[idx]);
+ else
+ {
+ char buf[10];
+ sprintf(buf, "T%d", idx);
+ string_append (s, buf);
+ }
+ }
+ else if (is_integral)
{
if (**mangled == 'm')
{
- string_appendn (tname, "-", 1);
+ string_appendn (s, "-", 1);
(*mangled)++;
}
while (isdigit (**mangled))
{
- string_appendn (tname, *mangled, 1);
+ string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
else if (is_char)
{
- char tmp[2];
- int val;
+ char tmp[2];
+ int val;
if (**mangled == 'm')
{
- string_appendn (tname, "-", 1);
+ string_appendn (s, "-", 1);
(*mangled)++;
}
- string_appendn (tname, "'", 1);
+ string_appendn (s, "'", 1);
val = consume_count(mangled);
if (val == 0)
{
success = 0;
+ if (!is_type)
+ string_delete (s);
break;
}
tmp[0] = (char)val;
tmp[1] = '\0';
- string_appendn (tname, &tmp[0], 1);
- string_appendn (tname, "'", 1);
+ string_appendn (s, &tmp[0], 1);
+ string_appendn (s, "'", 1);
}
else if (is_bool)
{
int val = consume_count (mangled);
if (val == 0)
- string_appendn (tname, "false", 5);
+ string_appendn (s, "false", 5);
else if (val == 1)
- string_appendn (tname, "true", 4);
+ string_appendn (s, "true", 4);
else
success = 0;
}
@@ -1024,65 +1176,102 @@ demangle_template (work, mangled, tname, trawname)
{
if (**mangled == 'm')
{
- string_appendn (tname, "-", 1);
+ string_appendn (s, "-", 1);
(*mangled)++;
}
while (isdigit (**mangled))
{
- string_appendn (tname, *mangled, 1);
+ string_appendn (s, *mangled, 1);
(*mangled)++;
}
if (**mangled == '.') /* fraction */
{
- string_appendn (tname, ".", 1);
+ string_appendn (s, ".", 1);
(*mangled)++;
while (isdigit (**mangled))
{
- string_appendn (tname, *mangled, 1);
+ string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
if (**mangled == 'e') /* exponent */
{
- string_appendn (tname, "e", 1);
+ string_appendn (s, "e", 1);
(*mangled)++;
while (isdigit (**mangled))
{
- string_appendn (tname, *mangled, 1);
+ string_appendn (s, *mangled, 1);
(*mangled)++;
}
}
}
else if (is_pointer)
{
- if (!get_count (mangled, &symbol_len))
+ symbol_len = consume_count (mangled);
+ if (symbol_len == 0)
{
success = 0;
+ if (!is_type)
+ string_delete (s);
break;
}
- string_appendn (tname, *mangled, symbol_len);
+ if (symbol_len == 0)
+ string_appendn (s, "0", 1);
+ else
+ {
+ char *p = xmalloc (symbol_len + 1), *q;
+ strncpy (p, *mangled, symbol_len);
+ p [symbol_len] = '\0';
+ q = cplus_demangle (p, work->options);
+ string_appendn (s, "&", 1);
+ if (q)
+ {
+ string_append (s, q);
+ free (q);
+ }
+ else
+ string_append (s, p);
+ free (p);
+ }
*mangled += symbol_len;
}
+ if (!is_type)
+ {
+ int len = s->p - s->b;
+ work->tmpl_argvec[i] = xmalloc (len + 1);
+ memcpy (work->tmpl_argvec[i], s->b, len);
+ work->tmpl_argvec[i][len] = '\0';
+
+ string_appends (tname, s);
+ string_delete (s);
+ }
}
need_comma = 1;
}
- if (tname->p[-1] == '>')
- string_append (tname, " ");
- string_append (tname, ">");
+ if (is_java_array)
+ {
+ string_append (tname, "[]");
+ }
+ else
+ {
+ if (tname->p[-1] == '>')
+ string_append (tname, " ");
+ string_append (tname, ">");
+ }
-/*
- if (work -> static_type)
- {
- string_append (declp, *mangled + 1);
- *mangled += strlen (*mangled);
- success = 1;
- }
- else
- {
- success = demangle_args (work, mangled, declp);
- }
+ /*
+ if (work -> static_type)
+ {
+ string_append (declp, *mangled + 1);
+ *mangled += strlen (*mangled);
+ success = 1;
}
-*/
+ else
+ {
+ success = demangle_args (work, mangled, declp);
+ }
+ }
+ */
return (success);
}
@@ -1096,14 +1285,14 @@ arm_pt (work, mangled, n, anchor, args)
/* ARM template? */
if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__")))
{
- int len;
- *args = *anchor + 6;
- len = consume_count (args);
- if (*args + len == mangled + n && **args == '_')
- {
- ++*args;
- return 1;
- }
+ int len;
+ *args = *anchor + 6;
+ len = consume_count (args);
+ if (*args + len == mangled + n && **args == '_')
+ {
+ ++*args;
+ return 1;
+ }
}
return 0;
}
@@ -1121,26 +1310,26 @@ demangle_arm_pt (work, mangled, n, declp)
/* ARM template? */
if (arm_pt (work, *mangled, n, &p, &args))
- {
- string arg;
- string_init (&arg);
- string_appendn (declp, *mangled, p - *mangled);
- string_append (declp, "<");
- /* should do error checking here */
- while (args < e) {
- string_clear (&arg);
- do_type (work, &args, &arg);
- string_appends (declp, &arg);
- string_append (declp, ",");
- }
- string_delete (&arg);
- --declp->p;
- string_append (declp, ">");
- }
+ {
+ string arg;
+ string_init (&arg);
+ string_appendn (declp, *mangled, p - *mangled);
+ string_append (declp, "<");
+ /* should do error checking here */
+ while (args < e) {
+ string_clear (&arg);
+ do_type (work, &args, &arg);
+ string_appends (declp, &arg);
+ string_append (declp, ",");
+ }
+ string_delete (&arg);
+ --declp->p;
+ string_append (declp, ">");
+ }
else
- {
- string_appendn (declp, *mangled, n);
- }
+ {
+ string_appendn (declp, *mangled, n);
+ }
*mangled += n;
}
@@ -1155,10 +1344,10 @@ demangle_class_name (work, mangled, declp)
n = consume_count (mangled);
if (strlen (*mangled) >= n)
- {
- demangle_arm_pt (work, mangled, n, declp);
- success = 1;
- }
+ {
+ demangle_arm_pt (work, mangled, n, declp);
+ success = 1;
+ }
return (success);
}
@@ -1223,7 +1412,7 @@ demangle_class (work, mangled, declp)
work -> constructor -= 1;
}
}
- string_prepend (declp, "::");
+ string_prepend (declp, (work -> options & DMGL_JAVA) ? "." : "::");
string_prepends (declp, &class_name);
success = 1;
}
@@ -1308,9 +1497,9 @@ demangle_prefix (work, mangled, declp)
work->constructor = 2;
}
-/* This block of code is a reduction in strength time optimization
- of:
- scan = mystrstr (*mangled, "__"); */
+ /* This block of code is a reduction in strength time optimization
+ of:
+ scan = mystrstr (*mangled, "__"); */
{
scan = *mangled;
@@ -1325,7 +1514,7 @@ demangle_prefix (work, mangled, declp)
if (scan != NULL)
{
/* We found a sequence of two or more '_', ensure that we start at
- the last pair in the sequence. */
+ the last pair in the sequence. */
i = strspn (scan, "_");
if (i > 2)
{
@@ -1344,8 +1533,8 @@ demangle_prefix (work, mangled, declp)
success = 0;
}
}
- else if ((scan == *mangled) &&
- (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
+ else if ((scan == *mangled)
+ && (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't')))
{
/* The ARM says nothing about the mangling of local variables.
But cfront mangles local variables by prepending __<nesting_level>
@@ -1394,7 +1583,7 @@ demangle_prefix (work, mangled, declp)
}
else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't')
{
- /* Cfront-style parameterized type. Handled later as a signature. */
+ /* Cfront-style parameterized type. Handled later as a signature. */
success = 1;
/* ARM template? */
@@ -1404,7 +1593,7 @@ demangle_prefix (work, mangled, declp)
{
/* Mangled name does not start with "__" but does have one somewhere
in there with non empty stuff after it. Looks like a global
- function name. */
+ function name. */
demangle_function_name (work, mangled, declp, scan);
}
else
@@ -1473,14 +1662,14 @@ gnu_special (work, mangled, declp)
&& (*mangled)[2] == 'v'
&& (*mangled)[3] == 't'
&& (*mangled)[4] == '_')
- || ((*mangled)[1] == 'v'
- && (*mangled)[2] == 't'
- && strchr (cplus_markers, (*mangled)[3]) != NULL)))
+ || ((*mangled)[1] == 'v'
+ && (*mangled)[2] == 't'
+ && strchr (cplus_markers, (*mangled)[3]) != NULL)))
{
/* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
and create the decl. Note that we consume the entire mangled
input string, which means that demangle_signature has no work
- to do. */
+ to do. */
if ((*mangled)[2] == 'v')
(*mangled) += 5; /* New style, with thunks: "__vt_" */
else
@@ -1494,7 +1683,7 @@ gnu_special (work, mangled, declp)
success = demangle_qualified (work, mangled, declp, 0, 1);
break;
case 't':
- success = demangle_template (work, mangled, declp, 0);
+ success = demangle_template (work, mangled, declp, 0, 1);
break;
default:
if (isdigit(*mangled[0]))
@@ -1513,7 +1702,8 @@ gnu_special (work, mangled, declp)
{
if (p != NULL)
{
- string_append (declp, "::");
+ string_append (declp,
+ (work -> options & DMGL_JAVA) ? "." : "::");
(*mangled)++;
}
}
@@ -1534,23 +1724,23 @@ gnu_special (work, mangled, declp)
(*mangled)++;
switch (**mangled)
{
- case 'Q':
- success = demangle_qualified (work, mangled, declp, 0, 1);
- break;
- case 't':
- success = demangle_template (work, mangled, declp, 0);
- break;
- default:
- n = consume_count (mangled);
- string_appendn (declp, *mangled, n);
- (*mangled) += n;
+ case 'Q':
+ success = demangle_qualified (work, mangled, declp, 0, 1);
+ break;
+ case 't':
+ success = demangle_template (work, mangled, declp, 0, 1);
+ break;
+ default:
+ n = consume_count (mangled);
+ string_appendn (declp, *mangled, n);
+ (*mangled) += n;
}
if (success && (p == *mangled))
{
/* Consumed everything up to the cplus_marker, append the
- variable name. */
+ variable name. */
(*mangled)++;
- string_append (declp, "::");
+ string_append (declp, (work -> options & DMGL_JAVA) ? "." : "::");
n = strlen (*mangled);
string_appendn (declp, *mangled, n);
(*mangled) += n;
@@ -1579,6 +1769,28 @@ gnu_special (work, mangled, declp)
success = 0;
}
}
+ else if (strncmp (*mangled, "__t", 3) == 0
+ && ((*mangled)[3] == 'i' || (*mangled)[3] == 'f'))
+ {
+ p = (*mangled)[3] == 'i' ? " type_info node" : " type_info function";
+ (*mangled) += 4;
+ switch (**mangled)
+ {
+ case 'Q':
+ success = demangle_qualified (work, mangled, declp, 0, 1);
+ break;
+ case 't':
+ success = demangle_template (work, mangled, declp, 0, 1);
+ break;
+ default:
+ success = demangle_fund_type (work, mangled, declp);
+ break;
+ }
+ if (success && **mangled != '\0')
+ success = 0;
+ if (success)
+ string_append (declp, p);
+ }
else
{
success = 0;
@@ -1624,7 +1836,7 @@ arm_special (work, mangled, declp)
/* Found a ARM style virtual table, get past ARM_VTABLE_STRING
and create the decl. Note that we consume the entire mangled
input string, which means that demangle_signature has no work
- to do. */
+ to do. */
scan = *mangled + ARM_VTABLE_STRLEN;
while (*scan != '\0') /* first check it can be demangled */
{
@@ -1762,7 +1974,7 @@ demangle_qualified (work, mangled, result, isfuncname, append)
return success;
/* Pick off the names and collect them in the temp buffer in the order
- in which they are found, separated by '::'. */
+ in which they are found, separated by '::'. */
while (qualifiers-- > 0)
{
@@ -1770,7 +1982,12 @@ demangle_qualified (work, mangled, result, isfuncname, append)
*mangled = *mangled + 1;
if (*mangled[0] == 't')
{
- success = demangle_template(work, mangled, &temp, 0);
+ success = demangle_template(work, mangled, &temp, 0, 1);
+ if (!success) break;
+ }
+ else if (*mangled[0] == 'X')
+ {
+ success = do_type (work, mangled, &temp);
if (!success) break;
}
else
@@ -1778,27 +1995,27 @@ demangle_qualified (work, mangled, result, isfuncname, append)
namelength = consume_count (mangled);
if (strlen (*mangled) < namelength)
{
- /* Simple sanity check failed */
- success = 0;
- break;
+ /* Simple sanity check failed */
+ success = 0;
+ break;
}
string_appendn (&temp, *mangled, namelength);
*mangled += namelength;
}
if (qualifiers > 0)
{
- string_appendn (&temp, "::", 2);
+ string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
}
}
/* If we are using the result as a function name, we need to append
the appropriate '::' separated constructor or destructor name.
We do this here because this is the most convenient place, where
- we already have a pointer to the name and the length of the name. */
+ we already have a pointer to the name and the length of the name. */
if (isfuncname && (work->constructor & 1 || work->destructor & 1))
{
- string_appendn (&temp, "::", 2);
+ string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
if (work -> destructor & 1)
{
string_append (&temp, "~");
@@ -1807,7 +2024,7 @@ demangle_qualified (work, mangled, result, isfuncname, append)
}
/* Now either prepend the temp buffer to the result, or append it,
- depending upon the state of the append flag. */
+ depending upon the state of the append flag. */
if (append)
{
@@ -1817,7 +2034,7 @@ demangle_qualified (work, mangled, result, isfuncname, append)
{
if (!STRING_EMPTY (result))
{
- string_appendn (&temp, "::", 2);
+ string_append (&temp, (work -> options & DMGL_JAVA) ? "." : "::");
}
string_prepends (result, &temp);
}
@@ -1906,20 +2123,21 @@ do_type (work, mangled, result)
switch (**mangled)
{
- /* A pointer type */
+ /* A pointer type */
case 'P':
case 'p':
(*mangled)++;
- string_prepend (&decl, "*");
+ if (! (work -> options & DMGL_JAVA))
+ string_prepend (&decl, "*");
break;
- /* A reference type */
+ /* A reference type */
case 'R':
(*mangled)++;
string_prepend (&decl, "&");
break;
- /* An array */
+ /* An array */
case 'A':
{
const char *p = ++(*mangled);
@@ -1955,7 +2173,7 @@ do_type (work, mangled, result)
}
break;
- /* A function */
+ /* A function */
case 'F':
(*mangled)++;
if (!STRING_EMPTY (&decl) && decl.b[0] == '*')
@@ -1965,7 +2183,7 @@ do_type (work, mangled, result)
}
/* After picking off the function args, we expect to either find the
function return type (preceded by an '_') or the end of the
- string. */
+ string. */
if (!demangle_args (work, mangled, &decl)
|| (**mangled != '_' && **mangled != '\0'))
{
@@ -1985,22 +2203,39 @@ do_type (work, mangled, result)
member = **mangled == 'M';
(*mangled)++;
- if (!isdigit (**mangled))
+ if (!isdigit (**mangled) && **mangled != 't')
{
success = 0;
break;
}
- n = consume_count (mangled);
- if (strlen (*mangled) < n)
+
+ string_append (&decl, ")");
+ string_prepend (&decl, (work -> options & DMGL_JAVA) ? "." : "::");
+ if (isdigit (**mangled))
{
- success = 0;
- break;
+ n = consume_count (mangled);
+ if (strlen (*mangled) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_prependn (&decl, *mangled, n);
+ *mangled += n;
+ }
+ else
+ {
+ string temp;
+ string_init (&temp);
+ success = demangle_template (work, mangled, &temp, NULL, 1);
+ if (success)
+ {
+ string_prependn (&decl, temp.b, temp.p - temp.b);
+ string_clear (&temp);
+ }
+ else
+ break;
}
- string_append (&decl, ")");
- string_prepend (&decl, "::");
- string_prependn (&decl, *mangled, n);
string_prepend (&decl, "(");
- *mangled += n;
if (member)
{
if (**mangled == 'C')
@@ -2043,27 +2278,27 @@ do_type (work, mangled, result)
break;
}
case 'G':
- (*mangled)++;
- break;
+ (*mangled)++;
+ break;
case 'C':
(*mangled)++;
-/*
- if ((*mangled)[1] == 'P')
+ /*
+ if ((*mangled)[1] == 'P')
{
-*/
- if (PRINT_ANSI_QUALIFIERS)
+ */
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ if (!STRING_EMPTY (&decl))
{
- if (!STRING_EMPTY (&decl))
- {
- string_prepend (&decl, " ");
- }
- string_prepend (&decl, "const");
+ string_prepend (&decl, " ");
}
- break;
-/*
+ string_prepend (&decl, "const");
}
-*/
+ break;
+ /*
+ }
+ */
/* fall through */
default:
@@ -2074,14 +2309,45 @@ do_type (work, mangled, result)
switch (**mangled)
{
- /* A qualified name, such as "Outer::Inner". */
- case 'Q':
- success = demangle_qualified (work, mangled, result, 0, 1);
- break;
+ /* A qualified name, such as "Outer::Inner". */
+ case 'Q':
+ success = demangle_qualified (work, mangled, result, 0, 1);
+ break;
+
+ case 'X':
+ case 'Y':
+ /* A template parm. We substitute the corresponding argument. */
+ {
+ int idx;
+ int lvl;
+
+ (*mangled)++;
+ idx = consume_count_with_underscores (mangled);
+
+ if (idx == -1
+ || (work->tmpl_argvec && idx >= work->ntmpl_args)
+ || consume_count_with_underscores (mangled) == -1)
+ {
+ success = 0;
+ break;
+ }
- default:
- success = demangle_fund_type (work, mangled, result);
- break;
+ if (work->tmpl_argvec)
+ string_append (result, work->tmpl_argvec[idx]);
+ else
+ {
+ char buf[10];
+ sprintf(buf, "T%d", idx);
+ string_append (result, buf);
+ }
+
+ success = 1;
+ }
+ break;
+
+ default:
+ success = demangle_fund_type (work, mangled, result);
+ break;
}
if (success)
@@ -2122,138 +2388,143 @@ demangle_fund_type (work, mangled, result)
int done = 0;
int success = 1;
- /* First pick off any type qualifiers. There can be more than one. */
+ /* First pick off any type qualifiers. There can be more than one. */
while (!done)
{
switch (**mangled)
{
- case 'C':
- (*mangled)++;
- if (PRINT_ANSI_QUALIFIERS)
- {
- APPEND_BLANK (result);
- string_append (result, "const");
- }
- break;
- case 'U':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "unsigned");
- break;
- case 'S': /* signed char only */
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "signed");
- break;
- case 'V':
- (*mangled)++;
- if (PRINT_ANSI_QUALIFIERS)
- {
- APPEND_BLANK (result);
- string_append (result, "volatile");
- }
- break;
- default:
- done = 1;
- break;
+ case 'C':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "const");
+ }
+ break;
+ case 'U':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "unsigned");
+ break;
+ case 'S': /* signed char only */
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "signed");
+ break;
+ case 'V':
+ (*mangled)++;
+ if (PRINT_ANSI_QUALIFIERS)
+ {
+ APPEND_BLANK (result);
+ string_append (result, "volatile");
+ }
+ break;
+ case 'J':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "__complex");
+ break;
+ default:
+ done = 1;
+ break;
}
}
- /* Now pick off the fundamental type. There can be only one. */
+ /* Now pick off the fundamental type. There can be only one. */
switch (**mangled)
{
- case '\0':
- case '_':
- break;
- case 'v':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "void");
- break;
- case 'x':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "long long");
- break;
- case 'l':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "long");
- break;
- case 'i':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "int");
- break;
- case 's':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "short");
- break;
- case 'b':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "bool");
- break;
- case 'c':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "char");
- break;
- case 'w':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "wchar_t");
- break;
- case 'r':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "long double");
- break;
- case 'd':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "double");
- break;
- case 'f':
- (*mangled)++;
- APPEND_BLANK (result);
- string_append (result, "float");
- break;
- case 'G':
- (*mangled)++;
- if (!isdigit (**mangled))
- {
- success = 0;
- break;
- }
- /* fall through */
- /* An explicit type, such as "6mytype" or "7integer" */
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- APPEND_BLANK (result);
- if (!demangle_class_name (work, mangled, result)) {
- --result->p;
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "void");
+ break;
+ case 'x':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long long");
+ break;
+ case 'l':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long");
+ break;
+ case 'i':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "int");
+ break;
+ case 's':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "short");
+ break;
+ case 'b':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "bool");
+ break;
+ case 'c':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "char");
+ break;
+ case 'w':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "wchar_t");
+ break;
+ case 'r':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "long double");
+ break;
+ case 'd':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "double");
+ break;
+ case 'f':
+ (*mangled)++;
+ APPEND_BLANK (result);
+ string_append (result, "float");
+ break;
+ case 'G':
+ (*mangled)++;
+ if (!isdigit (**mangled))
+ {
success = 0;
+ break;
}
- break;
- case 't':
- success = demangle_template(work,mangled, result, 0);
- break;
- default:
+ /* fall through */
+ /* An explicit type, such as "6mytype" or "7integer" */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ APPEND_BLANK (result);
+ if (!demangle_class_name (work, mangled, result)) {
+ --result->p;
success = 0;
- break;
}
+ break;
+ case 't':
+ success = demangle_template(work,mangled, result, 0, 1);
+ break;
+ default:
+ success = 0;
+ break;
+ }
return (success);
}
@@ -2292,15 +2563,15 @@ remember_type (work, start, len)
if (work -> typevec_size == 0)
{
work -> typevec_size = 3;
- work -> typevec =
- (char **) xmalloc (sizeof (char *) * work -> typevec_size);
+ work -> typevec
+ = (char **) xmalloc (sizeof (char *) * work -> typevec_size);
}
else
{
work -> typevec_size *= 2;
- work -> typevec =
- (char **) xrealloc ((char *)work -> typevec,
- sizeof (char *) * work -> typevec_size);
+ work -> typevec
+ = (char **) xrealloc ((char *)work -> typevec,
+ sizeof (char *) * work -> typevec_size);
}
}
tem = xmalloc (len + 1);
@@ -2309,7 +2580,7 @@ remember_type (work, start, len)
work -> typevec[work -> ntypes++] = tem;
}
-/* Forget the remembered types, but not the type vector itself. */
+/* Forget the remembered types, but not the type vector itself. */
static void
forget_types (work)
@@ -2434,7 +2705,7 @@ demangle_args (work, mangled, declp)
t--;
}
/* Validate the type index. Protect against illegal indices from
- malformed type strings. */
+ malformed type strings. */
if ((t < 0) || (t >= work -> ntypes))
{
return (0);
@@ -2515,7 +2786,7 @@ demangle_function_name (work, mangled, declp, scan)
/* Consume the function name, including the "__" separating the name
from the signature. We are guaranteed that SCAN points to the
- separator. */
+ separator. */
(*mangled) = scan + 2;
@@ -2525,7 +2796,7 @@ demangle_function_name (work, mangled, declp, scan)
/* See if we have an ARM style constructor or destructor operator.
If so, then just record it, clear the decl, and return.
We can't build the actual constructor/destructor decl until later,
- when we recover the class name from the signature. */
+ when we recover the class name from the signature. */
if (strcmp (declp -> b, "__ct") == 0)
{
@@ -2594,7 +2865,7 @@ demangle_function_name (work, mangled, declp, scan)
}
}
else if (declp->b[0] == '_' && declp->b[1] == '_'
- && declp->b[2] == 'o' && declp->b[3] == 'p')
+ && declp->b[2] == 'o' && declp->b[3] == 'p')
{
/* ANSI. */
/* type conversion operator. */
@@ -2630,7 +2901,7 @@ demangle_function_name (work, mangled, declp, scan)
{
if (declp->b[2] == 'a' && declp->b[5] == '\0')
{
- /* Assignment. */
+ /* Assignment. */
for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++)
{
if (strlen (optable[i].in) == 3
@@ -2799,17 +3070,27 @@ string_prependn (p, s, n)
/* To generate a standalone demangler program for testing purposes,
just compile and link this file with -DMAIN and libiberty.a. When
run, it demangles each command line arg, or each stdin string, and
- prints the result on stdout. */
+ prints the result on stdout. */
#ifdef MAIN
+#include "getopt.h"
+
+static char *program_name;
+static char *program_version = VERSION;
+static int flags = DMGL_PARAMS | DMGL_ANSI;
+
+static void demangle_it PARAMS ((char *));
+static void usage PARAMS ((FILE *, int));
+static void fatal PARAMS ((char *));
+
static void
demangle_it (mangled_name)
- char *mangled_name;
+ char *mangled_name;
{
char *result;
- result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI);
+ result = cplus_demangle (mangled_name, flags);
if (result == NULL)
{
printf ("%s\n", mangled_name);
@@ -2821,11 +3102,6 @@ demangle_it (mangled_name)
}
}
-#include "getopt.h"
-
-static char *program_name;
-static char *program_version = VERSION;
-
static void
usage (stream, status)
FILE *stream;
@@ -2833,8 +3109,8 @@ usage (stream, status)
{
fprintf (stream, "\
Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
- [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
- [--help] [--version] [arg...]\n",
+ [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\
+ [--help] [--version] [arg...]\n",
program_name);
exit (status);
}
@@ -2842,7 +3118,7 @@ Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\
#define MBUF_SIZE 512
char mbuffer[MBUF_SIZE];
-/* Defined in the automatically-generated underscore.c. */
+/* Defined in the automatically-generated underscore.c. */
extern int prepends_underscore;
int strip_underscore = 0;
@@ -2851,11 +3127,21 @@ static struct option long_options[] = {
{"strip-underscores", no_argument, 0, '_'},
{"format", required_argument, 0, 's'},
{"help", no_argument, 0, 'h'},
+ {"java", no_argument, 0, 'j'},
{"no-strip-underscores", no_argument, 0, 'n'},
{"version", no_argument, 0, 'v'},
{0, no_argument, 0, 0}
};
+/* More 'friendly' abort that prints the line and file.
+ config.h can #define abort fancy_abort if you like that sort of thing. */
+
+void
+fancy_abort ()
+{
+ fatal ("Internal gcc abort.");
+}
+
int
main (argc, argv)
int argc;
@@ -2868,44 +3154,47 @@ main (argc, argv)
strip_underscore = prepends_underscore;
- while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF)
+ while ((c = getopt_long (argc, argv, "_ns:j", long_options, (int *) 0)) != EOF)
{
switch (c)
{
- case '?':
- usage (stderr, 1);
- break;
- case 'h':
- usage (stdout, 0);
- case 'n':
- strip_underscore = 0;
- break;
- case 'v':
- printf ("GNU %s version %s\n", program_name, program_version);
- exit (0);
- case '_':
- strip_underscore = 1;
- break;
- case 's':
- if (strcmp (optarg, "gnu") == 0)
- {
- current_demangling_style = gnu_demangling;
- }
- else if (strcmp (optarg, "lucid") == 0)
- {
- current_demangling_style = lucid_demangling;
- }
- else if (strcmp (optarg, "arm") == 0)
- {
- current_demangling_style = arm_demangling;
- }
- else
- {
- fprintf (stderr, "%s: unknown demangling style `%s'\n",
- program_name, optarg);
- exit (1);
- }
- break;
+ case '?':
+ usage (stderr, 1);
+ break;
+ case 'h':
+ usage (stdout, 0);
+ case 'n':
+ strip_underscore = 0;
+ break;
+ case 'v':
+ printf ("GNU %s version %s\n", program_name, program_version);
+ exit (0);
+ case '_':
+ strip_underscore = 1;
+ break;
+ case 'j':
+ flags |= DMGL_JAVA;
+ break;
+ case 's':
+ if (strcmp (optarg, "gnu") == 0)
+ {
+ current_demangling_style = gnu_demangling;
+ }
+ else if (strcmp (optarg, "lucid") == 0)
+ {
+ current_demangling_style = lucid_demangling;
+ }
+ else if (strcmp (optarg, "arm") == 0)
+ {
+ current_demangling_style = arm_demangling;
+ }
+ else
+ {
+ fprintf (stderr, "%s: unknown demangling style `%s'\n",
+ program_name, optarg);
+ exit (1);
+ }
+ break;
}
}
@@ -2922,7 +3211,7 @@ main (argc, argv)
{
int i = 0;
c = getchar ();
- /* Try to read a label. */
+ /* Try to read a label. */
while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.'))
{
if (i >= MBUF_SIZE-1)
@@ -2944,8 +3233,7 @@ main (argc, argv)
mbuffer[i] = 0;
- result = cplus_demangle (mbuffer + skip_first,
- DMGL_PARAMS | DMGL_ANSI);
+ result = cplus_demangle (mbuffer + skip_first, flags);
if (result)
{
if (mbuffer[0] == '.')
diff --git a/gnu/usr.bin/gcc/cpp.texi b/gnu/usr.bin/gcc/cpp.texi
index 1de8371701e..9424b48f985 100644
--- a/gnu/usr.bin/gcc/cpp.texi
+++ b/gnu/usr.bin/gcc/cpp.texi
@@ -45,7 +45,7 @@ into another language, under the above conditions for modified versions.
@titlepage
@c @finalout
@title The C Preprocessor
-@subtitle Last revised July 1992
+@subtitle Last revised March 1997
@subtitle for GCC version 2
@author Richard M. Stallman
@page
@@ -54,7 +54,7 @@ This booklet is eventually intended to form the first chapter of a GNU
C Language manual.
@vskip 0pt plus 1filll
-Copyright @copyright{} 1987, 1989, 1991, 1992, 1993, 1994, 1995 Free
+Copyright @copyright{} 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free
Software Foundation, Inc.
Permission is granted to make and distribute verbatim copies of
@@ -105,7 +105,7 @@ to inform the compiler of where each source line originally came from.
C preprocessors vary in some details. This manual discusses the GNU C
preprocessor, the C Compatible Compiler Preprocessor. The GNU C
-preprocessor provides a superset of the features of ANSI Standard C.
+preprocessor provides a superset of the features of ANSI Standard C@.
ANSI Standard C requires the rejection of many harmless constructs commonly
used by today's C programs. Such incompatibility would be inconvenient for
@@ -115,6 +115,12 @@ options @samp{-trigraphs}, @samp{-undef} and @samp{-pedantic}, but in
practice the consequences of having strict ANSI Standard C make it
undesirable to do this. @xref{Invocation}.
+The C preprocessor is designed for C-like languages; you may run into
+problems if you apply it to other kinds of languages, because it assumes
+that it is dealing with C@. For example, the C preprocessor sometimes
+outputs extra white space to avoid inadvertent C token concatenation,
+and this may cause problems with other languages.
+
@menu
* Global Actions:: Actions made uniformly on all input files.
* Directives:: General syntax of preprocessing directives.
@@ -490,14 +496,14 @@ names, then inheritance is straightforward: simply write @samp{#include
Sometimes it is necessary to give the inheriting file the same name as
the base file. This is less straightforward.
-For example, suppose an application program uses the system header file
+For example, suppose an application program uses the system header
@file{sys/signal.h}, but the version of @file{/usr/include/sys/signal.h}
on a particular system doesn't do what the application program expects.
It might be convenient to define a ``local'' version, perhaps under the
name @file{/usr/local/include/sys/signal.h}, to override or add to the
one supplied by the system.
-You can do this by using the option @samp{-I.} for compilation, and
+You can do this by compiling with the option @samp{-I.}, and
writing a file @file{sys/signal.h} that does what the application
program expects. But making this file include the standard
@file{sys/signal.h} is not so easy---writing @samp{#include
@@ -521,8 +527,8 @@ file directories @emph{after} the directory in which the current file
was found.
Suppose you specify @samp{-I /usr/local/include}, and the list of
-directories to search also includes @file{/usr/include}; and suppose that
-both directories contain a file named @file{sys/signal.h}. Ordinary
+directories to search also includes @file{/usr/include}; and suppose
+both directories contain @file{sys/signal.h}. Ordinary
@samp{#include <sys/signal.h>} finds the file under
@file{/usr/local/include}. If that file contains @samp{#include_next
<sys/signal.h>}, it starts searching after that directory, and finds the
@@ -671,7 +677,7 @@ values, as it is defined in many C programs:
@end example
@noindent
-(This is not the best way to define a ``minimum'' macro in GNU C.
+(This is not the best way to define a ``minimum'' macro in GNU C@.
@xref{Side Effects}, for more information.)
To use a macro that expects arguments, you write the name of the macro
@@ -814,7 +820,7 @@ system-specific macros.
@cindex standard predefined macros
The standard predefined macros are available with the same meanings
-regardless of the machine or operating system on which you are using GNU C.
+regardless of the machine or operating system on which you are using GNU C@.
Their names all start and end with double underscores. Those preceding
@code{__GNUC__} in this table are standardized by ANSI C; the rest are
GNU C extensions.
@@ -859,8 +865,9 @@ if a @samp{#line} directive is used. @xref{Combining Sources}.
@findex __DATE__
This macro expands to a string constant that describes the date on
which the preprocessor is being run. The string constant contains
-eleven characters and looks like @samp{"Jan 29 1987"} or @w{@samp{"Apr
-1 1905"}}.
+eleven characters and looks like @w{@samp{"Feb 1 1996"}}.
+@c After reformatting the above, check that the date remains `Feb 1 1996',
+@c all on one line, with two spaces between the `Feb' and the `1'.
@item __TIME__
@findex __TIME__
@@ -871,9 +878,17 @@ eight characters and looks like @samp{"23:59:01"}.
@item __STDC__
@findex __STDC__
This macro expands to the constant 1, to signify that this is ANSI
-Standard C. (Whether that is actually true depends on what C compiler
+Standard C@. (Whether that is actually true depends on what C compiler
will operate on the output from the preprocessor.)
+On some hosts, system include files use a different convention, where
+@samp{__STDC__} is normally 0, but is 1 if the user specifies strict
+conformance to the C Standard. The preprocessor follows the host convention
+when processing system include files, but when processing user files it follows
+the usual GNU C convention.
+
+This macro is not defined if the @samp{-traditional} option is used.
+
@item __STDC_VERSION__
@findex __STDC_VERSION__
This macro expands to the C Standard's version number,
@@ -884,9 +899,11 @@ Like @samp{__STDC__}, whether this version number is accurate
for the entire implementation depends on what C compiler
will operate on the output from the preprocessor.
+This macro is not defined if the @samp{-traditional} option is used.
+
@item __GNUC__
@findex __GNUC__
-This macro is defined if and only if this is GNU C. This macro is
+This macro is defined if and only if this is GNU C@. This macro is
defined only when the entire GNU C compiler is in use; if you invoke the
preprocessor directly, @samp{__GNUC__} is undefined. The value
identifies the major version number of GNU CC (@samp{1} for GNU CC
@@ -921,7 +938,7 @@ This macro is defined if and only if the @samp{-ansi} switch was
specified when GNU C was invoked. Its definition is the null string.
This macro exists primarily to direct certain GNU header files not to
define certain traditional Unix constructs which are incompatible with
-ANSI C.
+ANSI C@.
@item __BASE_FILE__
@findex __BASE_FILE__
@@ -940,7 +957,7 @@ the nesting level is zero.
@item __VERSION__
@findex __VERSION__
This macro expands to a string which describes the version number of
-GNU C. The string is normally a sequence of decimal numbers separated
+GNU C@. The string is normally a sequence of decimal numbers separated
by periods, such as @samp{"2.6.0"}. The only reasonable use of this
macro is to incorporate it into a string constant.
@@ -956,9 +973,9 @@ execute with the same effect regardless.
@findex __CHAR_UNSIGNED__
This macro is defined if and only if the data type @code{char} is
unsigned on the target machine. It exists to cause the standard
-header file @file{limit.h} to work correctly. It is bad practice
+header file @file{limits.h} to work correctly. It is bad practice
to refer to this macro yourself; instead, refer to the standard
-macros defined in @file{limit.h}. The preprocessor uses
+macros defined in @file{limits.h}. The preprocessor uses
this macro to determine whether or not to sign-extend large character
constants written in octal; see @ref{#if Directive,,The @samp{#if} Directive}.
@@ -973,12 +990,14 @@ but in the @samp{m68k-coff} environment it expands to the string
@item __USER_LABEL_PREFIX__
@findex __USER_LABEL_PREFIX__
-This macro expands to a string describing the prefix applied to
-user generated labels in assembler code. It can be used to write
-assembler code that is usable in multiple environments.
-For example, in the @samp{m68k-aout} environment it expands to the
-string @samp{"_"}, but in the @samp{m68k-coff} environment it expands
-to the string @samp{""}.
+This macro expands to a string describing the prefix applied to user
+generated labels in assembler code. It can be used to write assembler
+code that is usable in multiple environments. For example, in the
+@samp{m68k-aout} environment it expands to the string @samp{"_"}, but in
+the @samp{m68k-coff} environment it expands to the string @samp{""}.
+This does not work with the @samp{-mno-underscores} option that the
+i386 OSF/rose and m88k targets provide nor with the @samp{-mcall*} options
+of the rs6000 System V Release 4 target.
@end table
@node Nonstandard Predefined,, Standard Predefined, Predefined
@@ -1237,7 +1256,7 @@ possible to piece together a string constant. However, two pieces of text
that don't together form a valid lexical unit cannot be concatenated. For
example, concatenation with @samp{x} on one side and @samp{+} on the other
is not meaningful because those two characters can't fit together in any
-lexical unit of C. The ANSI standard says that such attempts at
+lexical unit of C@. The ANSI standard says that such attempts at
concatenation are undefined, but in the GNU C preprocessor it is well
defined: it puts the @samp{x} and @samp{+} side by side with no particular
special results.
@@ -1437,7 +1456,7 @@ Defining the macro as
@noindent
provides the desired result.
-However, unintended grouping can result in another way. Consider
+Unintended grouping can result in another way. Consider
@samp{sizeof ceil_div(1, 2)}. That has the appearance of a C expression
that would compute the size of the type of @samp{ceil_div (1, 2)}, but in
fact it means something very different. Here is what it expands to:
@@ -1958,7 +1977,7 @@ practice because it helps people match the @samp{#endif} to the
corresponding @samp{#if}. Such comments should always be used, except in
short conditionals that are not nested. In fact, you can put anything at
all after the @samp{#endif} and it will be ignored by the GNU C preprocessor,
-but only comments are acceptable in ANSI Standard C.
+but only comments are acceptable in ANSI Standard C@.
@var{expression} is a C expression of integer type, subject to stringent
restrictions. It may contain
@@ -2327,7 +2346,7 @@ when you run @code{gcc} or @code{cpp}. @xref{Invocation}.
@findex #error
The directive @samp{#error} causes the preprocessor to report a fatal
error. The rest of the line that follows @samp{#error} is used as the
-error message.
+error message. The line must consist of complete tokens.
You would use @samp{#error} inside of a conditional that detects a
combination of parameters which you know the program does not properly
@@ -2337,7 +2356,7 @@ properly on a Vax, you might write
@smallexample
@group
#ifdef __vax__
-#error Won't work on Vaxen. See comments at get_last_object.
+#error "Won't work on Vaxen. See comments at get_last_object."
#endif
@end group
@end smallexample
@@ -2441,8 +2460,8 @@ rather than a line of output containing just a @samp{#}. Supposedly
some old C programs contain such lines.
@findex #pragma
-The ANSI standard specifies that the @samp{#pragma} directive has an
-arbitrary, implementation-defined effect. In the GNU C preprocessor,
+The ANSI standard specifies that the effect of the @samp{#pragma}
+directive is implementation-defined. In the GNU C preprocessor,
@samp{#pragma} directives are not used, except for @samp{#pragma once}
(@pxref{Once-Only}). However, they are left in the preprocessor output,
so they are available to the compilation pass.
@@ -2462,7 +2481,8 @@ where it is meaningful.
The output from the C preprocessor looks much like the input, except
that all preprocessing directive lines have been replaced with blank lines
and all comments with spaces. Whitespace within a line is not altered;
-however, a space is inserted after the expansions of most macro calls.
+however, unless @samp{-traditional} is used, spaces may be inserted into
+the expansions of macro calls to prevent tokens from being concatenated.
Source file name and line number information is conveyed by lines of
the form
@@ -2489,7 +2509,7 @@ This indicates returning to a file (after having included another file).
This indicates that the following text comes from a system header file,
so certain warnings should be suppressed.
@item 4
-This indicates that the following text should be treated as C.
+This indicates that the following text should be treated as C@.
@c maybe cross reference NO_IMPLICIT_EXTERN_C
@end table
@@ -2534,7 +2554,7 @@ output before the expansion of the macro call.
@item -traditional
@findex -traditional
-Try to imitate the behavior of old-fashioned C, as opposed to ANSI C.
+Try to imitate the behavior of old-fashioned C, as opposed to ANSI C@.
@itemize @bullet
@item
@@ -2562,17 +2582,17 @@ It considers @samp{1.0e+4} to be three tokens: @samp{1.0e}, @samp{+},
and @samp{4}.
@item
-A macro is not suppressed within its own definition, in traditional C.
+A macro is not suppressed within its own definition, in traditional C@.
Thus, any macro that is used recursively inevitably causes an error.
@item
The character @samp{#} has no special meaning within a macro definition
-in traditional C.
+in traditional C@.
@item
In traditional C, the text at the end of a macro expansion can run
together with the text after the macro call, to produce a single token.
-(This is impossible in ANSI C.)
+(This is impossible in ANSI C@.)
@item
Traditionally, @samp{\} inside a macro argument suppresses the syntactic
@@ -2614,17 +2634,22 @@ Warn if any trigraphs are encountered (assuming they are enabled).
@itemx -Wcomments
(Both forms have the same effect).
@end ignore
-Warn whenever a comment-start sequence @samp{/*} appears in a comment.
+Warn whenever a comment-start sequence @samp{/*} appears in a @samp{/*}
+comment, or whenever a Backslash-Newline appears in a @samp{//} comment.
@item -Wall
@findex -Wall
Requests both @samp{-Wtrigraphs} and @samp{-Wcomment} (but not
-@samp{-Wtraditional}).
+@samp{-Wtraditional} or @samp{-Wundef}).
@item -Wtraditional
@findex -Wtraditional
Warn about certain constructs that behave differently in traditional and
-ANSI C.
+ANSI C@.
+
+@item -Wundef
+@findex -Wundef
+Warn if an undefined identifier is evaluated in an @samp{#if} directive.
@item -I @var{directory}
@findex -I
@@ -2664,6 +2689,15 @@ Do not search for header files in the C++-specific standard directories,
but do still search the other standard directories.
(This option is used when building libg++.)
+@item -remap
+@findex -remap
+When searching for a header file in a directory, remap file names if a
+file named @file{header.gcc} exists in that directory. This can be used
+to work around limitations of file systems with file name restrictions.
+The @file{header.gcc} file should contain a series of lines with two
+tokens on each line: the first token is the name to map, and the second
+token is the actual name to use.
+
@item -D @var{name}
@findex -D
Predefine @var{name} as a macro, with definition @samp{1}.
@@ -2718,6 +2752,10 @@ predefined macros, and it outputs @emph{both} the @samp{#define}
directives and the result of preprocessing. Both kinds of output go to
the standard output file.
+@item -dI
+@findex -dI
+Output @samp{#include} directives in addition to the result of preprocessing.
+
@item -M [-MG]
@findex -M
Instead of outputting the result of preprocessing, output a rule
@@ -2813,9 +2851,10 @@ is applied to the standard system directories.
@findex -lang-objc++
Specify the source language. @samp{-lang-c} is the default; it
allows recognition of C++ comments (comments that begin with
-@samp{//} and end at end of line), since this is
-a common feature and it will most likely be in the next C standard.
-@samp{-lang-c89} disables recognition of C++ comments. @samp{-lang-c++}
+@samp{//} and end at end of line) and hexadecimal floating-point constants,
+since these features will most likely appear in the next C standard.
+@samp{-lang-c89} disables recognition of C++ comments and
+hexadecimal floating-point constants. @samp{-lang-c++}
handles C++ comment syntax and includes extra default include
directories for C++. @samp{-lang-objc} enables the Objective C
@samp{#import} directive. @samp{-lang-objc++} enables both C++ and Objective C
@@ -2836,11 +2875,12 @@ This option is available only when you call @code{cpp} directly;
@item -$
@findex -$
-Forbid the use of @samp{$} in identifiers. This is required for ANSI
-conformance. @code{gcc} automatically supplies this option to the
-preprocessor if you specify @samp{-ansi}, but @code{gcc} doesn't
-recognize the @samp{-$} option itself---to use it without the other
-effects of @samp{-ansi}, you must call the preprocessor directly.
+Forbid the use of @samp{$} in identifiers. This was formerly required
+for strict conformance to the C Standard before the standard was
+corrected.
+
+This option is available only when you call @code{cpp} directly;
+@code{gcc} will not pass it from its command line.
@end table
diff --git a/gnu/usr.bin/gcc/cppalloc.c b/gnu/usr.bin/gcc/cppalloc.c
index f7b6019d460..79d4c9b3f65 100644
--- a/gnu/usr.bin/gcc/cppalloc.c
+++ b/gnu/usr.bin/gcc/cppalloc.c
@@ -23,11 +23,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
what you give them. Help stamp out software-hoarding! */
#include "config.h"
+#include <stdio.h>
+#include "cpplib.h"
static void
memory_full ()
{
- fatal ("Memory exhausted.");
+ fprintf (stderr, "%s: Memory exhausted.\n", progname);
+ exit (FATAL_EXIT_CODE);
}
char *
@@ -35,10 +38,9 @@ xmalloc (size)
unsigned size;
{
register char *ptr = (char *) malloc (size);
- if (ptr != 0) return (ptr);
- memory_full ();
- /*NOTREACHED*/
- return 0;
+ if (ptr == 0)
+ memory_full ();
+ return ptr;
}
char *
@@ -51,14 +53,3 @@ xrealloc (old, size)
memory_full ();
return ptr;
}
-
-char *
-xcalloc (number, size)
- unsigned number, size;
-{
- register unsigned total = number * size;
- register char *ptr = (char *) calloc (number, size);
- if (ptr == 0)
- memory_full ();
- return ptr;
-}
diff --git a/gnu/usr.bin/gcc/cpperror.c b/gnu/usr.bin/gcc/cpperror.c
index 5ba3b78f457..0cf24b90ce3 100644
--- a/gnu/usr.bin/gcc/cpperror.c
+++ b/gnu/usr.bin/gcc/cpperror.c
@@ -88,31 +88,39 @@ cpp_file_line_for_message (pfile, filename, line, column)
fprintf (stderr, "%s:%d: ", filename, line);
}
-/* IS_ERROR is 1 for error, 0 for warning */
-void cpp_message (pfile, is_error, msg, arg1, arg2, arg3)
+/* IS_ERROR is 2 for "fatal" error, 1 for error, 0 for warning */
+
+void
+cpp_message (pfile, is_error, msg, arg1, arg2, arg3)
int is_error;
cpp_reader *pfile;
char *msg;
char *arg1, *arg2, *arg3;
{
- if (is_error)
- pfile->errors++;
- else
+ if (!is_error)
fprintf (stderr, "warning: ");
+ else if (is_error == 2)
+ pfile->errors = CPP_FATAL_LIMIT;
+ else if (pfile->errors < CPP_FATAL_LIMIT)
+ pfile->errors++;
fprintf (stderr, msg, arg1, arg2, arg3);
fprintf (stderr, "\n");
}
+/* Same as cpp_error, except we consider the error to be "fatal",
+ such as inconsistent options. I.e. there is little point in continuing.
+ (We do not exit, to support use of cpplib as a library.
+ Instead, it is the caller's responsibility to check
+ CPP_FATAL_ERRORS. */
+
void
-fatal (str, arg)
+cpp_fatal (pfile, str, arg)
+ cpp_reader *pfile;
char *str, *arg;
{
fprintf (stderr, "%s: ", progname);
- fprintf (stderr, str, arg);
- fprintf (stderr, "\n");
- exit (FATAL_EXIT_CODE);
+ cpp_message (pfile, 2, str, arg);
}
-
void
cpp_pfatal_with_name (pfile, name)
diff --git a/gnu/usr.bin/gcc/cppexp.c b/gnu/usr.bin/gcc/cppexp.c
index 6b73ad34e4d..98ad8787877 100644
--- a/gnu/usr.bin/gcc/cppexp.c
+++ b/gnu/usr.bin/gcc/cppexp.c
@@ -1,5 +1,5 @@
/* Parse C expressions for CCCP.
- Copyright (C) 1987, 1992, 1994, 1995 Free Software Foundation.
+ Copyright (C) 1987, 1992, 1994, 1995, 1997, 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
@@ -20,21 +20,26 @@ Boston, MA 02111-1307, USA.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding!
-Written by Per Bothner 1994. */
+Written by Per Bothner 1994. */
/* Parse a C expression from text in a string */
#include "config.h"
#include "cpplib.h"
+#include "gansidecl.h"
extern char *xmalloc PARAMS ((unsigned));
-extern char *xrealloc PARAMS ((char *, unsigned));
+extern char *xrealloc PARAMS ((void *, unsigned));
#ifdef MULTIBYTE_CHARS
#include <stdlib.h>
#include <locale.h>
#endif
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
#include <stdio.h>
/* This is used for communicating lists of keywords with cccp.c. */
@@ -60,7 +65,7 @@ struct arglist {
#endif
#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
+#define NULL_PTR ((GENERIC_PTR) 0)
#endif
extern char *xmalloc ();
@@ -121,26 +126,47 @@ static long right_shift ();
#define LEFT_OPERAND_REQUIRED 1
#define RIGHT_OPERAND_REQUIRED 2
#define HAVE_VALUE 4
-/*#define UNSIGNEDP 8*/
-
-#ifndef HOST_BITS_PER_WIDE_INT
+/* SKIP_OPERAND is set for '&&' '||' '?' and ':' when the
+ following operand should be short-circuited instead of evaluated. */
+#define SKIP_OPERAND 8
+/*#define UNSIGNEDP 16*/
+
+/* Find the largest host integer type and set its size and type.
+ Watch out: on some crazy hosts `long' is shorter than `int'. */
+
+#ifndef HOST_WIDE_INT
+# if HAVE_INTTYPES_H
+# include <inttypes.h>
+# define HOST_WIDE_INT intmax_t
+# else
+# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \
+ && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
+# define HOST_WIDE_INT int
+# else
+# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \
+ || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
+# define HOST_WIDE_INT long
+# else
+# define HOST_WIDE_INT long long
+# endif
+# endif
+# endif
+#endif
-#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
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
#endif
+#ifndef HOST_BITS_PER_WIDE_INT
+#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
#endif
struct operation {
short op;
- char rprio; /* Priority of op (relative to it right operand). */
+ char rprio; /* Priority of op (relative to it right operand). */
char flags;
char unsignedp; /* true if value should be treated as unsigned */
- HOST_WIDE_INT value; /* The value logically "right" of op. */
+ HOST_WIDE_INT value; /* The value logically "right" of op. */
};
/* Take care of parsing a number (anything that starts with a digit).
@@ -183,7 +209,7 @@ parse_number (pfile, start, olen)
else if (*p == '0')
base = 8;
- /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
+ /* Some buggy compilers (e.g. MPW C) seem to need both casts. */
ULONG_MAX_over_base = ((unsigned long) -1) / ((unsigned long) base);
for (; len > 0; len--) {
@@ -235,10 +261,10 @@ parse_number (pfile, start, olen)
}
if (base <= largest_digit)
- cpp_warning (pfile, "integer constant contains digits beyond the radix");
+ cpp_pedwarn (pfile, "integer constant contains digits beyond the radix");
if (overflow)
- cpp_warning (pfile, "integer constant out of range");
+ cpp_pedwarn (pfile, "integer constant out of range");
/* If too big to be signed, consider it unsigned. */
if ((long) n < 0 && ! op.unsignedp)
@@ -272,11 +298,12 @@ static struct token tokentab2[] = {
{NULL, ERROR}
};
-/* Read one token. */
+/* Read one token. */
struct operation
-cpp_lex (pfile)
-cpp_reader *pfile;
+cpp_lex (pfile, skip_evaluation)
+ cpp_reader *pfile;
+ int skip_evaluation;
{
register int c;
register int namelen;
@@ -307,16 +334,17 @@ cpp_reader *pfile;
pfile->limit = tok_start;
switch (token)
{
- case CPP_EOF: /* Should not happen ... */
+ case CPP_EOF: /* Should not happen ... */
+ case CPP_VSPACE:
op.op = 0;
return op;
- case CPP_VSPACE:
case CPP_POP:
if (CPP_BUFFER (pfile)->fname != NULL)
{
op.op = 0;
return op;
}
+ cpp_pop_buffer (pfile);
goto retry;
case CPP_HSPACE: case CPP_COMMENT:
goto retry;
@@ -362,7 +390,7 @@ cpp_reader *pfile;
{
if (c == '\\')
{
- c = cpp_parse_escape (pfile, &ptr);
+ c = cpp_parse_escape (pfile, (char **) &ptr);
if (width < HOST_BITS_PER_INT
&& (unsigned) c >= (1 << width))
cpp_pedwarn (pfile,
@@ -401,7 +429,7 @@ cpp_reader *pfile;
{
int num_bits = num_chars * width;
- if (cpp_lookup (pfile, "__CHAR_UNSIGNED__",
+ if (cpp_lookup (pfile, (U_CHAR *)"__CHAR_UNSIGNED__",
sizeof ("__CHAR_UNSIGNED__")-1, -1)
|| ((result >> (num_bits - 1)) & 1) == 0)
op.value
@@ -425,7 +453,7 @@ cpp_reader *pfile;
if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
result = wc;
else
- cpp_warning (pfile,"Ignoring invalid multibyte character");
+ cpp_pedwarn (pfile,"Ignoring invalid multibyte character");
}
#endif
op.value = result;
@@ -439,6 +467,9 @@ cpp_reader *pfile;
return op;
case CPP_NAME:
+ if (CPP_WARN_UNDEF (pfile) && !skip_evaluation)
+ cpp_warning (pfile, "`%.*s' is not defined",
+ (int) (tok_end - tok_start), tok_start);
return parse_number (pfile, "0", 0);
case CPP_OTHER:
@@ -538,7 +569,7 @@ cpp_parse_escape (pfile, string_ptr)
if ((i & ~((1 << MAX_CHAR_TYPE_SIZE) - 1)) != 0)
{
i &= (1 << MAX_CHAR_TYPE_SIZE) - 1;
- cpp_warning (pfile,
+ cpp_pedwarn (pfile,
"octal character constant does not fit in a byte");
}
return i;
@@ -569,7 +600,7 @@ cpp_parse_escape (pfile, string_ptr)
if (overflow | (i & ~((1 << BITS_PER_UNIT) - 1)))
{
i &= (1 << BITS_PER_UNIT) - 1;
- cpp_warning (pfile,
+ cpp_pedwarn (pfile,
"hex character constant does not fit in a byte");
}
return i;
@@ -626,7 +657,7 @@ right_shift (pfile, a, unsignedp, b)
return a >> b;
}
-/* These priorities are all even, so we can handle associatively. */
+/* These priorities are all even, so we can handle associatively. */
#define PAREN_INNER_PRIO 0
#define COMMA_PRIO 4
#define COND_PRIO (COMMA_PRIO+2)
@@ -670,6 +701,7 @@ cpp_parse_expr (pfile)
struct operation *limit = stack + INIT_STACK_SIZE;
register struct operation *top = stack;
int lprio, rprio;
+ int skip_evaluation = 0;
top->rprio = 0;
top->flags = 0;
@@ -679,17 +711,16 @@ cpp_parse_expr (pfile)
char flags = 0;
/* Read a token */
- op = cpp_lex (pfile);
+ op = cpp_lex (pfile, skip_evaluation);
/* See if the token is an operand, in which case go to set_value.
If the token is an operator, figure out its left and right
- priorities, and then goto maybe_reduce. */
+ priorities, and then goto maybe_reduce. */
switch (op.op)
{
case NAME:
- top->value = 0, top->unsignedp = 0;
- goto set_value;
+ abort ();
case INT: case CHAR:
top->value = op.value;
top->unsignedp = op.unsignedp;
@@ -740,7 +771,7 @@ cpp_parse_expr (pfile)
}
set_value:
- /* Push a value onto the stack. */
+ /* Push a value onto the stack. */
if (top->flags & HAVE_VALUE)
{
cpp_error (pfile, "syntax error in #if");
@@ -750,7 +781,7 @@ cpp_parse_expr (pfile)
continue;
maybe_reduce:
- /* Push an operator, and check if we can reduce now. */
+ /* Push an operator, and check if we can reduce now. */
while (top->rprio > lprio)
{
long v1 = top[-1].value, v2 = top[0].value;
@@ -782,7 +813,7 @@ cpp_parse_expr (pfile)
{
top->value = v1 + v2;
top->unsignedp = unsigned1 || unsigned2;
- if (! top->unsignedp
+ if (! top->unsignedp && ! skip_evaluation
&& ! possible_sum_sign (v1, v2, top->value))
integer_overflow (pfile);
}
@@ -791,7 +822,7 @@ cpp_parse_expr (pfile)
if (!(top->flags & HAVE_VALUE))
{ /* Unary '-' */
top->value = - v2;
- if ((top->value & v2) < 0 && ! unsigned2)
+ if (!skip_evaluation && (top->value & v2) < 0 && !unsigned2)
integer_overflow (pfile);
top->unsignedp = unsigned2;
top->flags |= HAVE_VALUE;
@@ -800,7 +831,7 @@ cpp_parse_expr (pfile)
{ /* Binary '-' */
top->value = v1 - v2;
top->unsignedp = unsigned1 || unsigned2;
- if (! top->unsignedp
+ if (! top->unsignedp && ! skip_evaluation
&& ! possible_sum_sign (top->value, v2, v1))
integer_overflow (pfile);
}
@@ -809,7 +840,7 @@ cpp_parse_expr (pfile)
top->unsignedp = unsigned1 || unsigned2;
if (top->unsignedp)
top->value = (unsigned long) v1 * v2;
- else
+ else if (!skip_evaluation)
{
top->value = v1 * v2;
if (v1
@@ -819,6 +850,8 @@ cpp_parse_expr (pfile)
}
break;
case '/':
+ if (skip_evaluation)
+ break;
if (v2 == 0)
{
cpp_error (pfile, "division by zero in #if");
@@ -835,6 +868,8 @@ cpp_parse_expr (pfile)
}
break;
case '%':
+ if (skip_evaluation)
+ break;
if (v2 == 0)
{
cpp_error (pfile, "division by zero in #if");
@@ -879,6 +914,8 @@ cpp_parse_expr (pfile)
top->unsignedp = 0;
break;
case LSH:
+ if (skip_evaluation)
+ break;
top->unsignedp = unsigned1;
if (v2 < 0 && ! unsigned2)
top->value = right_shift (pfile, v1, unsigned1, -v2);
@@ -886,6 +923,8 @@ cpp_parse_expr (pfile)
top->value = left_shift (pfile, v1, unsigned1, v2);
break;
case RSH:
+ if (skip_evaluation)
+ break;
top->unsignedp = unsigned1;
if (v2 < 0 && ! unsigned2)
top->value = left_shift (pfile, v1, unsigned1, -v2);
@@ -899,9 +938,13 @@ cpp_parse_expr (pfile)
case '^': LOGICAL(^); break;
case '|': LOGICAL(|); break;
case ANDAND:
- top->value = v1 && v2; top->unsignedp = 0; break;
+ top->value = v1 && v2; top->unsignedp = 0;
+ if (!v1) skip_evaluation--;
+ break;
case OROR:
- top->value = v1 || v2; top->unsignedp = 0; break;
+ top->value = v1 || v2; top->unsignedp = 0;
+ if (v1) skip_evaluation--;
+ break;
case ',':
if (CPP_PEDANTIC (pfile))
cpp_pedwarn (pfile, "comma operator in operand of `#if'");
@@ -928,6 +971,7 @@ cpp_parse_expr (pfile)
else
{
top--;
+ if (top->value) skip_evaluation--;
top->value = top->value ? v1 : v2;
top->unsignedp = unsigned1 || unsigned2;
}
@@ -967,27 +1011,40 @@ cpp_parse_expr (pfile)
}
top++;
- /* Check for and handle stack overflow. */
+ /* Check for and handle stack overflow. */
if (top == limit)
{
struct operation *new_stack;
- int old_size = (char*)limit - (char*)stack;
+ int old_size = (char *) limit - (char *) stack;
int new_size = 2 * old_size;
if (stack != init_stack)
- new_stack = (struct operation*) xrealloc (stack, new_size);
+ new_stack = (struct operation *) xrealloc (stack, new_size);
else
{
- new_stack = (struct operation*) xmalloc (new_size);
+ new_stack = (struct operation *) xmalloc (new_size);
bcopy ((char *) stack, (char *) new_stack, old_size);
}
stack = new_stack;
- top = (struct operation*)((char*) new_stack + old_size);
- limit = (struct operation*)((char*) new_stack + new_size);
+ top = (struct operation *) ((char *) new_stack + old_size);
+ limit = (struct operation *) ((char *) new_stack + new_size);
}
top->flags = flags;
top->rprio = rprio;
top->op = op.op;
+ if ((op.op == OROR && top[-1].value)
+ || (op.op == ANDAND && !top[-1].value)
+ || (op.op == '?' && !top[-1].value))
+ {
+ skip_evaluation++;
+ }
+ else if (op.op == ':')
+ {
+ if (top[-2].value) /* Was condition true? */
+ skip_evaluation++;
+ else
+ skip_evaluation--;
+ }
}
syntax_error:
if (stack != init_stack)
diff --git a/gnu/usr.bin/gcc/cpphash.c b/gnu/usr.bin/gcc/cpphash.c
index bd06e95387f..737ac39ef11 100644
--- a/gnu/usr.bin/gcc/cpphash.c
+++ b/gnu/usr.bin/gcc/cpphash.c
@@ -1,5 +1,5 @@
/* Part of CPP library. (Macro hash table support.)
- Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1986, 87, 89, 92-95, 1996 Free Software Foundation, Inc.
Written by Per Bothner, 1994.
Based on CCCP program by by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
@@ -24,24 +24,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "cpplib.h"
#include "cpphash.h"
+#include "gansidecl.h"
extern char *xmalloc PARAMS ((unsigned));
-/* Define a generic NULL if one hasn't already been defined. */
+/* Return hash function on name. must be compatible with the one
+ computed a step at a time, elsewhere */
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef __STDC__
-#define const
-#define volatile
-#endif
-
-/*
- * return hash function on name. must be compatible with the one
- * computed a step at a time, elsewhere
- */
int
hashf (name, len, hashsize)
register const U_CHAR *name;
@@ -56,19 +45,18 @@ hashf (name, len, hashsize)
return MAKE_POS (r) % hashsize;
}
-/*
- * 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. */
+
HASHNODE *
cpp_lookup (pfile, name, len, hash)
- struct parse_file *pfile;
+ cpp_reader *pfile;
const U_CHAR *name;
int len;
int hash;
@@ -91,7 +79,7 @@ cpp_lookup (pfile, name, len, hash)
return bucket;
bucket = bucket->next;
}
- return (HASHNODE*) 0;
+ return (HASHNODE *) 0;
}
/*
@@ -119,7 +107,7 @@ delete_macro (hp)
hp->next->prev = hp->prev;
/* make sure that the bucket chain header that
- the deleted guy was on points to the right thing afterwards. */
+ the deleted guy was on points to the right thing afterwards. */
if (hp == *hp->bucket_hdr)
*hp->bucket_hdr = hp->next;
@@ -140,20 +128,20 @@ delete_macro (hp)
free (hp);
}
-/*
- * install a name in the main hash table, even if it is already there.
- * name stops with first non alphanumeric, except leading '#'.
- * caller must check against redefinition if that is desired.
- * delete_macro () removes things installed by install () in fifo order.
- * this is important because of the `defined' special symbol used
- * in #if, and also if pushdef/popdef directives are ever implemented.
- *
- * 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 main hash table, even if it is already there.
+ name stops with first non alphanumeric, except leading '#'.
+ caller must check against redefinition if that is desired.
+ delete_macro () removes things installed by install () in fifo order.
+ this is important because of the `defined' special symbol used
+ in #if, and also if pushdef/popdef directives are ever implemented.
+
+ 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. */
+
HASHNODE *
install (name, len, type, ivalue, value, hash)
U_CHAR *name;
diff --git a/gnu/usr.bin/gcc/cpphash.h b/gnu/usr.bin/gcc/cpphash.h
index 914a12f5b01..ed06c186aed 100644
--- a/gnu/usr.bin/gcc/cpphash.h
+++ b/gnu/usr.bin/gcc/cpphash.h
@@ -35,4 +35,4 @@ static HASHNODE *hashtab[HASHSIZE];
#define HASHSTEP(old, c) ((old << 2) + c)
#define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
-extern HASHNODE* install PARAMS ((U_CHAR*,int,enum node_type, int,char*,int));
+extern HASHNODE *install PARAMS ((U_CHAR *,int,enum node_type, int,char *,int));
diff --git a/gnu/usr.bin/gcc/cpplib.c b/gnu/usr.bin/gcc/cpplib.c
index 8e91a099d81..9cfd3ac6e46 100644
--- a/gnu/usr.bin/gcc/cpplib.c
+++ b/gnu/usr.bin/gcc/cpplib.c
@@ -1,7 +1,7 @@
/* CPP Library.
- Copyright (C) 1986, 87, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
- Written by Per Bothner, 1994-95.
- Based on CCCP program by by Paul Rubin, June 1986
+ Copyright (C) 1986, 87, 89, 92-6, 1997 Free Software Foundation, Inc.
+ Contributed by Per Bothner, 1994-95.
+ Based on CCCP program by Paul Rubin, June 1986
Adapted to ANSI C, Richard Stallman, Jan 1987
This program is free software; you can redistribute it and/or modify it
@@ -16,80 +16,81 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding! */
-
-#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
+Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
#include "config.h"
-#endif /* not EMACS */
-#ifndef STANDARD_INCLUDE_DIR
-#define STANDARD_INCLUDE_DIR "/usr/include"
+#ifndef STDC_VALUE
+#define STDC_VALUE 1
#endif
-#ifndef LOCAL_INCLUDE_DIR
-#define LOCAL_INCLUDE_DIR "/usr/local/include"
+#include <ctype.h>
+#include <stdio.h>
+#include <signal.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
#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
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
#else
-#define PTR_INT_TYPE long
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+#endif
#endif
-#endif /* 0 */
-#include "cpplib.h"
-#include "cpphash.h"
+#ifdef HAVE_SYS_TIMES_H
+#include <sys/times.h>
+#endif
-#ifndef STDC_VALUE
-#define STDC_VALUE 1
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
#endif
-/* By default, colon separates directories in a path. */
-#ifndef PATH_SEPARATOR
-#define PATH_SEPARATOR ':'
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
#endif
-#include <ctype.h>
-#include <stdio.h>
-#include <signal.h>
-#ifdef __STDC__
-#include <stdlib.h>
+#if HAVE_LIMITS_H
+# include <limits.h>
#endif
-#ifndef VMS
-#ifndef USG
-#include <sys/time.h> /* for __DATE__ and __TIME__ */
-#include <sys/resource.h>
-#else
-#include <sys/param.h> /* CYGNUS LOCAL: shebs -noquiet */
-#include <sys/times.h>
-#include <time.h>
-#include <fcntl.h>
-#endif /* USG */
-#endif /* not VMS */
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+#ifdef HAVE_STRING_H
+# include <string.h>
+# else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#endif
+
+/* This defines "errno" properly for VMS, and gives us EACCES. */
#include <errno.h>
+#include "cpplib.h"
+#include "cpphash.h"
+#include "gansidecl.h"
+
+#ifdef NEED_DECLARATION_INDEX
extern char *index ();
+#endif
+
+#ifdef NEED_DECLARATION_RINDEX
extern char *rindex ();
+#endif
+
+#ifdef NEED_DECLARATION_GETENV
+extern char *getenv ();
+#endif
+
+extern char *update_path ();
#ifndef O_RDONLY
#define O_RDONLY 0
@@ -100,18 +101,26 @@ extern char *rindex ();
#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 <inttypes.h>
+# define HOST_WIDE_INT intmax_t
+# else
+# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT \
+ && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
+# define HOST_WIDE_INT int
+# else
+# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG \
+ || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
+# define HOST_WIDE_INT long
+# else
+# define HOST_WIDE_INT long long
+# endif
+# endif
+# endif
#endif
#ifndef S_ISREG
@@ -122,24 +131,14 @@ extern char *rindex ();
#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
+/* By default, colon separates directories in a path. */
+#ifndef PATH_SEPARATOR
+#define PATH_SEPARATOR ':'
#endif
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
+#ifndef STANDARD_INCLUDE_DIR
+#define STANDARD_INCLUDE_DIR "/usr/include"
#endif
-
#ifndef INCLUDE_LEN_FUDGE
#define INCLUDE_LEN_FUDGE 0
#endif
@@ -205,7 +204,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 */
@@ -234,7 +233,7 @@ struct assertion_hashnode {
#define NEWLINE_FIX \
do {while (PEEKC() == '\\' && PEEKN(1) == '\n') FORWARD(2); } while(0)
-/* Same, but assume we've already read the potential '\\' into C. */
+/* Same, but assume we've already read the potential '\\' into C. */
#define NEWLINE_FIX1(C) do { \
while ((C) == '\\' && PEEKC() == '\n') { FORWARD(1); (C) = GETC(); }\
} while(0)
@@ -247,49 +246,49 @@ struct cpp_pending {
/* Forward declarations. */
-extern char *xmalloc ();
+char *xmalloc ();
+void cpp_fatal ();
+void cpp_file_line_for_message PARAMS ((cpp_reader *, char *, int, int));
+void cpp_hash_cleanup PARAMS ((cpp_reader *));
+void cpp_message ();
+void cpp_print_containing_files PARAMS ((cpp_reader *));
static void add_import ();
static void append_include_chain ();
-static void make_undef ();
static void make_assertion ();
static void path_include ();
static void initialize_builtins ();
static void initialize_char_syntax ();
-static void dump_arg_n ();
-static void dump_defn_1 ();
extern void delete_macro ();
+#if 0
static void trigraph_pcp ();
+#endif
static int finclude ();
static void validate_else ();
static int comp_def_part ();
+#ifdef abort
extern void fancy_abort ();
-static void pipe_closed ();
-static void print_containing_files ();
+#endif
static int lookup_import ();
static int redundant_include_p ();
static is_system_include ();
static struct file_name_map *read_name_map ();
static char *read_filename_string ();
static int open_include_file ();
-static int check_preconditions ();
-static void pcfinclude ();
-static void pcstring_used ();
static int check_macro_name ();
static int compare_defs ();
static int compare_token_lists ();
static HOST_WIDE_INT eval_if_expression ();
static int change_newlines ();
extern int hashf ();
-static int file_size_and_mode ();
static struct arglist *read_token_list ();
static void free_token_list ();
static int safe_read ();
static void push_macro_expansion PARAMS ((cpp_reader *,
- U_CHAR*, int, HASHNODE*));
-static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending*));
+ U_CHAR *, int, HASHNODE *));
+static struct cpp_pending *nreverse_pending PARAMS ((struct cpp_pending *));
extern char *xrealloc ();
-extern char *xcalloc ();
+static char *xcalloc ();
static char *savestring ();
static void conditional_skip ();
@@ -300,9 +299,8 @@ enum file_change_code {same_file, enter_file, leave_file};
/* External declarations. */
-extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader*));
+extern HOST_WIDE_INT cpp_parse_expr PARAMS ((cpp_reader *));
-extern char *getenv ();
extern FILE *fdopen ();
extern char *version_string;
extern struct tm *localtime ();
@@ -346,15 +344,16 @@ struct file_name_list
};
/* If a buffer's dir field is SELF_DIR_DUMMY, it means the file was found
- via the same directory as the file that #included it. */
-#define SELF_DIR_DUMMY ((struct file_name_list*)(~0))
+ via the same directory as the file that #included it. */
+#define SELF_DIR_DUMMY ((struct file_name_list *) (~0))
-/* #include "file" looks in source file dir, then stack. */
-/* #include <file> just looks in the stack. */
-/* -I directories are added to the end, then the defaults are added. */
+/* #include "file" looks in source file dir, then stack. */
+/* #include <file> just looks in the stack. */
+/* -I directories are added to the end, then the defaults are added. */
/* The */
static struct default_include {
char *fname; /* The name of the directory. */
+ char *component; /* The component containing the directory */
int cplusplus; /* Only look here if we're compiling C++. */
int cxx_aware; /* Includes in this directory don't need to
be wrapped in extern "C" when compiling
@@ -365,33 +364,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, 1 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
#else /* not CROSS_COMPILE */
+#ifdef LOCAL_INCLUDE_DIR
/* This should be /usr/local/include and should come before
the fixincludes-fixed header files. */
- { LOCAL_INCLUDE_DIR, 0, 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, 1 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 1 },
+#endif
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
- { GCC_INCLUDE_DIR, 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
+#ifndef STANDARD_INCLUDE_COMPONENT
+#define STANDARD_INCLUDE_COMPONENT 0
#endif
- { STANDARD_INCLUDE_DIR, 0, 0 },
+ { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 },
#endif /* not CROSS_COMPILE */
- { 0, 0, 0 }
+ { 0, 0, 0, 0 }
};
#endif /* no INCLUDE_DEFAULTS */
@@ -401,17 +410,17 @@ struct directive {
int length; /* Length of name */
int (*func)(); /* Function to handle directive */
char *name; /* Name of directive */
- enum node_type type; /* Code which describes which directive. */
- char command_reads_line; /* One if rest of line is read by func. */
- 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. */
+ char command_reads_line; /* One if rest of line is read by func. */
};
+#define IS_INCLUDE_DIRECTIVE_TYPE(t) (T_INCLUDE <= (t) && (t) <= T_IMPORT)
+
/* Here is the actual list of #-directives, most-often-used first.
The initialize_builtins function assumes #define is the very first. */
static struct directive directive_table[] = {
- { 6, do_define, "define", T_DEFINE, 0, 1},
+ { 6, do_define, "define", T_DEFINE},
{ 5, do_xifdef, "ifdef", T_IFDEF, 1},
{ 6, do_xifdef, "ifndef", T_IFNDEF, 1},
{ 7, do_include, "include", T_INCLUDE, 1},
@@ -424,9 +433,9 @@ static struct directive directive_table[] = {
{ 5, do_undef, "undef", T_UNDEF},
{ 5, do_error, "error", T_ERROR},
{ 7, do_warning, "warning", T_WARNING},
- { 6, do_pragma, "pragma", T_PRAGMA, 0, 0, 1},
+ { 6, do_pragma, "pragma", T_PRAGMA},
{ 4, do_line, "line", T_LINE, 1},
- { 5, do_ident, "ident", T_IDENT, 1, 0, 1},
+ { 5, do_ident, "ident", T_IDENT, 1},
#ifdef SCCS_DIRECTIVE
{ 4, do_sccs, "sccs", T_SCCS},
#endif
@@ -435,9 +444,9 @@ static struct directive directive_table[] = {
{ -1, 0, "", T_UNUSED},
};
-/* 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];
@@ -488,7 +497,8 @@ initialize_char_syntax (opts)
/* Place into PFILE a quoted string representing the string SRC.
- Caller must reserve enough space in pfile->token_buffer. */
+ Caller must reserve enough space in pfile->token_buffer. */
+
static void
quote_string (pfile, src)
cpp_reader *pfile;
@@ -505,7 +515,7 @@ quote_string (pfile, src)
CPP_PUTC_Q (pfile, c);
else
{
- sprintf (CPP_PWRITTEN (pfile), "\\%03o", c);
+ sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o", c);
CPP_ADJUST_WRITTEN (pfile, 4);
}
break;
@@ -523,7 +533,7 @@ quote_string (pfile, src)
}
}
-/* Make sure PFILE->token_buffer will hold at least N more chars. */
+/* Re-allocates PFILE->token_buffer so it will hold at least N more chars. */
void
cpp_grow_buffer (pfile, n)
@@ -532,7 +542,7 @@ cpp_grow_buffer (pfile, n)
{
long old_written = CPP_WRITTEN (pfile);
pfile->token_buffer_size = n + 2 * pfile->token_buffer_size;
- pfile->token_buffer = (U_CHAR*)
+ pfile->token_buffer = (U_CHAR *)
xrealloc(pfile->token_buffer, pfile->token_buffer_size);
CPP_SET_WRITTEN (pfile, old_written);
}
@@ -605,7 +615,6 @@ make_assertion (pfile, option, str)
char *option;
U_CHAR *str;
{
- cpp_buffer *ip;
struct directive *kt;
U_CHAR *buf, *p, *q;
@@ -637,9 +646,11 @@ make_assertion (pfile, option, str)
return;
}
- ip = cpp_push_buffer (pfile, buf, strlen (buf));
- do_assert (pfile, NULL, NULL, NULL);
- cpp_pop_buffer (pfile);
+ if (cpp_push_buffer (pfile, buf, strlen (buf)) != NULL)
+ {
+ do_assert (pfile, NULL, NULL, NULL);
+ cpp_pop_buffer (pfile);
+ }
}
/* Append a chain of `struct file_name_list's
@@ -771,8 +782,8 @@ path_include (pfile, path)
}
void
-init_parse_options (opts)
- struct cpp_options *opts;
+cpp_options_init (opts)
+ cpp_options *opts;
{
bzero ((char *) opts, sizeof *opts);
opts->in_fname = NULL;
@@ -781,7 +792,6 @@ init_parse_options (opts)
/* Initialize is_idchar to allow $. */
opts->dollars_in_ident = 1;
initialize_char_syntax (opts);
- opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 0;
opts->no_line_commands = 0;
opts->no_trigraphs = 1;
@@ -789,6 +799,7 @@ init_parse_options (opts)
opts->print_include_names = 0;
opts->dump_macros = dump_none;
opts->no_output = 0;
+ opts->remap = 0;
opts->cplusplus = 0;
opts->cplusplus_comments = 0;
@@ -824,7 +835,7 @@ macro_cleanup (pbuf, pfile)
cpp_buffer *pbuf;
cpp_reader *pfile;
{
- HASHNODE *macro = (HASHNODE*)pbuf->data;
+ HASHNODE *macro = (HASHNODE *) pbuf->data;
if (macro->type == T_DISABLED)
macro->type = T_MACRO;
if (macro->type != T_MACRO || pbuf->buf != macro->value.defn->expansion)
@@ -845,52 +856,18 @@ file_cleanup (pbuf, pfile)
return 0;
}
-static void
-newline_fix (pfile)
- cpp_reader *pfile;
-{
-#if 1
- NEWLINE_FIX;
-#else
- register U_CHAR *p = bp;
-
- /* First count the backslash-newline pairs here. */
-
- while (p[0] == '\\' && p[1] == '\n')
- p += 2;
-
- /* What follows the backslash-newlines is not embarrassing. */
-
- if (*p != '/' && *p != '*')
- return;
-
- /* Copy all potentially embarrassing characters
- that follow the backslash-newline pairs
- down to where the pairs originally started. */
-
- while (*p == '*' || *p == '/')
- *bp++ = *p++;
-
- /* Now write the same number of pairs after the embarrassing chars. */
- while (bp < p) {
- *bp++ = '\\';
- *bp++ = '\n';
- }
-#endif
-}
-
/* Assuming we have read '/'.
If this is the start of a comment (followed by '*' or '/'),
skip to the end of the comment, and return ' '.
Return EOF if we reached the end of file before the end of the comment.
- If not the start of a comment, return '/'. */
+ If not the start of a comment, return '/'. */
static int
skip_comment (pfile, linep)
cpp_reader *pfile;
long *linep;
{
- int c;
+ int c = 0;
while (PEEKC() == '\\' && PEEKN(1) == '\n')
{
if (linep)
@@ -925,7 +902,7 @@ skip_comment (pfile, linep)
{
c = GETC ();
if (c == EOF)
- return ' '; /* Allow // to be terminated by EOF. */
+ return ' '; /* Allow // to be terminated by EOF. */
while (c == '\\' && PEEKC() == '\n')
{
FORWARD(1);
@@ -935,7 +912,7 @@ skip_comment (pfile, linep)
}
if (c == '\n')
{
- /* Don't consider final '\n' to be part of comment. */
+ /* Don't consider final '\n' to be part of comment. */
FORWARD(-1);
return ' ';
}
@@ -946,6 +923,7 @@ skip_comment (pfile, linep)
}
/* Skip whitespace \-newline and comments. Does not macro-expand. */
+
void
cpp_skip_hspace (pfile)
cpp_reader *pfile;
@@ -982,9 +960,9 @@ cpp_skip_hspace (pfile)
}
/* Read the rest of the current line.
- The line is appended to PFILE's output buffer. */
+ The line is appended to PFILE's output buffer. */
-void
+static void
copy_rest_of_line (pfile)
cpp_reader *pfile;
{
@@ -1009,7 +987,7 @@ copy_rest_of_line (pfile)
break;
case '/':
nextc = PEEKC();
- if (nextc == '*' || (opts->cplusplus_comments && nextc == '*'))
+ if (nextc == '*' || (opts->cplusplus_comments && nextc == '/'))
goto scan_directive_token;
break;
case '\f':
@@ -1067,7 +1045,7 @@ handle_directive (pfile)
goto done_a_directive;
}
- /* Now find the directive name. */
+ /* Now find the directive name. */
CPP_PUTC (pfile, '#');
parse_name (pfile, GETC());
ident = pfile->token_buffer + old_written + 1;
@@ -1113,11 +1091,13 @@ handle_directive (pfile)
break;
}
- if (! kt->command_reads_line)
+ if (kt->command_reads_line)
+ after_ident = 0;
+ else
{
/* Nonzero means do not delete comments within the directive.
#define needs this when -traditional. */
- int comments = CPP_TRADITIONAL (pfile) && kt->traditional_comments;
+ int comments = CPP_TRADITIONAL (pfile) && kt->type == T_DEFINE;
int save_put_out_comments = CPP_OPTIONS (pfile)->put_out_comments;
CPP_OPTIONS (pfile)->put_out_comments = comments;
after_ident = CPP_WRITTEN (pfile);
@@ -1125,37 +1105,39 @@ handle_directive (pfile)
CPP_OPTIONS (pfile)->put_out_comments = save_put_out_comments;
}
- /* For #pragma and #define, we may want to pass through the directive.
+ /* We may want to pass through #define, #pragma, and #include.
Other directives may create output, but we don't want the directive
- itself out, so we pop it now. For example #include may write a #line
- command (see comment in do_include), and conditionals may emit
+ itself out, so we pop it now. For example conditionals may emit
#failed ... #endfailed stuff. But note that popping the buffer
means the parameters to kt->func may point after pfile->limit
so these parameters are invalid as soon as something gets appended
to the token_buffer. */
line_end = CPP_PWRITTEN (pfile);
- if (!kt->pass_thru && kt->type != T_DEFINE)
+ if (! (kt->type == T_DEFINE
+ || kt->type == T_PRAGMA
+ || (IS_INCLUDE_DIRECTIVE_TYPE (kt->type)
+ && CPP_OPTIONS (pfile)->dump_includes)))
CPP_SET_WRITTEN (pfile, old_written);
(*kt->func) (pfile, kt, pfile->token_buffer + after_ident, line_end);
- if (kt->pass_thru
- || (kt->type == T_DEFINE
- && CPP_OPTIONS (pfile)->dump_macros == dump_definitions))
- {
- /* Just leave the entire #define in the output stack. */
- }
- else if (kt->type == T_DEFINE
- && CPP_OPTIONS (pfile)->dump_macros == dump_names)
+
+ if (kt->type == T_DEFINE)
{
- U_CHAR *p = pfile->token_buffer + old_written + 7; /* Skip "#define". */
- SKIP_WHITE_SPACE (p);
- while (is_idchar[*p]) p++;
- pfile->limit = p;
- CPP_PUTC (pfile, '\n');
+ if (CPP_OPTIONS (pfile)->dump_macros == dump_names)
+ {
+ /* Skip "#define". */
+ U_CHAR *p = pfile->token_buffer + old_written + 7;
+
+ SKIP_WHITE_SPACE (p);
+ while (is_idchar[*p]) p++;
+ pfile->limit = p;
+ CPP_PUTC (pfile, '\n');
+ }
+ else if (CPP_OPTIONS (pfile)->dump_macros != dump_definitions)
+ CPP_SET_WRITTEN (pfile, old_written);
}
- else if (kt->type == T_DEFINE)
- CPP_SET_WRITTEN (pfile, old_written);
+
done_a_directive:
return 1;
@@ -1199,7 +1181,7 @@ pass_thru_directive (buf, limit, pfile, 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;
@@ -1241,7 +1223,7 @@ collect_expansion (pfile, buf, limit, 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 (limit < buf)
abort ();
@@ -1257,7 +1239,7 @@ collect_expansion (pfile, buf, limit, nargs, arglist)
leading and trailing newline-marker and final null. */
maxsize = (sizeof (DEFINITION)
+ (limit - p) + 5);
- /* Occurrences of '@' get doubled, so allocate extra space for them. */
+ /* Occurrences of '@' get doubled, so allocate extra space for them. */
while (p < limit)
if (*p++ == '@')
maxsize++;
@@ -1270,7 +1252,7 @@ collect_expansion (pfile, buf, limit, nargs, arglist)
p = buf;
/* Add one initial space escape-marker to prevent accidental
- token-pasting (often removed by macroexpand). */
+ token-pasting (often removed by macroexpand). */
*exp_p++ = '@';
*exp_p++ = ' ';
@@ -1307,7 +1289,7 @@ collect_expansion (pfile, buf, limit, nargs, arglist)
case '@':
/* An '@' in a string or character constant stands for itself,
- and does not need to be escaped. */
+ and does not need to be escaped. */
if (!expected_delimiter)
*exp_p++ = c;
break;
@@ -1334,7 +1316,8 @@ collect_expansion (pfile, buf, limit, nargs, arglist)
Don't leave the # in the expansion. */
exp_p--;
SKIP_WHITE_SPACE (p);
- if (p == limit || ! is_idstart[*p])
+ if (p == limit || ! is_idstart[*p]
+ || (*p == 'L' && p + 1 < limit && (p[1] == '\'' || p[1] == '"')))
cpp_error (pfile,
"`#' operator is not followed by a macro argument name");
else
@@ -1395,7 +1378,8 @@ collect_expansion (pfile, buf, limit, 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) {
@@ -1504,7 +1488,8 @@ static char rest_extension[] = "...";
#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)
/* Create a DEFINITION node from a #define directive. Arguments are
- as for do_define. */
+ as for do_define. */
+
static MACRODEF
create_definition (buf, limit, pfile, predefinition)
U_CHAR *buf, *limit;
@@ -1535,7 +1520,7 @@ create_definition (buf, limit, pfile, predefinition)
/* 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;
@@ -1565,8 +1550,8 @@ create_definition (buf, limit, pfile, predefinition)
while (is_idchar[*bp]) {
bp++;
/* do we have a "special" rest-args extension here? */
- if (limit - bp > REST_EXTENSION_LENGTH &&
- strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
+ if (limit - bp > REST_EXTENSION_LENGTH
+ && strncmp (rest_extension, bp, REST_EXTENSION_LENGTH) == 0) {
rest_args = 1;
temp->rest_args = 1;
break;
@@ -1593,8 +1578,8 @@ create_definition (buf, limit, pfile, predefinition)
struct arglist *otemp;
for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
- if (temp->length == otemp->length &&
- strncmp (temp->name, otemp->name, temp->length) == 0) {
+ if (temp->length == otemp->length
+ && strncmp (temp->name, otemp->name, temp->length) == 0) {
U_CHAR *name;
name = (U_CHAR *) alloca (temp->length + 1);
@@ -1609,7 +1594,7 @@ create_definition (buf, limit, pfile, predefinition)
++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 (pfile, bp, limit, argno, arg_ptrs);
defn->rest_args = rest_args;
@@ -1656,7 +1641,7 @@ create_definition (buf, limit, pfile, predefinition)
}
}
}
- /* now everything from bp before limit is the definition. */
+ /* now everything from bp before limit is the definition. */
defn = collect_expansion (pfile, bp, limit, -1, NULL_PTR);
defn->args.argnames = (U_CHAR *) "";
}
@@ -1692,10 +1677,11 @@ check_macro_name (pfile, 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 == '"')))
cpp_error (pfile, "invalid %s name", usage);
else if (!is_idstart[*symname]) {
- U_CHAR *msg; /* what pain... */
+ U_CHAR *msg; /* what pain... */
msg = (U_CHAR *) alloca (sym_length + 1);
bcopy (symname, msg, sym_length);
msg[sym_length] = 0;
@@ -1707,11 +1693,11 @@ check_macro_name (pfile, 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)
+compare_defs (pfile, d1, d2)
+ cpp_reader *pfile;
DEFINITION *d1, *d2;
{
register struct reflist *a1, *a2;
@@ -1721,7 +1707,8 @@ compare_defs (d1, d2)
if (d1->nargs != d2->nargs)
return 1;
- if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
+ if (CPP_PEDANTIC (pfile)
+ && strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
return 1;
for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
a1 = a1->next, a2 = a2->next) {
@@ -1817,14 +1804,14 @@ do_define (pfile, keyword, buf, limit)
ok = 1;
/* Redefining a macro is ok if the definitions are the same. */
else if (hp->type == T_MACRO)
- ok = ! compare_defs (mdef.defn, hp->value.defn);
+ ok = ! compare_defs (pfile, mdef.defn, hp->value.defn);
/* Redefining a constant is ok with -D. */
else if (hp->type == T_CONST)
ok = ! CPP_OPTIONS (pfile)->done_initializing;
/* Print the warning if it's not ok. */
if (!ok)
{
- U_CHAR *msg; /* what pain... */
+ U_CHAR *msg; /* what pain... */
/* If we are passing through #define and #undef directives, do
that for this re-definition now. */
@@ -1869,7 +1856,7 @@ nope:
if stringified.
`use_count' is the number of times this macro arg is substituted
into the macro. If the actual use count exceeds 10,
- the value stored is 10. */
+ the value stored is 10. */
/* raw and expanded are relative to ARG_BASE */
#define ARG_BASE ((pfile)->token_buffer)
@@ -1883,26 +1870,27 @@ struct argdata {
char use_count;
};
+/* Allocate a new cpp_buffer for PFILE, and push it on the input buffer stack.
+ If BUFFER != NULL, then use the LENGTH characters in BUFFER
+ as the new input buffer.
+ Return the new buffer, or NULL on failure. */
-cpp_buffer*
+cpp_buffer *
cpp_push_buffer (pfile, buffer, length)
cpp_reader *pfile;
U_CHAR *buffer;
long length;
{
-#ifdef STATIC_BUFFERS
register cpp_buffer *buf = CPP_BUFFER (pfile);
if (buf == pfile->buffer_stack)
- fatal ("%s: macro or `#include' recursion too deep", buf->fname);
+ {
+ cpp_fatal (pfile, "%s: macro or `#include' recursion too deep",
+ buf->fname);
+ return NULL;
+ }
buf--;
bzero ((char *) buf, sizeof (cpp_buffer));
CPP_BUFFER (pfile) = buf;
-#else
- register cpp_buffer *buf = (cpp_buffer*) xmalloc (sizeof(cpp_buffer));
- bzero ((char *) buf, sizeof (cpp_buffer));
- CPP_PREV_BUFFER (buf) = CPP_BUFFER (pfile);
- CPP_BUFFER (pfile) = buf;
-#endif
buf->if_stack = pfile->if_stack;
buf->cleanup = null_cleanup;
buf->underflow = null_underflow;
@@ -1912,25 +1900,17 @@ cpp_push_buffer (pfile, buffer, length)
return buf;
}
-cpp_buffer*
+cpp_buffer *
cpp_pop_buffer (pfile)
cpp_reader *pfile;
{
cpp_buffer *buf = CPP_BUFFER (pfile);
-#ifdef STATIC_BUFFERS
(*buf->cleanup) (buf, pfile);
return ++CPP_BUFFER (pfile);
-#else
- cpp_buffer *next_buf = CPP_PREV_BUFFER (buf);
- (*buf->cleanup) (buf, pfile);
- CPP_BUFFER (pfile) = next_buf;
- free (buf);
- return next_buf;
-#endif
}
/* Scan until CPP_BUFFER (PFILE) is exhausted into PFILE->token_buffer.
- Pop the buffer when done. */
+ Pop the buffer when done. */
void
cpp_scan_buffer (pfile)
@@ -1940,7 +1920,7 @@ cpp_scan_buffer (pfile)
for (;;)
{
enum cpp_token token = cpp_get_token (pfile);
- if (token == CPP_EOF) /* Should not happen ... */
+ if (token == CPP_EOF) /* Should not happen ... */
break;
if (token == CPP_POP && CPP_BUFFER (pfile) == buffer)
{
@@ -1989,6 +1969,8 @@ cpp_expand_to_buffer (pfile, buf, length)
buf1[length] = 0;
ip = cpp_push_buffer (pfile, buf1, length);
+ if (ip == NULL)
+ return;
ip->has_escapes = 1;
#if 0
ip->lineno = obuf.lineno = 1;
@@ -2023,7 +2005,7 @@ adjust_position (buf, limit, linep, colp)
}
}
-/* Move line_base forward, updating lineno and colno. */
+/* Move line_base forward, updating lineno and colno. */
static void
update_position (pbuf)
@@ -2062,9 +2044,9 @@ cpp_buf_line_and_col (pbuf, linep, colp)
}
}
-/* Return the cpp_buffer that corresponds to a file (not a macro). */
+/* Return the cpp_buffer that corresponds to a file (not a macro). */
-cpp_buffer*
+cpp_buffer *
cpp_file_buffer (pfile)
cpp_reader *pfile;
{
@@ -2110,11 +2092,15 @@ output_line_command (pfile, conditional, file_change)
long line, col;
cpp_buffer *ip = CPP_BUFFER (pfile);
- if (ip->fname == NULL || CPP_OPTIONS (pfile)->no_output) {
+ if (ip->fname == NULL)
return;
- }
update_position (ip);
+
+ if (CPP_OPTIONS (pfile)->no_line_commands
+ || CPP_OPTIONS (pfile)->no_output)
+ return;
+
line = CPP_BUFFER (pfile)->lineno;
col = CPP_BUFFER (pfile)->colno;
adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
@@ -2157,7 +2143,7 @@ output_line_command (pfile, conditional, file_change)
CPP_PUTS_Q (pfile, sharp_line, sizeof(sharp_line)-1);
}
- sprintf (CPP_PWRITTEN (pfile), "%d ", line);
+ sprintf ((char *) CPP_PWRITTEN (pfile), "%ld ", line);
CPP_ADJUST_WRITTEN (pfile, strlen (CPP_PWRITTEN (pfile)));
quote_string (pfile, ip->nominal_fname);
@@ -2229,7 +2215,7 @@ macarg (pfile, rest_args)
goto found;
break;
found:
- /* Remove ',' or ')' from argument buffer. */
+ /* Remove ',' or ')' from argument buffer. */
CPP_ADJUST_WRITTEN (pfile, -1);
goto done;
default: ;
@@ -2291,7 +2277,7 @@ timestamp (pfile)
cpp_reader *pfile;
{
if (!pfile->timebuf) {
- time_t t = time ((time_t *)0);
+ time_t t = time ((time_t *) 0);
pfile->timebuf = localtime (&t);
}
return pfile->timebuf;
@@ -2329,7 +2315,7 @@ special_symbol (hp, pfile)
for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
{
- if (ip == NULL)
+ if (ip == CPP_NULL_BUFFER (pfile))
{
cpp_error (pfile, "cccp error: not in any file?!");
return; /* the show must go on */
@@ -2346,7 +2332,7 @@ special_symbol (hp, pfile)
char *string;
if (hp->type == T_BASE_FILE)
{
- while (CPP_PREV_BUFFER (ip))
+ while (CPP_PREV_BUFFER (ip) != CPP_NULL_BUFFER (pfile))
ip = CPP_PREV_BUFFER (ip);
}
string = ip->nominal_fname;
@@ -2360,7 +2346,8 @@ special_symbol (hp, pfile)
case T_INCLUDE_LEVEL:
true_indepth = 0;
- for (ip = CPP_BUFFER (pfile); ip != NULL; ip = CPP_PREV_BUFFER (ip))
+ ip = CPP_BUFFER (pfile);
+ for (; ip != CPP_NULL_BUFFER (pfile); ip = CPP_PREV_BUFFER (ip))
if (ip->fname != NULL)
true_indepth++;
@@ -2400,6 +2387,12 @@ special_symbol (hp, pfile)
case T_CONST:
buf = (char *) alloca (4 * sizeof (int));
sprintf (buf, "%d", hp->value.ival);
+#ifdef STDC_0_IN_SYSTEM_HEADERS
+ if (ip->system_header_p
+ && hp->length == 8 && bcmp (hp->name, "__STDC__", 8) == 0
+ && ! cpp_lookup (pfile, (U_CHAR *) "__STRICT_ANSI__", -1, -1))
+ strcpy (buf, "0");
+#endif
#if 0
if (pcp_inside_if && pcp_outfile)
/* Output a precondition for this macro use */
@@ -2414,7 +2407,7 @@ special_symbol (hp, pfile)
adjust_position (CPP_LINE_BASE (ip), ip->cur, &line, &col);
buf = (char *) alloca (10);
- sprintf (buf, "%d", line);
+ sprintf (buf, "%ld", line);
}
break;
@@ -2443,13 +2436,15 @@ special_symbol (hp, pfile)
if (!is_idstart[*ip->cur])
goto oops;
+ if (ip->cur[0] == 'L' && (ip->cur[1] == '\'' || ip->cur[1] == '"'))
+ goto oops;
if (hp = cpp_lookup (pfile, ip->cur, -1, -1))
{
#if 0
if (pcp_outfile && pcp_inside_if
&& (hp->type == T_CONST
|| (hp->type == T_MACRO && hp->value.defn->predefined)))
- /* Output a precondition for this macro use. */
+ /* Output a precondition for this macro use. */
fprintf (pcp_outfile, "#define %s\n", hp->name);
#endif
buf = " 1 ";
@@ -2494,100 +2489,77 @@ special_symbol (hp, pfile)
return;
}
+/* Write out a #define command for the special named MACRO_NAME
+ to PFILE's token_buffer. */
+
+static void
+dump_special_to_buffer (pfile, macro_name)
+ cpp_reader *pfile;
+ char *macro_name;
+{
+ static char define_directive[] = "#define ";
+ int macro_name_length = strlen (macro_name);
+ output_line_command (pfile, 0, same_file);
+ CPP_RESERVE (pfile, sizeof(define_directive) + macro_name_length);
+ CPP_PUTS_Q (pfile, define_directive, sizeof(define_directive)-1);
+ CPP_PUTS_Q (pfile, macro_name, macro_name_length);
+ CPP_PUTC_Q (pfile, ' ');
+ cpp_expand_to_buffer (pfile, macro_name, macro_name_length);
+ CPP_PUTC (pfile, '\n');
+}
+
/* Initialize the built-in macros. */
static void
initialize_builtins (pfile)
cpp_reader *pfile;
{
- install ("__LINE__", -1, T_SPECLINE, 0, 0, -1);
- install ("__DATE__", -1, T_DATE, 0, 0, -1);
- install ("__FILE__", -1, T_FILE, 0, 0, -1);
- install ("__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
- install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
- install ("__VERSION__", -1, T_VERSION, 0, 0, -1);
+ install ((U_CHAR *)"__LINE__", -1, T_SPECLINE, 0, 0, -1);
+ install ((U_CHAR *)"__DATE__", -1, T_DATE, 0, 0, -1);
+ install ((U_CHAR *)"__FILE__", -1, T_FILE, 0, 0, -1);
+ install ((U_CHAR *)"__BASE_FILE__", -1, T_BASE_FILE, 0, 0, -1);
+ install ((U_CHAR *)"__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, 0, -1);
+ install ((U_CHAR *)"__VERSION__", -1, T_VERSION, 0, 0, -1);
#ifndef NO_BUILTIN_SIZE_TYPE
- install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, 0, -1);
#endif
#ifndef NO_BUILTIN_PTRDIFF_TYPE
- install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, 0, -1);
#endif
- install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
- install ("__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
- install ("__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
- install ("__TIME__", -1, T_TIME, 0, 0, -1);
+ install ((U_CHAR *)"__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__USER_LABEL_PREFIX__", -1, T_USER_LABEL_PREFIX_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__REGISTER_PREFIX__", -1, T_REGISTER_PREFIX_TYPE, 0, 0, -1);
+ install ((U_CHAR *)"__TIME__", -1, T_TIME, 0, 0, -1);
if (!CPP_TRADITIONAL (pfile))
- install ("__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
+ install ((U_CHAR *)"__STDC__", -1, T_CONST, STDC_VALUE, 0, -1);
if (CPP_OPTIONS (pfile)->objc)
- install ("__OBJC__", -1, T_CONST, 1, 0, -1);
+ install ((U_CHAR *)"__OBJC__", -1, T_CONST, 1, 0, -1);
/* This is supplied using a -D by the compiler driver
so that it is present only when truly compiling with GNU C. */
/* install ("__GNUC__", -1, T_CONST, 2, 0, -1); */
if (CPP_OPTIONS (pfile)->debug_output)
{
- char directive[2048];
- register struct directive *dp = &directive_table[0];
- struct tm *timebuf = timestamp (pfile);
- cpp_buffer *pbuffer = CPP_BUFFER (pfile);
-
- while (CPP_PREV_BUFFER (pbuffer))
- pbuffer = CPP_PREV_BUFFER (pbuffer);
- sprintf (directive, " __BASE_FILE__ \"%s\"\n",
- pbuffer->nominal_fname);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
- sprintf (directive, " __VERSION__ \"%s\"\n", version_string);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
+ dump_special_to_buffer (pfile, "__BASE_FILE__");
+ dump_special_to_buffer (pfile, "__VERSION__");
#ifndef NO_BUILTIN_SIZE_TYPE
- sprintf (directive, " __SIZE_TYPE__ %s\n", SIZE_TYPE);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
+ dump_special_to_buffer (pfile, "__SIZE_TYPE__");
#endif
-
#ifndef NO_BUILTIN_PTRDIFF_TYPE
- sprintf (directive, " __PTRDIFF_TYPE__ %s\n", PTRDIFF_TYPE);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
+ dump_special_to_buffer (pfile, "__PTRDIFF_TYPE__");
#endif
-
- sprintf (directive, " __WCHAR_TYPE__ %s\n", CPP_WCHAR_TYPE (pfile));
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
- sprintf (directive, " __DATE__ \"%s %2d %4d\"\n",
- monthnames[timebuf->tm_mon],
- timebuf->tm_mday, timebuf->tm_year + 1900);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
- sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"\n",
- timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)], pfile, dp);
-
+ dump_special_to_buffer (pfile, "__WCHAR_TYPE__");
+ dump_special_to_buffer (pfile, "__DATE__");
+ dump_special_to_buffer (pfile, "__TIME__");
if (!CPP_TRADITIONAL (pfile))
- {
- sprintf (directive, " __STDC__ 1");
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)],
- pfile, dp);
- }
+ dump_special_to_buffer (pfile, "__STDC__");
if (CPP_OPTIONS (pfile)->objc)
- {
- sprintf (directive, " __OBJC__ 1");
- output_line_command (pfile, 0, same_file);
- pass_thru_directive (directive, &directive[strlen (directive)],
- pfile, dp);
- }
+ dump_special_to_buffer (pfile, "__OBJC__");
}
}
/* Return 1 iff a token ending in C1 followed directly by a token C2
- could cause mis-tokenization. */
+ could cause mis-tokenization. */
static int
unsafe_chars (c1, c2)
@@ -2602,27 +2574,27 @@ unsafe_chars (c1, c2)
case '.':
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- case 'e': case 'E':
+ case 'e': case 'E': case 'p': case 'P':
if (c2 == '-' || c2 == '+')
return 1; /* could extend a pre-processing number */
goto letter;
case 'L':
if (c2 == '\'' || c2 == '\"')
- return 1; /* Could turn into L"xxx" or L'xxx'. */
+ return 1; /* Could turn into L"xxx" or L'xxx'. */
goto letter;
letter:
case '_':
case 'a': case 'b': case 'c': case 'd': case 'f':
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+ case 'm': case 'n': case 'o': case 'q': case 'r':
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
case 'y': case 'z':
case 'A': case 'B': case 'C': case 'D': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K':
- case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'M': case 'N': case 'O': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z':
- /* We're in the middle of either a name or a pre-processing number. */
+ /* We're in the middle of either a name or a pre-processing number. */
return (is_idchar[c2] || c2 == '.');
case '<': case '>': case '!': case '%': case '#': case ':':
case '^': case '&': case '|': case '*': case '/': case '=':
@@ -2690,7 +2662,7 @@ macroexpand (pfile, hp)
/* Parse all the macro args that are supplied. I counts them.
The first NARGS args are stored in ARGS.
The rest are discarded. If rest_args is set then we assume
- macarg absorbed the rest of the args. */
+ macarg absorbed the rest of the args. */
i = 0;
rest_args = 0;
rest_args = 0;
@@ -2798,7 +2770,7 @@ macroexpand (pfile, hp)
int c;
/* Initially need_space is -1. Otherwise, 1 means the
previous character was a space, but we suppressed it;
- 0 means the previous character was a non-space. */
+ 0 means the previous character was a non-space. */
int need_space = -1;
i = 0;
arg->stringified = CPP_WRITTEN (pfile);
@@ -2853,7 +2825,7 @@ macroexpand (pfile, hp)
else
{
CPP_RESERVE (pfile, 4);
- sprintf (CPP_PWRITTEN (pfile), "\\%03o",
+ sprintf ((char *)CPP_PWRITTEN (pfile), "\\%03o",
(unsigned int) c);
CPP_ADJUST_WRITTEN (pfile, 4);
}
@@ -2941,6 +2913,11 @@ macroexpand (pfile, hp)
while (p1 != l1 && is_space[*p1]) p1++;
while (p1 != l1 && is_idchar[*p1])
xbuf[totlen++] = *p1++;
+ /* Delete any no-reexpansion marker that follows
+ an identifier at the beginning of the argument
+ if the argument is concatenated with what precedes it. */
+ if (p1[0] == '@' && p1[1] == '-')
+ p1 += 2;
}
if (ap->raw_after)
{
@@ -3008,7 +2985,7 @@ macroexpand (pfile, hp)
}
/* if there is anything left of the definition
- after handling the arg list, copy that in too. */
+ after handling the arg list, copy that in too. */
for (i = offset; i < defn->length; i++)
{
@@ -3032,7 +3009,7 @@ macroexpand (pfile, hp)
push_macro_expansion (pfile, xbuf, xbuf_len, hp);
CPP_BUFFER (pfile)->has_escapes = 1;
- /* Pop the space we've used in the token_buffer for argument expansion. */
+ /* Pop the space we've used in the token_buffer for argument expansion. */
CPP_SET_WRITTEN (pfile, old_written);
/* Recursive macro use sometimes works traditionally.
@@ -3051,6 +3028,8 @@ push_macro_expansion (pfile, xbuf, xbuf_len, hp)
HASHNODE *hp;
{
register cpp_buffer *mbuf = cpp_push_buffer (pfile, xbuf, xbuf_len);
+ if (mbuf == NULL)
+ return;
mbuf->cleanup = macro_cleanup;
mbuf->data = hp;
@@ -3098,7 +3077,7 @@ get_directive_token (pfile)
case CPP_POP:
if (! CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
return token;
- /* ... else fall though ... */
+ /* ... else fall though ... */
case CPP_HSPACE: case CPP_COMMENT:
CPP_SET_WRITTEN (pfile, old_written);
break;
@@ -3114,7 +3093,7 @@ get_directive_token (pfile)
The input is normally in part of the output_buffer following
CPP_WRITTEN, and will get overwritten by output_line_command.
I.e. in input file specification has been popped by handle_directive.
- This is safe. */
+ This is safe. */
static int
do_include (pfile, keyword, unused1, unused2)
@@ -3141,7 +3120,7 @@ do_include (pfile, keyword, unused1, unused2)
int f; /* file number */
int retried = 0; /* Have already tried macro
- expanding the include line*/
+ expanding the include line */
int angle_brackets = 0; /* 0 for "...", 1 for <...> */
int pcf = -1;
char *pcfbuf;
@@ -3149,6 +3128,14 @@ do_include (pfile, keyword, unused1, unused2)
int pcfnum;
f= -1; /* JF we iz paranoid! */
+ if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
+ {
+ if (importing)
+ cpp_pedwarn (pfile, "ANSI C does not allow `#import'");
+ if (skip_dirs)
+ cpp_pedwarn (pfile, "ANSI C does not allow `#include_next'");
+ }
+
if (importing && CPP_OPTIONS (pfile)->warn_import
&& !CPP_OPTIONS (pfile)->inhibit_warnings
&& !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning)
@@ -3183,14 +3170,14 @@ do_include (pfile, keyword, unused1, unused2)
if (CPP_OPTIONS (pfile)->first_bracket_include)
search_start = CPP_OPTIONS (pfile)->first_bracket_include;
}
- /* If -I- was specified, don't search current dir, only spec'd ones. */
+ /* If -I- was specified, don't search current dir, only spec'd ones. */
else if (! CPP_OPTIONS (pfile)->ignore_srcdir)
{
- cpp_buffer *fp;
+ cpp_buffer *fp = CPP_BUFFER (pfile);
/* We have "filename". Figure out directory this source
- file is coming from and put it on the front of the list. */
+ file is coming from and put it on the front of the list. */
- for (fp = CPP_BUFFER (pfile); fp != NULL; fp = CPP_PREV_BUFFER (fp))
+ for ( ; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
{
int n;
char *ep,*nam;
@@ -3269,8 +3256,8 @@ do_include (pfile, keyword, unused1, unused2)
past the dir in which the containing file was found. */
if (skip_dirs)
{
- cpp_buffer *fp;
- for (fp = CPP_BUFFER (pfile); fp != NULL; fp = CPP_PREV_BUFFER (fp))
+ cpp_buffer *fp = CPP_BUFFER (pfile);
+ for (; fp != CPP_NULL_BUFFER (pfile); fp = CPP_PREV_BUFFER (fp))
if (fp->fname != NULL)
{
/* fp->dir is null if the containing file was specified with
@@ -3429,18 +3416,18 @@ do_include (pfile, keyword, unused1, unused2)
/* Check to see if this include file is a once-only include file.
If so, give up. */
- struct file_name_list* ptr;
+ struct file_name_list *ptr;
for (ptr = pfile->dont_repeat_files; ptr; ptr = ptr->next) {
if (!strcmp (ptr->fname, fname)) {
close (f);
- return 0; /* This file was once'd. */
+ return 0; /* This file was once'd. */
}
}
for (ptr = pfile->all_include_files; ptr; ptr = ptr->next) {
if (!strcmp (ptr->fname, fname))
- break; /* This file was included before. */
+ break; /* This file was included before. */
}
if (ptr == 0) {
@@ -3465,7 +3452,7 @@ do_include (pfile, keyword, unused1, unused2)
if (CPP_OPTIONS(pfile)->print_include_names)
{
cpp_buffer *buf = CPP_BUFFER (pfile);
- while ((buf = CPP_PREV_BUFFER (buf)) != NULL)
+ while ((buf = CPP_PREV_BUFFER (buf)) != CPP_NULL_BUFFER (pfile))
putc ('.', stderr);
fprintf (stderr, "%s\n", fname);
}
@@ -3475,7 +3462,7 @@ do_include (pfile, keyword, unused1, unused2)
/* Actually process the file. */
- /* Record file on "seen" list for #import. */
+ /* Record file on "seen" list for #import. */
add_import (pfile, f, fname);
pcftry = (char *) alloca (strlen (fname) + 30);
@@ -3518,7 +3505,8 @@ do_include (pfile, keyword, unused1, unused2)
#endif
/* Actually process the file */
- cpp_push_buffer (pfile, NULL, 0);
+ if (cpp_push_buffer (pfile, NULL, 0) == NULL)
+ return 0;
if (finclude (pfile, f, fname, is_system_include (pfile, fname),
searchptr != dsp ? searchptr : SELF_DIR_DUMMY))
{
@@ -3595,6 +3583,7 @@ is_system_include (pfile, filename)
* If HASH is >= 0, it is the precomputed hash code.
* Otherwise, compute the hash code.
*/
+
static ASSERTION_HASHNODE *
assertion_install (pfile, name, len, hash)
cpp_reader *pfile;
@@ -3672,8 +3661,8 @@ delete_assertion (hp)
tail = next;
}
- /* 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;
@@ -3686,7 +3675,7 @@ delete_assertion (hp)
The value returned in the end of the string written to RESULT,
or NULL on error. */
-static U_CHAR*
+static U_CHAR *
convert_string (pfile, result, in, limit, handle_escapes)
cpp_reader *pfile;
register U_CHAR *result, *in, *limit;
@@ -3755,7 +3744,7 @@ do_line (pfile, keyword)
/* The Newline at the end of this line remains to be processed.
To put the next line at the specified line number,
we must store a line number now that is one less. */
- new_lineno = atoi (pfile->token_buffer + old_written) - 1;
+ new_lineno = atoi ((char *)(pfile->token_buffer + old_written)) - 1;
CPP_SET_WRITTEN (pfile, old_written);
/* NEW_LINENO is one less than the actual line number here. */
@@ -3825,11 +3814,10 @@ do_line (pfile, 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 &&
- strncmp (hp->value.cpval, fname, fname_length) == 0) {
+ if (hp->length == fname_length
+ && strncmp (hp->value.cpval, fname, fname_length) == 0) {
ip->nominal_fname = hp->value.cpval;
break;
}
@@ -3915,7 +3903,7 @@ do_error (pfile, keyword, buf, limit)
U_CHAR *buf, *limit;
{
int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+ U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy (buf, copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
@@ -3936,11 +3924,13 @@ do_warning (pfile, keyword, buf, limit)
U_CHAR *buf, *limit;
{
int length = limit - buf;
- U_CHAR *copy = (U_CHAR *) xmalloc (length + 1);
+ U_CHAR *copy = (U_CHAR *) alloca (length + 1);
bcopy (buf, copy, length);
copy[length] = 0;
SKIP_WHITE_SPACE (copy);
- cpp_warning (pfile, "#warning %s", copy);
+ /* Use `pedwarn' not `warning', because #warning isn't in the C Standard;
+ if -pedantic-errors is given, #warning should cause an error. */
+ cpp_pedwarn (pfile, "#warning %s", copy);
return 0;
}
@@ -3956,7 +3946,7 @@ do_once (pfile)
for (ip = CPP_BUFFER (pfile); ; ip = CPP_PREV_BUFFER (ip))
{
- if (ip == NULL)
+ if (ip == CPP_NULL_BUFFER (pfile))
return 0;
if (ip->fname != NULL)
break;
@@ -3974,7 +3964,7 @@ do_once (pfile)
return 0;
}
-/* #ident has already been copied to the output file, so just ignore it. */
+/* Report program identification. */
static int
do_ident (pfile, keyword, buf, limit)
@@ -3989,7 +3979,7 @@ do_ident (pfile, keyword, buf, limit)
if (CPP_PEDANTIC (pfile) && !CPP_BUFFER (pfile)->system_header_p)
cpp_pedwarn (pfile, "ANSI C does not allow `#ident'");
- /* Leave rest of line to be read by later calls to cpp_get_token. */
+ /* Leave rest of line to be read by later calls to cpp_get_token. */
return 0;
}
@@ -4151,6 +4141,7 @@ do_elif (pfile, keyword, buf, limit)
* 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 (pfile, buf, length)
cpp_reader *pfile;
@@ -4161,7 +4152,7 @@ eval_if_expression (pfile, buf, length)
HOST_WIDE_INT value;
long old_written = CPP_WRITTEN (pfile);
- save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, 0, -1);
+ save_defined = install ((U_CHAR *)"defined", -1, T_SPEC_DEFINED, 0, 0, -1);
pfile->pcp_inside_if = 1;
value = cpp_parse_expr (pfile);
@@ -4187,7 +4178,7 @@ do_xifdef (pfile, keyword, unused1, unused2)
{
int skip;
cpp_buffer *ip = CPP_BUFFER (pfile);
- U_CHAR* ident;
+ U_CHAR *ident;
int ident_length;
enum cpp_token token;
int start_of_file = 0;
@@ -4295,6 +4286,7 @@ conditional_skip (pfile, skip, type, control_macro)
* leaves input ptr at the sharp sign found.
* If ANY is nonzero, return at next directive of any sort.
*/
+
static void
skip_if_group (pfile, any)
cpp_reader *pfile;
@@ -4412,7 +4404,7 @@ skip_if_group (pfile, any)
}
c = GETC ();
}
- /* We're in the middle of a line. Skip the rest of it. */
+ /* We're in the middle of a line. Skip the rest of it. */
for (;;) {
switch (c)
{
@@ -4591,9 +4583,8 @@ validate_else (pfile, directive)
}
/* Get the next token, and add it to the text in pfile->token_buffer.
- Return the kind of token we got. */
+ Return the kind of token we got. */
-
enum cpp_token
cpp_get_token (pfile)
cpp_reader *pfile;
@@ -4621,11 +4612,12 @@ cpp_get_token (pfile)
cpp_buffer *next_buf
= CPP_PREV_BUFFER (CPP_BUFFER (pfile));
CPP_BUFFER (pfile)->seen_eof = 1;
- if (CPP_BUFFER (pfile)->nominal_fname && next_buf != 0)
+ if (CPP_BUFFER (pfile)->nominal_fname
+ && next_buf != CPP_NULL_BUFFER (pfile))
{
/* We're about to return from an #include file.
Emit #line information now (as part of the CPP_POP) result.
- But the #line refers to the file we will pop to. */
+ But the #line refers to the file we will pop to. */
cpp_buffer *cur_buffer = CPP_BUFFER (pfile);
CPP_BUFFER (pfile) = next_buf;
pfile->input_stack_listing_current = 0;
@@ -4660,7 +4652,7 @@ cpp_get_token (pfile)
"unterminated comment");
goto handle_eof;
}
- c = '/'; /* Initial letter of comment. */
+ c = '/'; /* Initial letter of comment. */
return_comment:
/* Comments are equivalent to spaces.
For -traditional, a comment is equivalent to nothing. */
@@ -4685,7 +4677,7 @@ cpp_get_token (pfile)
{
#if 0
/* This may not work if cpp_get_token is called recursively,
- since many places look for horizontal space. */
+ since many places look for horizontal space. */
if (newlines)
{
/* Copy the newlines into the output buffer, in order to
@@ -4725,8 +4717,8 @@ cpp_get_token (pfile)
}
/* OK, now bring us back to the state we were in before we entered
- this branch. We need #line b/c the newline for the pragma
- could fuck things up. */
+ this branch. We need #line because the newline for the pragma
+ could mess things up. */
output_line_command (pfile, 0, same_file);
*(obp++) = ' '; /* just in case, if comments are copied thru */
*(obp++) = '/';
@@ -4824,7 +4816,7 @@ cpp_get_token (pfile)
cc = GETC();
if (cc == '\n')
{
- /* Backslash newline is replaced by nothing at all. */
+ /* Backslash newline is replaced by nothing at all. */
CPP_ADJUST_WRITTEN (pfile, -1);
pfile->lineno++;
}
@@ -4888,7 +4880,7 @@ cpp_get_token (pfile)
/* Chill style comment */
if (opts->put_out_comments)
parse_set_mark (&start_mark, pfile);
- FORWARD(1); /* Skip second '-'. */
+ FORWARD(1); /* Skip second '-'. */
for (;;)
{
c = GETC ();
@@ -4896,7 +4888,7 @@ cpp_get_token (pfile)
break;
if (c == '\n')
{
- /* Don't consider final '\n' to be part of comment. */
+ /* Don't consider final '\n' to be part of comment. */
FORWARD(-1);
break;
}
@@ -5032,7 +5024,9 @@ cpp_get_token (pfile)
if (c == EOF)
break;
if (!is_idchar[c] && c != '.'
- && ((c2 != 'e' && c2 != 'E') || (c != '+' && c != '-')))
+ && ((c2 != 'e' && c2 != 'E'
+ && ((c2 != 'p' && c2 != 'P') || CPP_C89 (pfile)))
+ || (c != '+' && c != '-')))
break;
FORWARD(1);
c2= c;
@@ -5109,7 +5103,7 @@ cpp_get_token (pfile)
if (hp->type == T_DISABLED)
{
if (pfile->output_escapes)
- { /* Return "@-IDENT", followed by '\0'. */
+ { /* Return "@-IDENT", followed by '\0'. */
int i;
CPP_RESERVE (pfile, 3);
ident = pfile->token_buffer + before_name_written;
@@ -5155,7 +5149,7 @@ cpp_get_token (pfile)
if (!is_macro_call)
return CPP_NAME;
}
- /* This is now known to be a macro call. */
+ /* This is now known to be a macro call. */
/* it might not actually be a macro. */
if (hp->type != T_MACRO) {
@@ -5179,7 +5173,7 @@ cpp_get_token (pfile)
/* An extra "@ " is added to the end of a macro expansion
to prevent accidental token pasting. We prefer to avoid
unneeded extra spaces (for the sake of cpp-using tools like
- imake). Here we remove the space if it is safe to do so. */
+ imake). Here we remove the space if it is safe to do so. */
if (pfile->buffer->rlimit - pfile->buffer->cur >= 3
&& pfile->buffer->rlimit[-2] == '@'
&& pfile->buffer->rlimit[-1] == ' ')
@@ -5236,7 +5230,8 @@ cpp_get_token (pfile)
}
}
-/* Like cpp_get_token, but skip spaces and comments. */
+/* Like cpp_get_token, but skip spaces and comments. */
+
enum cpp_token
cpp_get_non_space_token (pfile)
cpp_reader *pfile;
@@ -5252,7 +5247,7 @@ cpp_get_non_space_token (pfile)
}
}
-/* Parse an identifier starting with C. */
+/* Parse an identifier starting with C. */
int
parse_name (pfile, c)
@@ -5271,7 +5266,10 @@ parse_name (pfile, c)
break;
}
- CPP_RESERVE(pfile, 2); /* One more for final NUL. */
+ if (c == '$' && CPP_PEDANTIC (pfile))
+ cpp_pedwarn ("`$' in identifier");
+
+ CPP_RESERVE(pfile, 2); /* One more for final NUL. */
CPP_PUTC_Q (pfile, c);
c = GETC();
if (c == EOF)
@@ -5416,7 +5414,8 @@ read_filename_string (ch, f)
return alloc;
}
-/* This structure holds a linked list of file name maps, one per directory. */
+/* This structure holds a linked list of file name maps, one per directory. */
+
struct file_name_map_list
{
struct file_name_map_list *map_list_next;
@@ -5513,65 +5512,68 @@ open_include_file (pfile, filename, searchptr)
char *filename;
struct file_name_list *searchptr;
{
- register struct file_name_map *map;
- register char *from;
- char *p, *dir;
-
- if (searchptr && ! searchptr->got_name_map)
+ if (CPP_OPTIONS (pfile)->remap)
{
- searchptr->name_map = read_name_map (pfile,
- searchptr->fname
- ? searchptr->fname : ".");
- searchptr->got_name_map = 1;
- }
+ register struct file_name_map *map;
+ register char *from;
+ char *p, *dir;
- /* 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 (searchptr && ! searchptr->got_name_map)
{
- if (! strcmp (map->map_from, from))
+ searchptr->name_map = read_name_map (pfile,
+ searchptr->fname
+ ? searchptr->fname : ".");
+ searchptr->got_name_map = 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)
{
- /* Found a match. */
- return open (map->map_to, O_RDONLY, 0666);
+ if (! strcmp (map->map_from, from))
+ {
+ /* Found a match. */
+ return open (map->map_to, O_RDONLY, 0666);
+ }
}
}
- }
- /* Try to find a mapping file for the particular directory we are
- looking in. Thus #include <sys/types.h> will look up sys/types.h
- in /usr/include/header.gcc and look up types.h in
- /usr/include/sys/header.gcc. */
- p = rindex (filename, '/');
- if (! p)
- p = filename;
- if (searchptr
- && searchptr->fname
- && strlen (searchptr->fname) == p - filename
- && ! strncmp (searchptr->fname, filename, p - filename))
- {
- /* FILENAME is in SEARCHPTR, which we've already checked. */
- return open (filename, O_RDONLY, 0666);
- }
+ /* Try to find a mapping file for the particular directory we are
+ looking in. Thus #include <sys/types.h> will look up sys/types.h
+ in /usr/include/header.gcc and look up types.h in
+ /usr/include/sys/header.gcc. */
+ p = rindex (filename, '/');
+ if (! p)
+ p = filename;
+ if (searchptr
+ && searchptr->fname
+ && strlen (searchptr->fname) == p - filename
+ && ! strncmp (searchptr->fname, filename, p - filename))
+ {
+ /* FILENAME is in SEARCHPTR, which we've already checked. */
+ return open (filename, O_RDONLY, 0666);
+ }
- if (p == filename)
- {
- dir = ".";
- from = filename;
- }
- else
- {
- dir = (char *) alloca (p - filename + 1);
- bcopy (filename, dir, p - filename);
- dir[p - filename] = '\0';
- from = p + 1;
+ if (p == filename)
+ {
+ dir = ".";
+ from = filename;
+ }
+ else
+ {
+ dir = (char *) alloca (p - filename + 1);
+ bcopy (filename, dir, p - filename);
+ dir[p - filename] = '\0';
+ from = p + 1;
+ }
+ for (map = read_name_map (pfile, dir); map; map = map->map_next)
+ if (! strcmp (map->map_from, from))
+ return open (map->map_to, O_RDONLY, 0666);
}
- for (map = read_name_map (pfile, dir); map; map = map->map_next)
- if (! strcmp (map->map_from, from))
- return open (map->map_to, O_RDONLY, 0666);
return open (filename, O_RDONLY, 0666);
}
@@ -5595,14 +5597,14 @@ finclude (pfile, f, fname, system_header_p, dirptr)
int system_header_p;
struct file_name_list *dirptr;
{
- int st_mode;
- long st_size;
+ struct stat st;
+ size_t st_size;
long i;
int length;
cpp_buffer *fp; /* For input stack frame */
int missing_newline = 0;
- if (file_size_and_mode (f, &st_mode, &st_size) < 0)
+ if (fstat (f, &st) < 0)
{
cpp_perror_with_name (pfile, fname);
close (f);
@@ -5621,7 +5623,13 @@ finclude (pfile, f, fname, system_header_p, dirptr)
fp->colno = 1;
fp->cleanup = file_cleanup;
- if (S_ISREG (st_mode)) {
+ if (S_ISREG (st.st_mode)) {
+ st_size = (size_t) st.st_size;
+ if (st_size != st.st_size || st_size + 2 < st_size) {
+ cpp_error (pfile, "file `%s' too large", fname);
+ close (f);
+ return 0;
+ }
fp->buf = (U_CHAR *) xmalloc (st_size + 2);
fp->alimit = fp->buf + st_size + 2;
fp->cur = fp->buf;
@@ -5632,14 +5640,14 @@ finclude (pfile, f, fname, system_header_p, dirptr)
fp->rlimit = fp->buf + length;
if (length < 0) goto nope;
}
- else if (S_ISDIR (st_mode)) {
+ else if (S_ISDIR (st.st_mode)) {
cpp_error (pfile, "directory `%s' specified in #include", fname);
close (f);
return 0;
} else {
/* Cannot count its file size before reading.
First read the entire file into heap and
- copy them into buffer on stack. */
+ copy them into buffer on stack. */
int bsize = 2000;
@@ -5707,8 +5715,14 @@ finclude (pfile, f, fname, system_header_p, dirptr)
return 1;
}
+/* This is called after options have been processed.
+ * Check options for consistency, and setup for processing input
+ * from the file named FNAME. (Use standard input if FNAME==NULL.)
+ * Return 1 on success, 0 on failure.
+ */
+
int
-push_parse_file (pfile, fname)
+cpp_start_read (pfile, fname)
cpp_reader *pfile;
char *fname;
{
@@ -5739,6 +5753,8 @@ push_parse_file (pfile, fname)
/* Do partial setup of input buffer for the sake of generating
early #line directives (when -g is in effect). */
fp = cpp_push_buffer (pfile, NULL, 0);
+ if (!fp)
+ return 0;
if (opts->in_fname == NULL)
opts->in_fname = "";
fp->nominal_fname = fp->fname = opts->in_fname;
@@ -5823,7 +5839,7 @@ push_parse_file (pfile, fname)
/* Now handle the command line options. */
/* Do -U's, -D's and -A's in the order they were seen. */
- /* First reverse the list. */
+ /* First reverse the list. */
opts->pending = nreverse_pending (opts->pending);
for (pend = opts->pending; pend; pend = pend->next)
@@ -5851,8 +5867,8 @@ push_parse_file (pfile, fname)
opts->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 ((opts->objc << 1) + opts->cplusplus)
{
@@ -5896,6 +5912,7 @@ push_parse_file (pfile, fname)
nstore[endp-startp] = '\0';
include_defaults[num_dirs].fname = savestring (nstore);
+ include_defaults[num_dirs].component = 0;
include_defaults[num_dirs].cplusplus = opts->cplusplus;
include_defaults[num_dirs].cxx_aware = 1;
num_dirs++;
@@ -5962,7 +5979,7 @@ push_parse_file (pfile, fname)
= (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->fname = update_path (p->fname, p->component);
new->got_name_map = 0;
append_include_chain (pfile, new, new);
if (opts->first_system_include == 0)
@@ -6001,9 +6018,10 @@ push_parse_file (pfile, fname)
if (fd < 0)
{
cpp_perror_with_name (pfile, pend->arg);
- return FATAL_EXIT_CODE;
+ return 0;
}
- cpp_push_buffer (pfile, NULL, 0);
+ if (!cpp_push_buffer (pfile, NULL, 0))
+ return 0;
finclude (pfile, fd, pend->arg, 0, NULL_PTR);
cpp_scan_buffer (pfile);
}
@@ -6023,7 +6041,10 @@ push_parse_file (pfile, fname)
inhibit compilation. */
if (opts->print_deps_missing_files
&& (opts->print_deps == 0 || !opts->no_output))
- fatal (pfile, "-MG must be specified with one of -M or -MM");
+ {
+ cpp_fatal (pfile, "-MG must be specified with one of -M or -MM");
+ return 0;
+ }
/* Either of two environment variables can specify output of deps.
Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
@@ -6082,8 +6103,12 @@ push_parse_file (pfile, fname)
deps_output (pfile, "-", ':');
else
{
- char *p, *q;
- int len;
+ char *p, *q, *r;
+ int len, x;
+ static char *known_suffixes[] = { ".c", ".C", ".s", ".S", ".m",
+ ".cc", ".cxx", ".cpp", ".cp",
+ ".c++", 0
+ };
/* Discard all directory prefixes from filename. */
if ((q = rindex (opts->in_fname, '/')) != NULL
@@ -6102,27 +6127,21 @@ push_parse_file (pfile, fname)
/* Output P, but remove known suffixes. */
len = strlen (p);
q = p + len;
- if (len >= 2
- && p[len - 2] == '.'
- && index("cCsSm", p[len - 1]))
- q = p + (len - 2);
- else if (len >= 3
- && p[len - 3] == '.'
- && p[len - 2] == 'c'
- && p[len - 1] == 'c')
- q = p + (len - 3);
- else if (len >= 4
- && p[len - 4] == '.'
- && p[len - 3] == 'c'
- && p[len - 2] == 'x'
- && p[len - 1] == 'x')
- q = p + (len - 4);
- else if (len >= 4
- && p[len - 4] == '.'
- && p[len - 3] == 'c'
- && p[len - 2] == 'p'
- && p[len - 1] == 'p')
- q = p + (len - 4);
+ /* Point to the filename suffix. */
+ r = rindex (p, '.');
+ /* Compare against the known suffixes. */
+ x = 0;
+ while (known_suffixes[x] != 0)
+ {
+ if (strncmp (known_suffixes[x], r, q - r) == 0)
+ {
+ /* Make q point to the bit we're going to overwrite
+ with an object suffix. */
+ q = r;
+ break;
+ }
+ x++;
+ }
/* Supply our own suffix. */
#ifndef VMS
@@ -6166,15 +6185,16 @@ push_parse_file (pfile, fname)
if (fd < 0)
{
cpp_perror_with_name (pfile, pend->arg);
- return FATAL_EXIT_CODE;
+ return 0;
}
- cpp_push_buffer (pfile, NULL, 0);
+ if (!cpp_push_buffer (pfile, NULL, 0))
+ return 0;
finclude (pfile, fd, pend->arg, 0, NULL_PTR);
}
}
pfile->no_record_file--;
- /* Free the pending list. */
+ /* Free the pending list. */
for (pend = opts->pending; pend; )
{
struct cpp_pending *next = pend->next;
@@ -6197,18 +6217,18 @@ push_parse_file (pfile, fname)
#endif
if (finclude (pfile, f, fname, 0, NULL_PTR))
output_line_command (pfile, 0, same_file);
- return SUCCESS_EXIT_CODE;
+ return 1;
}
void
-init_parse_file (pfile)
+cpp_reader_init (pfile)
cpp_reader *pfile;
{
bzero ((char *) pfile, sizeof (cpp_reader));
pfile->get_token = cpp_get_token;
pfile->token_buffer_size = 200;
- pfile->token_buffer = (U_CHAR*)xmalloc (pfile->token_buffer_size);
+ pfile->token_buffer = (U_CHAR *) xmalloc (pfile->token_buffer_size);
CPP_SET_WRITTEN (pfile, 0);
pfile->system_include_depth = 0;
@@ -6242,7 +6262,7 @@ push_pending (pfile, cmd, arg)
char *arg;
{
struct cpp_pending *pend
- = (struct cpp_pending*)xmalloc (sizeof (struct cpp_pending));
+ = (struct cpp_pending *) xmalloc (sizeof (struct cpp_pending));
pend->cmd = cmd;
pend->arg = arg;
pend->next = CPP_OPTIONS (pfile)->pending;
@@ -6265,7 +6285,10 @@ cpp_handle_options (pfile, argc, argv)
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
if (opts->out_fname != NULL)
- fatal ("Usage: %s [switches] input output", argv[0]);
+ {
+ cpp_fatal (pfile, "Usage: %s [switches] input output", argv[0]);
+ return argc;
+ }
else if (opts->in_fname != NULL)
opts->out_fname = argv[i];
else
@@ -6273,17 +6296,24 @@ cpp_handle_options (pfile, argc, argv)
} else {
switch (argv[i][1]) {
+ missing_filename:
+ cpp_fatal (pfile, "Filename missing after `%s' option", argv[i]);
+ return argc;
+ missing_dirname:
+ cpp_fatal (pfile, "Directory name missing after `%s' option", argv[i]);
+ return argc;
+
case 'i':
if (!strcmp (argv[i], "-include")
|| !strcmp (argv[i], "-imacros")) {
if (i + 1 == argc)
- fatal ("Filename missing after `%s' option", argv[i]);
+ goto missing_filename;
else
push_pending (pfile, argv[i], argv[i+1]), i++;
}
if (!strcmp (argv[i], "-iprefix")) {
if (i + 1 == argc)
- fatal ("Filename missing after `-iprefix' option");
+ goto missing_filename;
else
opts->include_prefix = argv[++i];
}
@@ -6294,7 +6324,7 @@ cpp_handle_options (pfile, argc, argv)
struct file_name_list *dirtmp;
if (i + 1 == argc)
- fatal ("Filename missing after `-isystem' option");
+ goto missing_filename;
dirtmp = (struct file_name_list *)
xmalloc (sizeof (struct file_name_list));
@@ -6332,7 +6362,7 @@ cpp_handle_options (pfile, argc, argv)
dirtmp->control_macro = 0;
dirtmp->c_system_include_path = 0;
if (i + 1 == argc)
- fatal ("Directory name missing after `-iwithprefix' option");
+ goto missing_dirname;
dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
+ strlen (prefix) + 1);
@@ -6367,7 +6397,7 @@ cpp_handle_options (pfile, argc, argv)
dirtmp->control_macro = 0;
dirtmp->c_system_include_path = 0;
if (i + 1 == argc)
- fatal ("Directory name missing after `-iwithprefixbefore' option");
+ goto missing_dirname;
dirtmp->fname = (char *) xmalloc (strlen (argv[i+1])
+ strlen (prefix) + 1);
@@ -6387,7 +6417,7 @@ cpp_handle_options (pfile, argc, argv)
dirtmp->control_macro = 0;
dirtmp->c_system_include_path = 0;
if (i + 1 == argc)
- fatal ("Directory name missing after `-idirafter' option");
+ goto missing_dirname;
else
dirtmp->fname = argv[++i];
dirtmp->got_name_map = 0;
@@ -6402,9 +6432,12 @@ cpp_handle_options (pfile, argc, argv)
case 'o':
if (opts->out_fname != NULL)
- fatal ("Output filename specified twice");
+ {
+ cpp_fatal (pfile, "Output filename specified twice");
+ return argc;
+ }
if (i + 1 == argc)
- fatal ("Filename missing after -o option");
+ goto missing_filename;
opts->out_fname = argv[++i];
if (!strcmp (opts->out_fname, "-"))
opts->out_fname = "";
@@ -6420,10 +6453,9 @@ cpp_handle_options (pfile, argc, argv)
#if 0
else if (!strcmp (argv[i], "-pcp")) {
char *pcp_fname = argv[++i];
- pcp_outfile =
- ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
- ? fopen (pcp_fname, "w")
- : fdopen (dup (fileno (stdout)), "w"));
+ pcp_outfile = ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
+ ? fopen (pcp_fname, "w")
+ : fdopen (dup (fileno (stdout)), "w"));
if (pcp_outfile == 0)
cpp_pfatal_with_name (pfile, pcp_fname);
no_precomp = 1;
@@ -6434,8 +6466,6 @@ cpp_handle_options (pfile, argc, argv)
case 't':
if (!strcmp (argv[i], "-traditional")) {
opts->traditional = 1;
- if (opts->dollars_in_ident > 0)
- opts->dollars_in_ident = 1;
} else if (!strcmp (argv[i], "-trigraphs")) {
if (!opts->chill)
opts->no_trigraphs = 0;
@@ -6444,15 +6474,20 @@ cpp_handle_options (pfile, argc, argv)
case 'l':
if (! strcmp (argv[i], "-lang-c"))
- opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->objc = 0;
+ opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 0;
+ if (! strcmp (argv[i], "-lang-c89"))
+ opts->cplusplus = 0, opts->cplusplus_comments = 0, opts->c89 = 1,
+ opts->objc = 0;
if (! strcmp (argv[i], "-lang-c++"))
- opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->objc = 0;
- if (! strcmp (argv[i], "-lang-c-c++-comments"))
- opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->objc = 0;
+ opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 0;
if (! strcmp (argv[i], "-lang-objc"))
- opts->objc = 1, opts->cplusplus = 0, opts->cplusplus_comments = 1;
+ opts->cplusplus = 0, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 1;
if (! strcmp (argv[i], "-lang-objc++"))
- opts->objc = 1, opts->cplusplus = 1, opts->cplusplus_comments = 1;
+ opts->cplusplus = 1, opts->cplusplus_comments = 1, opts->c89 = 0,
+ opts->objc = 1;
if (! strcmp (argv[i], "-lang-asm"))
opts->lang_asm = 1;
if (! strcmp (argv[i], "-lint"))
@@ -6487,6 +6522,10 @@ cpp_handle_options (pfile, argc, argv)
opts->warn_stringify = 1;
else if (!strcmp (argv[i], "-Wno-traditional"))
opts->warn_stringify = 0;
+ else if (!strcmp (argv[i], "-Wundef"))
+ opts->warn_undef = 1;
+ else if (!strcmp (argv[i], "-Wno-undef"))
+ opts->warn_undef = 0;
else if (!strcmp (argv[i], "-Wimport"))
opts->warn_import = 1;
else if (!strcmp (argv[i], "-Wno-import"))
@@ -6532,7 +6571,7 @@ cpp_handle_options (pfile, argc, argv)
if (!strcmp (argv[i], "-MD") || !strcmp (argv[i], "-MMD"))
{
if (i+1 == argc)
- fatal ("Filename missing after %s option", argv[i]);
+ goto missing_filename;
opts->deps_file = argv[++i];
}
else
@@ -6560,6 +6599,9 @@ cpp_handle_options (pfile, argc, argv)
case 'D':
opts->dump_macros = dump_definitions;
break;
+ case 'I':
+ opts->dump_includes = 1;
+ break;
}
}
}
@@ -6587,7 +6629,10 @@ cpp_handle_options (pfile, argc, argv)
if (argv[i][2] != 0)
push_pending (pfile, "-D", argv[i] + 2);
else if (i + 1 == argc)
- fatal ("Macro name missing after -D option");
+ {
+ cpp_fatal (pfile, "Macro name missing after -D option");
+ return argc;
+ }
else
i++, push_pending (pfile, "-D", argv[i]);
break;
@@ -6599,7 +6644,10 @@ cpp_handle_options (pfile, argc, argv)
if (argv[i][2] != 0)
p = argv[i] + 2;
else if (i + 1 == argc)
- fatal ("Assertion missing after -A option");
+ {
+ cpp_fatal (pfile, "Assertion missing after -A option");
+ return argc;
+ }
else
p = argv[++i];
@@ -6633,7 +6681,10 @@ cpp_handle_options (pfile, argc, argv)
if (argv[i][2] != 0)
push_pending (pfile, "-U", argv[i] + 2);
else if (i + 1 == argc)
- fatal ("Macro name missing after -U option");
+ {
+ cpp_fatal (pfile, "Macro name missing after -U option", NULL);
+ return argc;
+ }
else
push_pending (pfile, "-U", argv[i+1]), i++;
break;
@@ -6672,7 +6723,7 @@ cpp_handle_options (pfile, argc, argv)
if (argv[i][2] != 0)
dirtmp->fname = argv[i] + 2;
else if (i + 1 == argc)
- fatal ("Directory name missing after -I option");
+ goto missing_dirname;
else
dirtmp->fname = argv[++i];
dirtmp->got_name_map = 0;
@@ -6695,6 +6746,11 @@ cpp_handle_options (pfile, argc, argv)
#endif
break;
+ case 'r':
+ if (!strcmp (argv[i], "-remap"))
+ opts->remap = 1;
+ break;
+
case 'u':
/* Sun compiler passes undocumented switch "-undef".
Let's assume it means to inhibit the predefined symbols. */
@@ -6742,13 +6798,14 @@ cpp_finish (pfile)
if (opts->deps_file)
{
if (ferror (deps_stream) || fclose (deps_stream) != 0)
- fatal ("I/O error on output");
+ cpp_fatal (pfile, "I/O error on output");
}
}
}
}
-/* Free resources used by PFILE. */
+/* Free resources used by PFILE.
+ This is the cpp_reader 'finalizer' or 'destructor' (in C++ terminology). */
void
cpp_cleanup (pfile)
@@ -7154,25 +7211,9 @@ free_token_list (tokens)
}
}
-/* Get the file-mode and data size of the file open on FD
- and store them in *MODE_POINTER and *SIZE_POINTER. */
-
-static int
-file_size_and_mode (fd, mode_pointer, size_pointer)
- int fd;
- int *mode_pointer;
- long int *size_pointer;
-{
- struct stat sbuf;
-
- 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;
-}
-
/* 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. */
@@ -7182,9 +7223,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
@@ -7202,6 +7250,16 @@ safe_read (desc, ptr, len)
}
static char *
+xcalloc (number, size)
+ unsigned number, size;
+{
+ register unsigned total = number * size;
+ register char *ptr = (char *) xmalloc (total);
+ bzero (ptr, total);
+ return ptr;
+}
+
+static char *
savestring (input)
char *input;
{
@@ -7211,7 +7269,8 @@ savestring (input)
return output;
}
-/* Initialize PMARK to remember the current position of PFILE. */
+/* Initialize PMARK to remember the current position of PFILE. */
+
void
parse_set_mark (pmark, pfile)
struct parse_marker *pmark;
@@ -7224,20 +7283,21 @@ parse_set_mark (pmark, pfile)
pmark->position = pbuf->cur - pbuf->buf;
}
-/* Cleanup PMARK - we no longer need it. */
+/* Cleanup PMARK - we no longer need it. */
+
void
parse_clear_mark (pmark)
struct parse_marker *pmark;
{
struct parse_marker **pp = &pmark->buf->marks;
for (; ; pp = &(*pp)->next) {
- if (*pp == NULL) fatal ("internal error", "in parse_set_mark");
+ if (*pp == NULL) abort ();
if (*pp == pmark) break;
}
*pp = pmark->next;
}
-/* Backup the current position of PFILE to that saved in PMARK. */
+/* Backup the current position of PFILE to that saved in PMARK. */
void
parse_goto_mark (pmark, pfile)
@@ -7246,12 +7306,12 @@ parse_goto_mark (pmark, pfile)
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
if (pbuf != pmark->buf)
- fatal ("internal error %s", "parse_goto_mark");
+ cpp_fatal (pfile, "internal error %s", "parse_goto_mark");
pbuf->cur = pbuf->buf + pmark->position;
}
/* Reset PMARK to point to the current position of PFILE. (Same
- as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */
+ as parse_clear_mark (PMARK), parse_set_mark (PMARK, PFILE) but faster. */
void
parse_move_mark (pmark, pfile)
@@ -7260,7 +7320,7 @@ parse_move_mark (pmark, pfile)
{
cpp_buffer *pbuf = CPP_BUFFER (pfile);
if (pbuf != pmark->buf)
- fatal ("internal error %s", "parse_move_mark");
+ cpp_fatal (pfile, "internal error %s", "parse_move_mark");
pmark->position = pbuf->cur - pbuf->buf;
}
@@ -7429,7 +7489,7 @@ cpp_pedwarn_with_file_and_line (pfile, file, line, msg, arg1, arg2, arg3)
msg, arg1, arg2, arg3);
}
-/* This defines "errno" properly for VMS, and gives us EACCES. */
+/* This defines "errno" properly for VMS, and gives us EACCES. */
#include <errno.h>
#ifndef errno
extern int errno;
@@ -7438,11 +7498,7 @@ extern int errno;
#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
@@ -7450,9 +7506,8 @@ char *strerror ();
char *strerror (int,...);
#endif
-/*
- * my_strerror - return the descriptive text associated with an `errno' code.
- */
+/* my_strerror - return the descriptive text associated with an
+ `errno' code. */
char *
my_strerror (errnum)
diff --git a/gnu/usr.bin/gcc/cpplib.h b/gnu/usr.bin/gcc/cpplib.h
index 3075b7904d2..346ce44037d 100644
--- a/gnu/usr.bin/gcc/cpplib.h
+++ b/gnu/usr.bin/gcc/cpplib.h
@@ -1,5 +1,5 @@
/* Definitions for CPP library.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
Written by Per Bothner, 1994-95.
This program is free software; you can redistribute it and/or modify it
@@ -27,11 +27,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern "C" {
#endif
-#define STATIC_BUFFERS
-
typedef unsigned char U_CHAR;
-struct parse_file;
typedef struct cpp_reader cpp_reader;
typedef struct cpp_buffer cpp_buffer;
typedef struct cpp_options cpp_options;
@@ -72,15 +69,15 @@ enum cpp_token {
};
#ifndef PARAMS
-#ifdef __STDC
+#ifdef __STDC__
#define PARAMS(P) P
#else
#define PARAMS(P) ()
#endif
#endif /* !PARAMS */
-typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader*));
-typedef int (*parse_cleanup_t) PARAMS((cpp_buffer *, cpp_reader*));
+typedef enum cpp_token (*parse_underflow_t) PARAMS((cpp_reader *));
+typedef int (*parse_cleanup_t) PARAMS((cpp_buffer *, cpp_reader *));
/* A parse_marker indicates a previous position,
which we can backtrack to. */
@@ -91,16 +88,18 @@ struct parse_marker {
int position;
};
-extern void parse_set_mark PARAMS ((struct parse_marker*, cpp_reader*));
-extern void parse_clear_mark PARAMS ((struct parse_marker*));
-extern void parse_goto_mark PARAMS((struct parse_marker*, cpp_reader*));
-extern void parse_move_mark PARAMS((struct parse_marker*, cpp_reader*));
+extern void parse_set_mark PARAMS ((struct parse_marker *, cpp_reader *));
+extern void parse_clear_mark PARAMS ((struct parse_marker *));
+extern void parse_goto_mark PARAMS((struct parse_marker *, cpp_reader *));
+extern void parse_move_mark PARAMS((struct parse_marker *, cpp_reader *));
-extern int cpp_handle_options PARAMS ((cpp_reader*, int, char**));
-extern enum cpp_token cpp_get_token PARAMS ((struct parse_marker*));
-extern void cpp_skip_hspace PARAMS((cpp_reader*));
+extern int cpp_handle_options PARAMS ((cpp_reader *, int, char **));
+extern enum cpp_token cpp_get_token PARAMS ((cpp_reader *));
+extern void cpp_skip_hspace PARAMS((cpp_reader *));
extern enum cpp_token cpp_get_non_space_token PARAMS ((cpp_reader *));
+/* This frees resources used by PFILE. */
+extern void cpp_cleanup PARAMS ((cpp_reader *PFILE));
/* Maintain and search list of included files, for #import. */
@@ -134,9 +133,6 @@ struct cpp_buffer {
long line_base;
long lineno; /* Line number at CPP_LINE_BASE. */
long colno; /* Column number at CPP_LINE_BASE. */
-#ifndef STATIC_BUFFERS
- cpp_buffer *chain;
-#endif
parse_underflow_t underflow;
parse_cleanup_t cleanup;
void *data;
@@ -150,7 +146,7 @@ struct cpp_buffer {
char seen_eof;
/* True if buffer contains escape sequences.
- Currently there are are only two kind:
+ Currently there are three kinds:
"@-" means following identifier should not be macro-expanded.
"@ " means a token-separator. This turns into " " in final output
if not stringizing and needed to separate tokens; otherwise nothing.
@@ -165,25 +161,28 @@ struct file_name_map_list;
typedef struct assertion_hashnode ASSERTION_HASHNODE;
#define ASSERTION_HASHSIZE 37
-#ifdef STATIC_BUFFERS
/* Maximum nesting of cpp_buffers. We use a static limit, partly for
efficiency, and partly to limit runaway recursion. */
#define CPP_STACK_MAX 200
-#endif
+
+/* A cpp_reader encapsulates the "state" of a pre-processor run.
+ Applying cpp_get_token repeatedly yields a stream of pre-processor
+ tokens. Usually, there is only one cpp_reader object active. */
struct cpp_reader {
- unsigned char *limit;
parse_underflow_t get_token;
cpp_buffer *buffer;
-#ifdef STATIC_BUFFERS
cpp_buffer buffer_stack[CPP_STACK_MAX];
-#endif
int errors; /* Error counter for exit code */
void *data;
- U_CHAR *token_buffer;
+ /* A buffer used for both for cpp_get_token's output, and also internally. */
+ unsigned char *token_buffer;
+ /* Allocated size of token_buffer. CPP_RESERVE allocates space. */
int token_buffer_size;
+ /* End of the written part of token_buffer. */
+ unsigned char *limit;
/* Line where a newline was first seen in a string constant. */
int multiline_string_line;
@@ -260,14 +259,26 @@ struct cpp_reader {
/* Number of bytes since the last newline. */
int deps_column;
+
+#ifdef __cplusplus
+ ~cpp_reader () { cpp_cleanup (this); }
+#endif
};
+#define CPP_FATAL_LIMIT 1000
+/* True if we have seen a "fatal" error. */
+#define CPP_FATAL_ERRORS(READER) ((READER)->errors >= CPP_FATAL_LIMIT)
+
#define CPP_BUF_PEEK(BUFFER) \
((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur : EOF)
#define CPP_BUF_GET(BUFFER) \
((BUFFER)->cur < (BUFFER)->rlimit ? *(BUFFER)->cur++ : EOF)
#define CPP_FORWARD(BUFFER, N) ((BUFFER)->cur += (N))
+/* Macros for manipulating the token_buffer. */
+
+#define CPP_OUT_BUFFER(PFILE) ((PFILE)->token_buffer)
+
/* Number of characters currently in PFILE's output buffer. */
#define CPP_WRITTEN(PFILE) ((PFILE)->limit - (PFILE)->token_buffer)
#define CPP_PWRITTEN(PFILE) ((PFILE)->limit)
@@ -293,17 +304,14 @@ struct cpp_reader {
#define CPP_ADJUST_WRITTEN(PFILE,DELTA) ((PFILE)->limit += (DELTA))
#define CPP_SET_WRITTEN(PFILE,N) ((PFILE)->limit = (PFILE)->token_buffer + (N))
-#define CPP_OPTIONS(PFILE) ((cpp_options*)(PFILE)->data)
+#define CPP_OPTIONS(PFILE) ((cpp_options *) (PFILE)->data)
+
#define CPP_BUFFER(PFILE) ((PFILE)->buffer)
-#ifdef STATIC_BUFFERS
#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)+1)
+/* The bottom of the buffer stack. */
#define CPP_NULL_BUFFER(PFILE) (&(PFILE)->buffer_stack[CPP_STACK_MAX])
-#else
-#define CPP_PREV_BUFFER(BUFFER) ((BUFFER)->chain)
-#define CPP_NULL_BUFFER(PFILE) ((cpp_buffer*)0)
-#endif
-/* Pointed to by parse_file::data. */
+/* Pointed to by cpp_reader::data. */
struct cpp_options {
char *in_fname;
@@ -402,6 +410,10 @@ struct cpp_options {
char no_output;
+ /* Nonzero means we should look for header.gcc files that remap file
+ names. */
+ char remap;
+
/* Nonzero means don't output line number information. */
char no_line_commands;
@@ -415,21 +427,20 @@ struct cpp_options {
so don't look for #include "foo" the source-file directory. */
char ignore_srcdir;
-/* 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) */
+ /* Zero means dollar signs are punctuation.
+ This used to be needed for conformance to the C Standard,
+ before the C Standard was corrected. */
char dollars_in_ident;
-#ifndef DOLLARS_IN_IDENTIFIERS
-#define DOLLARS_IN_IDENTIFIERS 1
-#endif
/* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */
char traditional;
+ /* Nonzero means warn if undefined identifiers are evaluated in an #if. */
+ char warn_undef;
+
+ /* Nonzero for the 1989 C Standard, including corrigenda and amendments. */
+ char c89;
+
/* Nonzero means give all the error messages the ANSI standard requires. */
char pedantic;
@@ -479,6 +490,10 @@ struct cpp_options {
where they are defined. */
int debug_output;
+ /* Nonzero means pass #include lines through to the output,
+ even if they are ifdefed out. */
+ int dump_includes;
+
/* Pending -D, -U and -A options, in reverse order. */
struct cpp_pending *pending;
@@ -491,6 +506,8 @@ struct cpp_options {
};
#define CPP_TRADITIONAL(PFILE) (CPP_OPTIONS(PFILE)-> traditional)
+#define CPP_WARN_UNDEF(PFILE) (CPP_OPTIONS(PFILE)->warn_undef)
+#define CPP_C89(PFILE) (CPP_OPTIONS(PFILE)->c89)
#define CPP_PEDANTIC(PFILE) (CPP_OPTIONS (PFILE)->pedantic)
#define CPP_PRINT_DEPS(PFILE) (CPP_OPTIONS (PFILE)->print_deps)
@@ -551,7 +568,7 @@ typedef struct macrodef MACRODEF;
struct macrodef
{
struct definition *defn;
- U_CHAR *symnam;
+ unsigned char *symnam;
int symlen;
};
@@ -582,7 +599,7 @@ struct definition {
int length; /* length of expansion string */
int predefined; /* True if the macro was builtin or */
/* came from the command line */
- U_CHAR *expansion;
+ unsigned char *expansion;
int line; /* Line number of definition */
char *file; /* File of definition */
char rest_args; /* Nonzero if last arg. absorbs the rest */
@@ -602,11 +619,11 @@ struct definition {
with comma-space between them.
The only use of this is that we warn on redefinition
if this differs between the old and new definitions. */
- U_CHAR *argnames;
+ unsigned char *argnames;
} args;
};
-extern U_CHAR is_idchar[256];
+extern unsigned char is_idchar[256];
/* Stack of conditionals currently in progress
(including both successful and failing conditionals). */
@@ -617,15 +634,15 @@ struct if_stack {
int lineno; /* similarly */
int if_succeeded; /* true if a leg of this if-group
has been passed through rescan */
- U_CHAR *control_macro; /* For #ifndef at start of file,
+ unsigned char *control_macro; /* For #ifndef at start of file,
this is the macro name tested. */
enum node_type type; /* type of last directive seen in this group */
};
typedef struct if_stack IF_STACK_FRAME;
-extern void cpp_buf_line_and_col PARAMS((cpp_buffer*, long*, long*));
-extern cpp_buffer* cpp_file_buffer PARAMS((cpp_reader*));
-extern void cpp_define PARAMS ((cpp_reader*, U_CHAR*));
+extern void cpp_buf_line_and_col PARAMS((cpp_buffer *, long *, long *));
+extern cpp_buffer* cpp_file_buffer PARAMS((cpp_reader *));
+extern void cpp_define PARAMS ((cpp_reader*, unsigned char *));
extern void cpp_error ();
extern void cpp_warning ();
@@ -638,12 +655,13 @@ extern void cpp_error_from_errno ();
extern void cpp_perror_with_name ();
extern void cpp_pfatal_with_name ();
-extern void cpp_grow_buffer PARAMS ((cpp_reader*, long));
-extern int cpp_parse_escape PARAMS ((cpp_reader*, char**));
-extern cpp_buffer* cpp_push_buffer PARAMS ((cpp_reader *, U_CHAR*, long));
-extern cpp_buffer* cpp_pop_buffer PARAMS ((cpp_reader *));
+extern void cpp_grow_buffer PARAMS ((cpp_reader *, long));
+extern int cpp_parse_escape PARAMS ((cpp_reader *, char **));
+extern cpp_buffer *cpp_push_buffer PARAMS ((cpp_reader *,
+ unsigned char *, long));
+extern cpp_buffer *cpp_pop_buffer PARAMS ((cpp_reader *));
-extern cpp_hashnode* cpp_lookup PARAMS ((cpp_reader*, const U_CHAR*,
+extern cpp_hashnode *cpp_lookup PARAMS ((cpp_reader *, const unsigned char *,
int, int));
#ifdef __cplusplus
diff --git a/gnu/usr.bin/gcc/cppmain.c b/gnu/usr.bin/gcc/cppmain.c
index 506ce05f7e8..83bbe94f7da 100644
--- a/gnu/usr.bin/gcc/cppmain.c
+++ b/gnu/usr.bin/gcc/cppmain.c
@@ -1,5 +1,5 @@
/* CPP main program, using CPP Library.
- Copyright (C) 1995 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997 Free Software Foundation, Inc.
Written by Per Bothner, 1994-95.
This program is free software; you can redistribute it and/or modify it
@@ -20,13 +20,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
You are forbidden to forbid anyone else to use, share and improve
what you give them. Help stamp out software-hoarding! */
-#include "cpplib.h"
-#include <stdio.h>
-
#ifndef EMACS
#include "config.h"
#endif /* not EMACS */
+#include "cpplib.h"
+#include <stdio.h>
+
extern char *getenv ();
char *progname;
@@ -34,6 +34,7 @@ char *progname;
cpp_reader parse_in;
cpp_options options;
+#ifdef abort
/* More 'friendly' abort that prints the line and file.
config.h can #define abort fancy_abort if you like that sort of thing. */
@@ -42,6 +43,7 @@ fancy_abort ()
{
fatal ("Internal gcc abort.");
}
+#endif
int
@@ -51,26 +53,28 @@ main (argc, argv)
{
char *p;
int i;
- int argi = 1; /* Next argument to handle. */
+ int argi = 1; /* Next argument to handle. */
struct cpp_options *opts = &options;
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && p[-1] != '/') --p;
progname = p;
- init_parse_file (&parse_in);
+ cpp_reader_init (&parse_in);
parse_in.data = opts;
- init_parse_options (opts);
+ cpp_options_init (opts);
argi += cpp_handle_options (&parse_in, argc - argi , argv + argi);
- if (argi < argc)
- fatal ("Invalid option `%s'", argv[argi]);
+ if (argi < argc && ! CPP_FATAL_ERRORS (&parse_in))
+ cpp_fatal (&parse_in, "Invalid option `%s'", argv[argi]);
+ if (CPP_FATAL_ERRORS (&parse_in))
+ exit (FATAL_EXIT_CODE);
+
parse_in.show_column = 1;
- i = push_parse_file (&parse_in, opts->in_fname);
- if (i != SUCCESS_EXIT_CODE)
- return i;
+ if (! cpp_start_read (&parse_in, opts->in_fname))
+ exit (FATAL_EXIT_CODE);
/* Now that we know the input file is valid, open the output. */
@@ -86,7 +90,7 @@ main (argc, argv)
{
fwrite (parse_in.token_buffer, 1, CPP_WRITTEN (&parse_in), stdout);
}
- parse_in.limit = parse_in.token_buffer;
+ CPP_SET_WRITTEN (&parse_in, 0);
kind = cpp_get_token (&parse_in);
if (kind == CPP_EOF)
break;
diff --git a/gnu/usr.bin/gcc/cross-make b/gnu/usr.bin/gcc/cross-make
index 33bf93088df..5e5a93fb44e 100644
--- a/gnu/usr.bin/gcc/cross-make
+++ b/gnu/usr.bin/gcc/cross-make
@@ -22,6 +22,3 @@ FLOAT_H = $(CROSS_FLOAT_H)
# Don't install assert.h in /usr/local/include.
assertdir = $(tooldir)/include
-
-# Don't run fixproto
-STMP_FIXPROTO =
diff --git a/gnu/usr.bin/gcc/crtstuff.c b/gnu/usr.bin/gcc/crtstuff.c
index 8bd3b1abf4c..52a3c048e60 100644
--- a/gnu/usr.bin/gcc/crtstuff.c
+++ b/gnu/usr.bin/gcc/crtstuff.c
@@ -1,9 +1,7 @@
/* Specialized bits of code needed to support construction and
destruction of file-scope objects in C++ code.
-
- Written by Ron Guilmette (rfg@netcom.com) with help from Richard Stallman.
-
-Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.com).
This file is part of GNU CC.
@@ -54,6 +52,9 @@ Boston, MA 02111-1307, USA. */
do not apply. */
#include "tm.h"
+#include "defaults.h"
+#include <stddef.h>
+#include "frame.h"
/* Provide default definitions for the pseudo-ops used to switch to the
.ctors and .dtors sections.
@@ -77,6 +78,9 @@ Boston, MA 02111-1307, USA. */
#ifndef DTORS_SECTION_ASM_OP
#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
#endif
+#if !defined (EH_FRAME_SECTION_ASM_OP) && defined (DWARF2_UNWIND_INFO) && defined(ASM_OUTPUT_SECTION_NAME)
+#define EH_FRAME_SECTION_ASM_OP ".section\t.eh_frame,\"aw\""
+#endif
#ifdef OBJECT_FORMAT_ELF
@@ -113,18 +117,32 @@ typedef void (*func_ptr) (void);
functions in each root executable and one in each shared library, but
although they all have the same code, each one is unique in that it
refers to one particular associated `__DTOR_LIST__' which belongs to the
- same particular root executable or shared library file. */
+ same particular root executable or shared library file.
+
+ On some systems, this routine is run more than once from the .fini,
+ when exit is called recursively, so we arrange to remember where in
+ the list we left off processing, and we resume at that point,
+ should we be re-invoked. */
+static char __EH_FRAME_BEGIN__[];
static func_ptr __DTOR_LIST__[];
static void
__do_global_dtors_aux ()
{
- func_ptr *p;
- for (p = __DTOR_LIST__ + 1; *p; p++)
- (*p) ();
+ static func_ptr *p = __DTOR_LIST__ + 1;
+ while (*p)
+ {
+ p++;
+ (*(p-1)) ();
+ }
+
+#ifdef EH_FRAME_SECTION_ASM_OP
+ __deregister_frame_info (__EH_FRAME_BEGIN__);
+#endif
}
/* Stick a call to __do_global_dtors_aux into the .fini section. */
+
static void
fini_dummy ()
{
@@ -136,6 +154,30 @@ fini_dummy ()
asm (TEXT_SECTION_ASM_OP);
}
+#ifdef EH_FRAME_SECTION_ASM_OP
+/* Stick a call to __register_frame_info into the .init section. For some
+ reason calls with no arguments work more reliably in .init, so stick the
+ call in another function. */
+
+static void
+frame_dummy ()
+{
+ static struct object object;
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+}
+
+static void
+init_dummy ()
+{
+ asm (INIT_SECTION_ASM_OP);
+ frame_dummy ();
+#ifdef FORCE_INIT_SECTION_ALIGN
+ FORCE_INIT_SECTION_ALIGN;
+#endif
+ asm (TEXT_SECTION_ASM_OP);
+}
+#endif /* EH_FRAME_SECTION_ASM_OP */
+
#else /* OBJECT_FORMAT_ELF */
/* The function __do_global_ctors_aux is compiled twice (once in crtbegin.o
@@ -144,6 +186,7 @@ fini_dummy ()
function. It is externally callable so that __main can invoke it when
INVOKE__main is defined. This has the additional effect of forcing cc1
to switch to the .text section. */
+
static void __do_global_ctors_aux ();
void __do_global_ctors ()
{
@@ -163,7 +206,7 @@ asm (INIT_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
crti.o may do something, such as bump the stack, which we have to
undo before we reach the function prologue code for __do_global_ctors
(directly below). For such systems, define the macro INIT_SECTION_PREAMBLE
- to expand into the code needed to undo the actions of the crti.o file. */
+ to expand into the code needed to undo the actions of the crti.o file. */
#ifdef INIT_SECTION_PREAMBLE
INIT_SECTION_PREAMBLE;
@@ -186,6 +229,29 @@ __do_global_ctors_aux () /* prologue goes in .init section */
}
#endif /* OBJECT_FORMAT_ELF */
+
+#else /* defined(INIT_SECTION_ASM_OP) */
+
+#ifdef HAS_INIT_SECTION
+/* This case is used by the Irix 6 port, which supports named sections but
+ not an SVR4-style .fini section. __do_global_dtors can be non-static
+ in this case because we protect it with -hidden_symbol. */
+
+static char __EH_FRAME_BEGIN__[];
+static func_ptr __DTOR_LIST__[];
+void
+__do_global_dtors ()
+{
+ func_ptr *p;
+ for (p = __DTOR_LIST__ + 1; *p; p++)
+ (*p) ();
+
+#ifdef EH_FRAME_SECTION_ASM_OP
+ __deregister_frame_info (__EH_FRAME_BEGIN__);
+#endif
+}
+#endif
+
#endif /* defined(INIT_SECTION_ASM_OP) */
/* Force cc1 to switch to .data section. */
@@ -219,6 +285,17 @@ asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
STATIC func_ptr __DTOR_LIST__[1] = { (func_ptr) (-1) };
#endif
+#ifdef EH_FRAME_SECTION_ASM_OP
+/* Stick a label at the beginning of the frame unwind info so we can register
+ and deregister it with the exception handling library code. */
+
+asm (EH_FRAME_SECTION_ASM_OP);
+#ifdef INIT_SECTION_ASM_OP
+STATIC
+#endif
+char __EH_FRAME_BEGIN__[] = { };
+#endif /* EH_FRAME_SECTION_ASM_OP */
+
#endif /* defined(CRT_BEGIN) */
#ifdef CRT_END
@@ -237,6 +314,7 @@ __do_global_ctors_aux ()
}
/* Stick a call to __do_global_ctors_aux into the .init section. */
+
static void
init_dummy ()
{
@@ -247,12 +325,12 @@ init_dummy ()
#endif
asm (TEXT_SECTION_ASM_OP);
-/* This is a kludge. The Linux dynamic linker needs ___brk_addr, __environ
- and atexit (). We have to make sure they are in the .dynsym section. We
- accomplish it by making a dummy call here. This
- code is never reached. */
+/* This is a kludge. The i386 GNU/Linux dynamic linker needs ___brk_addr,
+ __environ and atexit (). We have to make sure they are in the .dynsym
+ section. We accomplish it by making a dummy call here. This
+ code is never reached. */
-#if defined(__linux__) && defined(__PIC__)
+#if defined(__linux__) && defined(__PIC__) && defined(__i386__)
{
extern void *___brk_addr;
extern char **__environ;
@@ -284,7 +362,7 @@ init_dummy ()
other libraries, etc. That's because those other initializations may
include setup operations for very primitive things (e.g. initializing
the state of the floating-point coprocessor, etc.) which should be done
- before we start to execute any of the user's code. */
+ before we start to execute any of the user's code. */
static void
__do_global_ctors_aux () /* prologue goes in .text section */
@@ -292,10 +370,35 @@ __do_global_ctors_aux () /* prologue goes in .text section */
asm (INIT_SECTION_ASM_OP);
DO_GLOBAL_CTORS_BODY;
ON_EXIT (__do_global_dtors, 0);
+#ifdef FORCE_INIT_SECTION_ALIGN
+ FORCE_INIT_SECTION_ALIGN;
+#endif
+ asm (TEXT_SECTION_ASM_OP);
} /* epilogue and body go in .init section */
#endif /* OBJECT_FORMAT_ELF */
+#else /* defined(INIT_SECTION_ASM_OP) */
+
+#ifdef HAS_INIT_SECTION
+/* This case is used by the Irix 6 port, which supports named sections but
+ not an SVR4-style .init section. __do_global_ctors can be non-static
+ in this case because we protect it with -hidden_symbol. */
+extern char __EH_FRAME_BEGIN__[];
+static func_ptr __CTOR_END__[];
+void
+__do_global_ctors ()
+{
+ func_ptr *p;
+#ifdef EH_FRAME_SECTION_ASM_OP
+ static struct object object;
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+#endif
+ for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
+ (*p) ();
+}
+#endif
+
#endif /* defined(INIT_SECTION_ASM_OP) */
/* Force cc1 to switch to .data section. */
@@ -321,4 +424,13 @@ asm (DTORS_SECTION_ASM_OP); /* cc1 doesn't know that we are switching! */
STATIC func_ptr __DTOR_END__[1] = { (func_ptr) 0 };
#endif
+#ifdef EH_FRAME_SECTION_ASM_OP
+/* Terminate the frame unwind info section with a 4byte 0 as a sentinel;
+ this would be the 'length' field in a real FDE. */
+
+typedef unsigned int ui32 __attribute__ ((mode (SI)));
+asm (EH_FRAME_SECTION_ASM_OP);
+STATIC ui32 __FRAME_END__[] = { 0 };
+#endif /* EH_FRAME_SECTION */
+
#endif /* defined(CRT_END) */
diff --git a/gnu/usr.bin/gcc/dbxout.c b/gnu/usr.bin/gcc/dbxout.c
index e3226147aee..92557685b31 100644
--- a/gnu/usr.bin/gcc/dbxout.c
+++ b/gnu/usr.bin/gcc/dbxout.c
@@ -1,5 +1,5 @@
/* Output dbx-format symbol table information from GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -67,11 +67,11 @@ Boston, MA 02111-1307, USA. */
For more on data type definitions, see `dbxout_type'. */
-/* Include these first, because they may define MIN and MAX. */
+#include "config.h"
+
#include <stdio.h>
#include <errno.h>
-#include "config.h"
#include "tree.h"
#include "rtl.h"
#include "flags.h"
@@ -127,9 +127,20 @@ extern int errno;
#endif
/* Nonzero means if the type has methods, only output debugging
- information if methods are actually written to the asm file. */
+ information if methods are actually written to the asm file. This
+ optimization only works if the debugger can detect the special C++
+ marker. */
+
+#define MINIMAL_DEBUG 1
+
+#ifdef NO_DOLLAR_IN_LABEL
+#ifdef NO_DOT_IN_LABEL
+#undef MINIMAL_DEBUG
+#define MINIMAL_DEBUG 0
+#endif
+#endif
-static int flag_minimal_debug = 1;
+static int flag_minimal_debug = MINIMAL_DEBUG;
/* Nonzero if we have actually used any of the GDB extensions
to the debugging format. The idea is that we use them for the
@@ -143,6 +154,8 @@ static int have_used_extensions = 0;
static int source_label_number = 1;
+static int scope_labelno = 0;
+
char *getpwd ();
/* Typical USG systems don't have stab.h, and they also have
@@ -156,7 +169,7 @@ char *getpwd ();
#define FORCE_TEXT
#endif
-#if defined (USG) || defined (NO_STAB_H)
+#if defined (USG) || defined (NO_STAB_H) || defined (CROSS_COMPILE)
#include "gstab.h" /* If doing DBX on sysV, use our own stab.h. */
#else
#include <stab.h> /* On BSD, use the system's stab.h. */
@@ -205,15 +218,28 @@ static char *cwd;
enum typestatus {TYPE_UNSEEN, TYPE_XREF, TYPE_DEFINED};
-/* Vector recording the status of describing C data types.
+/* Structure recording information about a C data type.
+ The status element says whether we have yet output
+ the definition of the type. TYPE_XREF says we have
+ output it as a cross-reference only.
+ The file_number and type_number elements are used if DBX_USE_BINCL
+ is defined. */
+
+struct typeinfo
+{
+ enum typestatus status;
+#ifdef DBX_USE_BINCL
+ int file_number;
+ int type_number;
+#endif
+};
+
+/* Vector recording information about C data types.
When we first notice a data type (a tree node),
we assign it a number using next_type_number.
- That is its index in this vector.
- The vector element says whether we have yet output
- the definition of the type. TYPE_XREF says we have
- output it as a cross-reference only. */
+ That is its index in this vector. */
-enum typestatus *typevec;
+struct typeinfo *typevec;
/* Number of elements of space allocated in `typevec'. */
@@ -225,6 +251,29 @@ static int typevec_len;
static int next_type_number;
+#ifdef DBX_USE_BINCL
+
+/* When using N_BINCL in dbx output, each type number is actually a
+ pair of the file number and the type number within the file.
+ This is a stack of input files. */
+
+struct dbx_file
+{
+ struct dbx_file *next;
+ int file_number;
+ int next_type_number;
+};
+
+/* This is the top of the stack. */
+
+static struct dbx_file *current_file;
+
+/* This is the next file number to use. */
+
+static int next_file_number;
+
+#endif /* DBX_USE_BINCL */
+
/* In dbx output, we must assign symbol-blocks id numbers
in the order in which their beginnings are encountered.
We output debugging info that refers to the beginning and
@@ -275,121 +324,46 @@ static int current_sym_nchars;
void dbxout_types ();
void dbxout_args ();
void dbxout_symbol ();
-static void dbxout_type_name ();
-static void dbxout_type ();
-static void dbxout_typedefs ();
-static void dbxout_symbol_name ();
-static void dbxout_symbol_location ();
-static void dbxout_prepare_symbol ();
-static void dbxout_finish_symbol ();
-static void dbxout_continue ();
-static void print_int_cst_octal ();
-static void print_octal ();
+
+static void dbxout_function_end PROTO((void));
+static void dbxout_typedefs PROTO((tree));
+static void dbxout_type_index PROTO((tree));
+static void dbxout_continue PROTO((void));
+static void dbxout_type_fields PROTO((tree));
+static void dbxout_type_method_1 PROTO((tree, char *));
+static void dbxout_type_methods PROTO((tree));
+static void dbxout_range_type PROTO((tree));
+static void dbxout_type PROTO((tree, int, int));
+static void print_int_cst_octal PROTO((tree));
+static void print_octal PROTO((unsigned HOST_WIDE_INT, int));
+static void dbxout_type_name PROTO((tree));
+static void dbxout_symbol_location PROTO((tree, tree, char *, rtx));
+static void dbxout_symbol_name PROTO((tree, char *, int));
+static void dbxout_prepare_symbol PROTO((tree));
+static void dbxout_finish_symbol PROTO((tree));
+static void dbxout_block PROTO((tree, int, tree));
+static void dbxout_really_begin_function PROTO((tree));
-#if 0 /* Not clear we will actually need this. */
-
-/* Return the absolutized filename for the given relative
- filename. Note that if that filename is already absolute, it may
- still be returned in a modified form because this routine also
- eliminates redundant slashes and single dots and eliminates double
- dots to get a shortest possible filename from the given input
- filename. The absolutization of relative filenames is made by
- assuming that the given filename is to be taken as relative to
- the first argument (cwd) or to the current directory if cwd is
- NULL. */
-
-static char *
-abspath (rel_filename)
- char *rel_filename;
+static void
+dbxout_function_end ()
{
- /* Setup the current working directory as needed. */
- char *abs_buffer
- = (char *) alloca (strlen (cwd) + strlen (rel_filename) + 1);
- char *endp = abs_buffer;
- char *outp, *inp;
- char *value;
-
- /* Copy the filename (possibly preceded by the current working
- directory name) into the absolutization buffer. */
-
- {
- char *src_p;
-
- if (rel_filename[0] != '/')
- {
- src_p = cwd;
- while (*endp++ = *src_p++)
- continue;
- *(endp-1) = '/'; /* overwrite null */
- }
- src_p = rel_filename;
- while (*endp++ = *src_p++)
- continue;
- if (endp[-1] == '/')
- *endp = '\0';
-
- /* Now make a copy of abs_buffer into abs_buffer, shortening the
- filename (by taking out slashes and dots) as we go. */
-
- outp = inp = abs_buffer;
- *outp++ = *inp++; /* copy first slash */
- for (;;)
- {
- if (!inp[0])
- break;
- else if (inp[0] == '/' && outp[-1] == '/')
- {
- inp++;
- continue;
- }
- else if (inp[0] == '.' && outp[-1] == '/')
- {
- if (!inp[1])
- break;
- else if (inp[1] == '/')
- {
- inp += 2;
- continue;
- }
- else if ((inp[1] == '.') && (inp[2] == 0 || inp[2] == '/'))
- {
- inp += (inp[2] == '/') ? 3 : 2;
- outp -= 2;
- while (outp >= abs_buffer && *outp != '/')
- outp--;
- if (outp < abs_buffer)
- {
- /* Catch cases like /.. where we try to backup to a
- point above the absolute root of the logical file
- system. */
-
- fprintf (stderr, "%s: invalid file name: %s\n",
- pname, rel_filename);
- exit (1);
- }
- *++outp = '\0';
- continue;
- }
- }
- *outp++ = *inp++;
- }
-
- /* On exit, make sure that there is a trailing null, and make sure that
- the last character of the returned string is *not* a slash. */
-
- *outp = '\0';
- if (outp[-1] == '/')
- *--outp = '\0';
-
- /* Make a copy (in the heap) of the stuff left in the absolutization
- buffer and return a pointer to the copy. */
-
- value = (char *) oballoc (strlen (abs_buffer) + 1);
- strcpy (value, abs_buffer);
- return value;
+ char lscope_label_name[100];
+ /* Convert Ltext into the appropriate format for local labels in case
+ the system doesn't insert underscores in front of user generated
+ labels. */
+ ASM_GENERATE_INTERNAL_LABEL (lscope_label_name, "Lscope", scope_labelno);
+ ASM_OUTPUT_INTERNAL_LABEL (asmfile, "Lscope", scope_labelno);
+ scope_labelno++;
+
+ /* By convention, GCC will mark the end of a function with an N_FUN
+ symbol and an empty string. */
+ fprintf (asmfile, "%s \"\",%d,0,0,", ASM_STABS_OP, N_FUN);
+ assemble_name (asmfile, lscope_label_name);
+ fputc ('-', asmfile);
+ assemble_name (asmfile, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));
+ fprintf (asmfile, "\n");
}
-#endif /* 0 */
-
+
/* At the beginning of compilation, start writing the symbol table.
Initialize `typevec' and output the standard data types of C. */
@@ -404,7 +378,7 @@ dbxout_init (asm_file, input_file_name, syms)
asmfile = asm_file;
typevec_len = 100;
- typevec = (enum typestatus *) xmalloc (typevec_len * sizeof typevec[0]);
+ typevec = (struct typeinfo *) xmalloc (typevec_len * sizeof typevec[0]);
bzero ((char *) typevec, typevec_len * sizeof typevec[0]);
/* Convert Ltext into the appropriate format for local labels in case
@@ -464,6 +438,14 @@ dbxout_init (asm_file, input_file_name, syms)
next_type_number = 1;
next_block_number = 2;
+#ifdef DBX_USE_BINCL
+ current_file = (struct dbx_file *) xmalloc (sizeof *current_file);
+ current_file->next = NULL;
+ current_file->file_number = 0;
+ current_file->next_type_number = 1;
+ next_file_number = 1;
+#endif
+
/* Make sure that types `int' and `char' have numbers 1 and 2.
Definitions of other integer types will refer to those numbers.
(Actually it should no longer matter what their numbers are.
@@ -499,12 +481,47 @@ dbxout_typedefs (syms)
tree type = TREE_TYPE (syms);
if (TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && TYPE_SIZE (type) != NULL_TREE
&& ! TREE_ASM_WRITTEN (TYPE_NAME (type)))
dbxout_symbol (TYPE_NAME (type), 0);
}
}
}
+/* Change to reading from a new source file. Generate a N_BINCL stab. */
+
+void
+dbxout_start_new_source_file (filename)
+ char *filename;
+{
+#ifdef DBX_USE_BINCL
+ struct dbx_file *n = (struct dbx_file *) xmalloc (sizeof *n);
+
+ n->next = current_file;
+ n->file_number = next_file_number++;
+ n->next_type_number = 1;
+ current_file = n;
+ fprintf (asmfile, "%s ", ASM_STABS_OP);
+ output_quoted_string (asmfile, filename);
+ fprintf (asmfile, ",%d,0,0,0\n", N_BINCL);
+#endif
+}
+
+/* Revert to reading a previous source file. Generate a N_EINCL stab. */
+
+void
+dbxout_resume_previous_source_file ()
+{
+#ifdef DBX_USE_BINCL
+ struct dbx_file *next;
+
+ fprintf (asmfile, "%s %d,0,0,0\n", ASM_STABN_OP, N_EINCL);
+ next = current_file->next;
+ free (current_file);
+ current_file = next;
+#endif
+}
+
/* Output debugging info to FILE to switch to sourcefile FILENAME. */
void
@@ -556,7 +573,7 @@ dbxout_source_line (file, filename, lineno)
/* At the end of compilation, finish writing the symbol table.
Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is
- to do nothing. */
+ to do nothing. */
void
dbxout_finish (file, filename)
@@ -568,6 +585,22 @@ dbxout_finish (file, filename)
#endif /* DBX_OUTPUT_MAIN_SOURCE_FILE_END */
}
+/* Output the index of a type. */
+
+static void
+dbxout_type_index (type)
+ tree type;
+{
+#ifndef DBX_USE_BINCL
+ fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
+ CHARS (3);
+#else
+ struct typeinfo *t = &typevec[TYPE_SYMTAB_ADDRESS (type)];
+ fprintf (asmfile, "(%d,%d)", t->file_number, t->type_number);
+ CHARS (7);
+#endif
+}
+
/* Continue a symbol-description that gets too big.
End one symbol table entry with a double-backslash
and start a new one, eventually producing something like
@@ -609,6 +642,8 @@ dbxout_type_fields (type)
|| TREE_CODE (DECL_SIZE (tem)) != INTEGER_CST))
continue;
/* Omit here the nameless fields that are used to skip bits. */
+ else if (DECL_IGNORED_P (tem))
+ continue;
else if (TREE_CODE (tem) != CONST_DECL)
{
/* Continue the line if necessary,
@@ -805,7 +840,7 @@ dbxout_type_methods (type)
/* This is the "mangled" name of the method.
It encodes the argument types. */
char *debug_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl));
- int destructor = 0;
+ int show_arg_types = 0;
CONTIN;
@@ -816,10 +851,23 @@ dbxout_type_methods (type)
if (flag_minimal_debug)
{
+ char marker;
+
+ /* We can't optimize a method which uses an anonymous
+ class, because the debugger will not be able to
+ associate the arbitrary class name with the actual
+ class. */
+#ifndef NO_DOLLAR_IN_LABEL
+ marker = '$';
+#else
+ marker = '.';
+#endif
+ if (strchr (debug_name, marker))
+ show_arg_types = 1;
/* Detect ordinary methods because their mangled names
start with the operation name. */
- if (!strncmp (IDENTIFIER_POINTER (name), debug_name,
- IDENTIFIER_LENGTH (name)))
+ else if (!strncmp (IDENTIFIER_POINTER (name), debug_name,
+ IDENTIFIER_LENGTH (name)))
{
debug_name += IDENTIFIER_LENGTH (name);
if (debug_name[0] == '_' && debug_name[1] == '_')
@@ -829,7 +877,7 @@ dbxout_type_methods (type)
/* Get past const and volatile qualifiers. */
while (*method_name == 'C' || *method_name == 'V')
method_name++;
- /* Skip digits for length of type_encoding. */
+ /* Skip digits for length of type_encoding. */
while (*method_name == *length_ptr && *length_ptr)
length_ptr++, method_name++;
if (! strncmp (method_name,
@@ -846,7 +894,7 @@ dbxout_type_methods (type)
char *length_ptr = formatted_type_identifier_length;
while (*ctor_name == 'C' || *ctor_name == 'V')
ctor_name++;
- /* Skip digits for length of type_encoding. */
+ /* Skip digits for length of type_encoding. */
while (*ctor_name == *length_ptr && *length_ptr)
length_ptr++, ctor_name++;
if (!strncmp (IDENTIFIER_POINTER (type_encoding), ctor_name,
@@ -855,7 +903,7 @@ dbxout_type_methods (type)
}
/* The other alternative is a destructor. */
else
- destructor = 1;
+ show_arg_types = 1;
/* Output the operation name just once, for the first method
that we output. */
@@ -867,7 +915,7 @@ dbxout_type_methods (type)
}
}
- dbxout_type (TREE_TYPE (fndecl), 0, destructor);
+ dbxout_type (TREE_TYPE (fndecl), 0, show_arg_types);
dbxout_type_method_1 (fndecl, debug_name);
}
@@ -881,7 +929,7 @@ dbxout_type_methods (type)
/* Emit a "range" type specification, which has the form:
"r<index type>;<lower bound>;<upper bound>;".
- TYPE is an INTEGER_TYPE. */
+ TYPE is an INTEGER_TYPE. */
static void
dbxout_range_type (type)
@@ -894,9 +942,12 @@ dbxout_range_type (type)
dbxout_type (type, 0, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
else
{
- /* This used to say `r1' and we used to take care
- to make sure that `int' was type number 1. */
- fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (integer_type_node));
+ /* Traditionally, we made sure 'int' was type 1, and builtin types
+ were defined to be sub-ranges of int. Unfortunately, this
+ does not allow us to distinguish true sub-ranges from integer
+ types. So, instead we define integer (non-sub-range) types as
+ sub-ranges of themselves. */
+ dbxout_type_index (type);
}
if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST)
fprintf (asmfile, ";%d",
@@ -939,7 +990,18 @@ dbxout_type (type, full, show_arg_types)
type = integer_type_node;
else
{
- type = TYPE_MAIN_VARIANT (type);
+ /* Try to find the "main variant" with the same name but not const
+ or volatile. (Since stabs does not distinguish const and volatile,
+ there is no need to make them separate types. But types with
+ different names are usefully distinguished.) */
+
+ for (tem = TYPE_MAIN_VARIANT (type); tem; tem = TYPE_NEXT_VARIANT (tem))
+ if (!TYPE_READONLY (tem) && !TYPE_VOLATILE (tem)
+ && TYPE_NAME (tem) == TYPE_NAME (type))
+ {
+ type = tem;
+ break;
+ }
if (TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_DECL_SUPPRESS_DEBUG (TYPE_NAME (type)))
@@ -955,18 +1017,24 @@ dbxout_type (type, full, show_arg_types)
if (next_type_number == typevec_len)
{
- typevec =
- (enum typestatus *) xrealloc (typevec,
- typevec_len * 2 * sizeof typevec[0]);
+ typevec
+ = (struct typeinfo *) xrealloc (typevec,
+ typevec_len * 2 * sizeof typevec[0]);
bzero ((char *) (typevec + typevec_len),
typevec_len * sizeof typevec[0]);
typevec_len *= 2;
}
+
+#ifdef DBX_USE_BINCL
+ typevec[TYPE_SYMTAB_ADDRESS (type)].file_number
+ = current_file->file_number;
+ typevec[TYPE_SYMTAB_ADDRESS (type)].type_number
+ = current_file->next_type_number++;
+#endif
}
/* Output the number of this type, to refer to it. */
- fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
- CHARS (3);
+ dbxout_type_index (type);
#ifdef DBX_TYPE_DEFINED
if (DBX_TYPE_DEFINED (type))
@@ -976,7 +1044,7 @@ dbxout_type (type, full, show_arg_types)
/* If this type's definition has been output or is now being output,
that is all. */
- switch (typevec[TYPE_SYMTAB_ADDRESS (type)])
+ switch (typevec[TYPE_SYMTAB_ADDRESS (type)].status)
{
case TYPE_UNSEEN:
break;
@@ -1014,7 +1082,7 @@ dbxout_type (type, full, show_arg_types)
/* No way in DBX fmt to describe a variable size. */
|| TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
- typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
+ typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
return;
}
#endif
@@ -1027,7 +1095,14 @@ dbxout_type (type, full, show_arg_types)
/* Mark it as defined, so that if it is self-referent
we will not get into an infinite recursion of definitions. */
- typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_DEFINED;
+ typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_DEFINED;
+
+ if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+ {
+ dbxout_type (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), 0, 0);
+ return;
+ }
switch (TREE_CODE (type))
{
@@ -1038,25 +1113,30 @@ dbxout_type (type, full, show_arg_types)
without saying what it is. The debugger will make it
a void type when the reference is seen, and nothing will
ever override that default. */
- fprintf (asmfile, "%d", TYPE_SYMTAB_ADDRESS (type));
- CHARS (3);
+ dbxout_type_index (type);
break;
case INTEGER_TYPE:
if (type == char_type_node && ! TREE_UNSIGNED (type))
- /* Output the type `char' as a subrange of itself!
- I don't understand this definition, just copied it
- from the output of pcc.
- This used to use `r2' explicitly and we used to
- take care to make sure that `char' was type number 2. */
- fprintf (asmfile, "r%d;0;127;", TYPE_SYMTAB_ADDRESS (type));
+ {
+ /* Output the type `char' as a subrange of itself!
+ I don't understand this definition, just copied it
+ from the output of pcc.
+ This used to use `r2' explicitly and we used to
+ take care to make sure that `char' was type number 2. */
+ fprintf (asmfile, "r");
+ dbxout_type_index (type);
+ fprintf (asmfile, ";0;127;");
+ }
else if (use_gnu_debug_info_extensions
&& (TYPE_PRECISION (type) > TYPE_PRECISION (integer_type_node)
|| TYPE_PRECISION (type) > HOST_BITS_PER_WIDE_INT))
{
/* This used to say `r1' and we used to take care
to make sure that `int' was type number 1. */
- fprintf (asmfile, "r%d;", TYPE_SYMTAB_ADDRESS (integer_type_node));
+ fprintf (asmfile, "r");
+ dbxout_type_index (integer_type_node);
+ fprintf (asmfile, ";");
print_int_cst_octal (TYPE_MIN_VALUE (type));
fprintf (asmfile, ";");
print_int_cst_octal (TYPE_MAX_VALUE (type));
@@ -1064,15 +1144,16 @@ dbxout_type (type, full, show_arg_types)
}
else /* Output other integer types as subranges of `int'. */
dbxout_range_type (type);
- CHARS (25);
+ CHARS (22);
break;
case REAL_TYPE:
/* This used to say `r1' and we used to take care
to make sure that `int' was type number 1. */
- fprintf (asmfile, "r%d;%d;0;", TYPE_SYMTAB_ADDRESS (integer_type_node),
- int_size_in_bytes (type));
- CHARS (16);
+ fprintf (asmfile, "r");
+ dbxout_type_index (integer_type_node);
+ fprintf (asmfile, ";%d;0;", int_size_in_bytes (type));
+ CHARS (13);
break;
case CHAR_TYPE:
@@ -1080,10 +1161,13 @@ dbxout_type (type, full, show_arg_types)
fprintf (asmfile, "@s%d;-20;",
BITS_PER_UNIT * int_size_in_bytes (type));
else
- /* Output the type `char' as a subrange of itself.
- That is what pcc seems to do. */
- fprintf (asmfile, "r%d;0;%d;", TYPE_SYMTAB_ADDRESS (char_type_node),
- TREE_UNSIGNED (type) ? 255 : 127);
+ {
+ /* Output the type `char' as a subrange of itself.
+ That is what pcc seems to do. */
+ fprintf (asmfile, "r");
+ dbxout_type_index (char_type_node);
+ fprintf (asmfile, ";0;%d;", TREE_UNSIGNED (type) ? 255 : 127);
+ }
CHARS (9);
break;
@@ -1107,10 +1191,11 @@ dbxout_type (type, full, show_arg_types)
if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
{
- fprintf (asmfile, "r%d;%d;0;",
- TYPE_SYMTAB_ADDRESS (type),
+ fprintf (asmfile, "r");
+ dbxout_type_index (type);
+ fprintf (asmfile, ";%d;0;",
int_size_in_bytes (TREE_TYPE (type)));
- CHARS (15); /* The number is probably incorrect here. */
+ CHARS (12); /* The number is probably incorrect here. */
}
else
{
@@ -1141,7 +1226,7 @@ dbxout_type (type, full, show_arg_types)
fprintf (asmfile, "@s%d;",
BITS_PER_UNIT * int_size_in_bytes (type));
/* Check if a bitstring type, which in Chill is
- different from a [power]set. */
+ different from a [power]set. */
if (TYPE_STRING_FLAG (type))
fprintf (asmfile, "@S;");
}
@@ -1156,7 +1241,7 @@ dbxout_type (type, full, show_arg_types)
followed by a reference to the target-type.
ar1;0;N;M for a C array of type M and size N+1. */
/* Check if a character string type, which in Chill is
- different from an array of characters. */
+ different from an array of characters. */
if (TYPE_STRING_FLAG (type) && use_gnu_debug_info_extensions)
{
have_used_extensions = 1;
@@ -1164,14 +1249,17 @@ dbxout_type (type, full, show_arg_types)
}
tem = TYPE_DOMAIN (type);
if (tem == NULL)
- fprintf (asmfile, "ar%d;0;-1;",
- TYPE_SYMTAB_ADDRESS (integer_type_node));
+ {
+ fprintf (asmfile, "ar");
+ dbxout_type_index (integer_type_node);
+ fprintf (asmfile, ";0;-1;");
+ }
else
{
fprintf (asmfile, "a");
dbxout_range_type (tem);
}
- CHARS (17);
+ CHARS (14);
dbxout_type (TREE_TYPE (type), 0, 0);
break;
@@ -1215,7 +1303,7 @@ dbxout_type (type, full, show_arg_types)
else
fprintf (asmfile, "$$%d", anonymous_type_number++);
fprintf (asmfile, ":");
- typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
+ typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
break;
}
@@ -1312,7 +1400,7 @@ dbxout_type (type, full, show_arg_types)
fprintf (asmfile, "xe");
CHARS (3);
dbxout_type_name (type);
- typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF;
+ typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
fprintf (asmfile, ":");
return;
}
@@ -1363,6 +1451,7 @@ dbxout_type (type, full, show_arg_types)
/* Normally, just output the return type.
The argument types are encoded in the method name. */
putc ('#', asmfile);
+ CHARS (1);
dbxout_type (TREE_TYPE (type), 0, 0);
putc (';', asmfile);
CHARS (1);
@@ -1593,7 +1682,7 @@ dbxout_symbol (decl, local)
/* If this typedef name was defined by outputting the type,
don't duplicate it. */
- if (typevec[TYPE_SYMTAB_ADDRESS (type)] == TYPE_DEFINED
+ if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED
&& TYPE_NAME (TREE_TYPE (decl)) == decl)
return;
#endif
@@ -1625,10 +1714,7 @@ dbxout_symbol (decl, local)
&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
- && (!strcmp (lang_identify (), "cplusplus")
- /* The following line maybe unnecessary;
- in 2.6, try removing it. */
- || DECL_SOURCE_LINE (decl) == 0))
+ && DECL_ARTIFICIAL (decl))
{
tree name = TYPE_NAME (type);
if (TREE_CODE (name) == TYPE_DECL)
@@ -1653,7 +1739,10 @@ dbxout_symbol (decl, local)
if ((TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE
|| TREE_CODE (type) == QUAL_UNION_TYPE)
- && TYPE_NAME (type) == decl)
+ && TYPE_NAME (type) == decl
+ /* Distinguish the implicit typedefs of C++
+ from explicit ones that might be found in C. */
+ && DECL_ARTIFICIAL (decl))
{
if (use_gnu_debug_info_extensions && have_used_extensions)
{
@@ -1774,13 +1863,17 @@ dbxout_symbol (decl, local)
/* else it is something we handle like a normal variable. */
}
- DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
+ DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX, 0);
#ifdef LEAF_REG_REMAP
if (leaf_function)
leaf_renumber_regs_insn (DECL_RTL (decl));
#endif
dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
+ break;
+
+ default:
+ break;
}
}
@@ -2086,8 +2179,8 @@ dbxout_parms (parms)
/* Perform any necessary register eliminations on the parameter's rtl,
so that the debugging output will be accurate. */
DECL_INCOMING_RTL (parms)
- = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
- DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
+ = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX, 0);
+ DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX, 0);
#ifdef LEAF_REG_REMAP
if (leaf_function)
{
@@ -2514,5 +2607,13 @@ dbxout_function (decl)
#ifdef DBX_OUTPUT_FUNCTION_END
DBX_OUTPUT_FUNCTION_END (asmfile, decl);
#endif
+#if defined(ASM_OUTPUT_SECTION_NAME)
+ if (use_gnu_debug_info_extensions
+#if defined(NO_DBX_FUNCTION_END)
+ && ! NO_DBX_FUNCTION_END
+#endif
+ )
+ dbxout_function_end ();
+#endif
}
#endif /* DBX_DEBUGGING_INFO */
diff --git a/gnu/usr.bin/gcc/defaults.h b/gnu/usr.bin/gcc/defaults.h
index 27d4f3f9e56..434d761afed 100644
--- a/gnu/usr.bin/gcc/defaults.h
+++ b/gnu/usr.bin/gcc/defaults.h
@@ -1,10 +1,8 @@
/* Definitions of various defaults for how to do assembler output
(most of which are designed to be appropriate for GAS or for
some BSD assembler).
-
- Written by Ron Guilmette (rfg@netcom.com)
-
-Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1996 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.com)
This file is part of GNU CC.
@@ -56,19 +54,6 @@ do { fprintf (FILE, "\t%s\t", ASM_LONG); \
} while (0)
#endif
-/* This is how to output an element of a case-vector that is relative.
- Some targets don't use this, but we have to define it anyway. */
-
-#ifndef ASM_OUTPUT_ADDR_DIFF_ELT
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \
-do { fprintf (FILE, "\t%s\t", ASM_SHORT); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "L", (VALUE)); \
- fputc ('-', FILE); \
- ASM_OUTPUT_INTERNAL_LABEL (FILE, "L", (REL)); \
- fputc ('\n', FILE); \
- } while (0)
-#endif
-
/* choose a reasonable default for ASM_OUTPUT_ASCII. */
#ifndef ASM_OUTPUT_ASCII
@@ -133,6 +118,13 @@ do { fprintf (FILE, "\t%s\t", ASM_SHORT); \
#endif
#endif
+/* This is how to output a reference to a user-level label named NAME. */
+
+#ifndef ASM_OUTPUT_LABELREF
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ do { fputs (USER_LABEL_PREFIX, FILE); fputs (NAME, FILE); } while (0)
+#endif
+
/* This determines whether or not we support weak symbols. */
#ifndef SUPPORTS_WEAK
#ifdef ASM_WEAKEN_LABEL
@@ -141,3 +133,9 @@ do { fprintf (FILE, "\t%s\t", ASM_SHORT); \
#define SUPPORTS_WEAK 0
#endif
#endif
+
+/* If we have a definition of INCOMING_RETURN_ADDR_RTX, assume that
+ the rest of the DWARF 2 frame unwind support is also provided. */
+#if !defined (DWARF2_UNWIND_INFO) && defined (INCOMING_RETURN_ADDR_RTX)
+#define DWARF2_UNWIND_INFO 1
+#endif
diff --git a/gnu/usr.bin/gcc/demangle.h b/gnu/usr.bin/gcc/demangle.h
index 8dcd5fd06a6..00f6a0c3bc0 100644
--- a/gnu/usr.bin/gcc/demangle.h
+++ b/gnu/usr.bin/gcc/demangle.h
@@ -1,5 +1,5 @@
/* Defs for interface to demanglers.
- Copyright 1992, 1995 Free Software Foundation, Inc.
+ Copyright 1992, 1995, 1996 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -21,27 +21,8 @@
#define DEMANGLE_H
#ifdef IN_GCC
-
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
+#include "gansidecl.h"
#define PARAMS(ARGS) PROTO(ARGS)
-
-#ifdef __STDC__
-#define PTR void *
-#else
-#ifndef const
-#define const
-#endif
-#define PTR char *
-#endif
-
#else /* ! IN_GCC */
#include <ansidecl.h>
#endif /* IN_GCC */
@@ -51,6 +32,7 @@
#define DMGL_NO_OPTS 0 /* For readability... */
#define DMGL_PARAMS (1 << 0) /* Include function args */
#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
+#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */
#define DMGL_AUTO (1 << 8)
#define DMGL_GNU (1 << 9)
@@ -95,10 +77,10 @@ extern char *
cplus_demangle PARAMS ((const char *mangled, int options));
extern int
-cplus_demangle_opname PARAMS ((char *opname, char *result, int options));
+cplus_demangle_opname PARAMS ((const char *opname, char *result, int options));
-extern char *
-cplus_mangle_opname PARAMS ((char *opname, int options));
+extern const char *
+cplus_mangle_opname PARAMS ((const char *opname, int options));
/* Note: This sets global state. FIXME if you care about multi-threading. */
diff --git a/gnu/usr.bin/gcc/doschk.c b/gnu/usr.bin/gcc/doschk.c
index 7fbb7334dc1..ad553df7e8c 100644
--- a/gnu/usr.bin/gcc/doschk.c
+++ b/gnu/usr.bin/gcc/doschk.c
@@ -251,8 +251,8 @@ display_problems ()
first_err = 1;
for (i=0; i<ecount-1; i++)
{
- if ((strcmp (elist[i]->dos_name, elist[i+1]->dos_name) == 0) &&
- (strcmp (elist[i]->path, elist[i+1]->path) == 0))
+ if ((strcmp (elist[i]->dos_name, elist[i+1]->dos_name) == 0)
+ && (strcmp (elist[i]->path, elist[i+1]->path) == 0))
{
if (first_err)
{
@@ -280,8 +280,8 @@ display_problems ()
first_err = 1;
for (i=0; i<ecount-1; i++)
{
- if ((strncmp (elist[i]->full_name, elist[i+1]->full_name, 14) == 0) &&
- (strcmp (elist[i]->path, elist[i+1]->path) == 0))
+ if ((strncmp (elist[i]->full_name, elist[i+1]->full_name, 14) == 0)
+ && (strcmp (elist[i]->path, elist[i+1]->path) == 0))
{
if (first_err)
{
diff --git a/gnu/usr.bin/gcc/dwarf.h b/gnu/usr.bin/gcc/dwarf.h
index 014a4fc48b8..6aca017e6e5 100644
--- a/gnu/usr.bin/gcc/dwarf.h
+++ b/gnu/usr.bin/gcc/dwarf.h
@@ -180,7 +180,11 @@ enum dwarf_location_atom {
OP_CONST = 0x04,
OP_DEREF2 = 0x05,
OP_DEREF4 = 0x06,
- OP_ADD = 0x07
+ OP_ADD = 0x07,
+
+ /* GNU extensions. */
+
+ OP_MULT = 0x80
};
#define OP_LO_USER 0x80 /* implementation-defined range start */
diff --git a/gnu/usr.bin/gcc/dwarfout.c b/gnu/usr.bin/gcc/dwarfout.c
index b484e5a9eb2..7f42d061ab1 100644
--- a/gnu/usr.bin/gcc/dwarfout.c
+++ b/gnu/usr.bin/gcc/dwarfout.c
@@ -1,9 +1,6 @@
/* Output Dwarf format symbol table information from the GNU C compiler.
- Copyright (C) 1992, 1993, 1995 Free Software Foundation, Inc.
-
- Written by Ron Guilmette (rfg@netcom.com) for
- Network Computing Devices, August, September, October, November 1990.
- Generously contributed by NCD to the Free Software Foundation.
+ Copyright (C) 1992, 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Ron Guilmette (rfg@monkeys.com) of Network Computing Devices.
This file is part of GNU CC.
@@ -36,13 +33,6 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "defaults.h"
-#ifndef DWARF_VERSION
-#define DWARF_VERSION 1
-#endif
-
-/* #define NDEBUG 1 */
-#include "assert.h"
-
#if defined(DWARF_TIMESTAMPS)
#if defined(POSIX)
#include <time.h>
@@ -56,10 +46,36 @@ extern time_t time ();
#endif /* !defined(POSIX) */
#endif /* defined(DWARF_TIMESTAMPS) */
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+/* We cannot use <assert.h> in GCC source, since that would include
+ GCC's assert.h, which may not be compatible with the host compiler. */
+#undef assert
+#ifdef NDEBUG
+# define assert(e)
+#else
+# define assert(e) do { if (! (e)) abort (); } while (0)
+#endif
+
extern char *getpwd ();
+#ifdef NEED_DECLARATION_INDEX
extern char *index ();
+#endif
+
+#ifdef NEED_DECLARATION_RINDEX
extern char *rindex ();
+#endif
/* IMPORTANT NOTE: Please see the file README.DWARF for important details
regarding the GNU implementation of Dwarf. */
@@ -72,10 +88,8 @@ extern char *rindex ();
/* Note that the implementation of C++ support herein is (as yet) unfinished.
If you want to try to complete it, more power to you. */
-#if defined(__GNUC__) && (NDEBUG == 1)
-#define inline static inline
-#else
-#define inline static
+#if !defined(__GNUC__) || (NDEBUG != 1)
+#define inline
#endif
/* How to start an assembler comment. */
@@ -106,6 +120,21 @@ extern char *rindex ();
#define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0)
+/* Define a macro which returns non-zero for a TYPE_DECL which was
+ implicitly generated for a tagged type.
+
+ Note that unlike the gcc front end (which generates a NULL named
+ TYPE_DECL node for each complete tagged type, each array type, and
+ each function type node created) the g++ front end generates a
+ _named_ TYPE_DECL node for each tagged type node created.
+ These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
+ generate a DW_TAG_typedef DIE for them. */
+#define TYPE_DECL_IS_STUB(decl) \
+ (DECL_NAME (decl) == NULL \
+ || (DECL_ARTIFICIAL (decl) \
+ && is_tagged_type (TREE_TYPE (decl)) \
+ && decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
+
extern int flag_traditional;
extern char *version_string;
extern char *language_string;
@@ -168,7 +197,7 @@ struct filename_entry {
typedef struct filename_entry filename_entry;
-/* Pointer to an array of elements, each one having the structure above. */
+/* Pointer to an array of elements, each one having the structure above. */
static filename_entry *filename_table;
@@ -207,7 +236,7 @@ static char *last_filename;
static unsigned next_block_number = 2;
-/* Counter to generate unique names for DIEs. */
+/* Counter to generate unique names for DIEs. */
static unsigned next_unused_dienum = 1;
@@ -293,13 +322,128 @@ static unsigned current_funcdef_number = 1;
static tree dwarf_last_decl;
+/* A flag indicating that we are emitting the member declarations of a
+ class, so member functions and variables should not be entirely emitted.
+ This is a kludge to avoid passing a second argument to output_*_die. */
+
+static int in_class;
+
/* Forward declarations for functions defined in this file. */
-static void output_type ();
-static void type_attribute ();
-static void output_decls_for_scope ();
-static void output_decl ();
-static unsigned lookup_filename ();
+static char *dwarf_tag_name PROTO((unsigned));
+static char *dwarf_attr_name PROTO((unsigned));
+static char *dwarf_stack_op_name PROTO((unsigned));
+static char *dwarf_typemod_name PROTO((unsigned));
+static char *dwarf_fmt_byte_name PROTO((unsigned));
+static char *dwarf_fund_type_name PROTO((unsigned));
+static tree decl_ultimate_origin PROTO((tree));
+static tree block_ultimate_origin PROTO((tree));
+static void output_unsigned_leb128 PROTO((unsigned long));
+static void output_signed_leb128 PROTO((long));
+static inline int is_body_block PROTO((tree));
+static int fundamental_type_code PROTO((tree));
+static tree root_type_1 PROTO((tree, int));
+static tree root_type PROTO((tree));
+static void write_modifier_bytes_1 PROTO((tree, int, int, int));
+static void write_modifier_bytes PROTO((tree, int, int));
+static inline int type_is_fundamental PROTO((tree));
+static void equate_decl_number_to_die_number PROTO((tree));
+static inline void equate_type_number_to_die_number PROTO((tree));
+static void output_reg_number PROTO((rtx));
+static void output_mem_loc_descriptor PROTO((rtx));
+static void output_loc_descriptor PROTO((rtx));
+static void output_bound_representation PROTO((tree, unsigned, int));
+static void output_enumeral_list PROTO((tree));
+static inline unsigned ceiling PROTO((unsigned, unsigned));
+static inline tree field_type PROTO((tree));
+static inline unsigned simple_type_align_in_bits PROTO((tree));
+static inline unsigned simple_type_size_in_bits PROTO((tree));
+static unsigned field_byte_offset PROTO((tree));
+static inline void sibling_attribute PROTO((void));
+static void location_attribute PROTO((rtx));
+static void data_member_location_attribute PROTO((tree));
+static void const_value_attribute PROTO((rtx));
+static void location_or_const_value_attribute PROTO((tree));
+static inline void name_attribute PROTO((char *));
+static inline void fund_type_attribute PROTO((unsigned));
+static void mod_fund_type_attribute PROTO((tree, int, int));
+static inline void user_def_type_attribute PROTO((tree));
+static void mod_u_d_type_attribute PROTO((tree, int, int));
+static inline void ordering_attribute PROTO((unsigned));
+static void subscript_data_attribute PROTO((tree));
+static void byte_size_attribute PROTO((tree));
+static inline void bit_offset_attribute PROTO((tree));
+static inline void bit_size_attribute PROTO((tree));
+static inline void element_list_attribute PROTO((tree));
+static inline void stmt_list_attribute PROTO((char *));
+static inline void low_pc_attribute PROTO((char *));
+static inline void high_pc_attribute PROTO((char *));
+static inline void body_begin_attribute PROTO((char *));
+static inline void body_end_attribute PROTO((char *));
+static inline void language_attribute PROTO((unsigned));
+static inline void member_attribute PROTO((tree));
+static inline void string_length_attribute PROTO((tree));
+static inline void comp_dir_attribute PROTO((char *));
+static inline void sf_names_attribute PROTO((char *));
+static inline void src_info_attribute PROTO((char *));
+static inline void mac_info_attribute PROTO((char *));
+static inline void prototyped_attribute PROTO((tree));
+static inline void producer_attribute PROTO((char *));
+static inline void inline_attribute PROTO((tree));
+static inline void containing_type_attribute PROTO((tree));
+static inline void abstract_origin_attribute PROTO((tree));
+static inline void src_coords_attribute PROTO((unsigned, unsigned));
+static inline void pure_or_virtual_attribute PROTO((tree));
+static void name_and_src_coords_attributes PROTO((tree));
+static void type_attribute PROTO((tree, int, int));
+static char *type_tag PROTO((tree));
+static inline void dienum_push PROTO((void));
+static inline void dienum_pop PROTO((void));
+static inline tree member_declared_type PROTO((tree));
+static char *function_start_label PROTO((tree));
+static void output_array_type_die PROTO((void *));
+static void output_set_type_die PROTO((void *));
+static void output_entry_point_die PROTO((void *));
+static void output_inlined_enumeration_type_die PROTO((void *));
+static void output_inlined_structure_type_die PROTO((void *));
+static void output_inlined_union_type_die PROTO((void *));
+static void output_enumeration_type_die PROTO((void *));
+static void output_formal_parameter_die PROTO((void *));
+static void output_global_subroutine_die PROTO((void *));
+static void output_global_variable_die PROTO((void *));
+static void output_label_die PROTO((void *));
+static void output_lexical_block_die PROTO((void *));
+static void output_inlined_subroutine_die PROTO((void *));
+static void output_local_variable_die PROTO((void *));
+static void output_member_die PROTO((void *));
+static void output_pointer_type_die PROTO((void *));
+static void output_reference_type_die PROTO((void *));
+static void output_ptr_to_mbr_type_die PROTO((void *));
+static void output_compile_unit_die PROTO((void *));
+static void output_string_type_die PROTO((void *));
+static void output_structure_type_die PROTO((void *));
+static void output_local_subroutine_die PROTO((void *));
+static void output_subroutine_type_die PROTO((void *));
+static void output_typedef_die PROTO((void *));
+static void output_union_type_die PROTO((void *));
+static void output_unspecified_parameters_die PROTO((void *));
+static void output_padded_null_die PROTO((void *));
+static void output_die PROTO((void (*) (), void *));
+static void end_sibling_chain PROTO((void));
+static void output_formal_types PROTO((tree));
+static void pend_type PROTO((tree));
+static inline int type_of_for_scope PROTO((tree, tree));
+static void output_pending_types_for_scope PROTO((tree));
+static void output_type PROTO((tree, tree));
+static void output_tagged_type_instantiation PROTO((tree));
+static void output_block PROTO((tree, int));
+static void output_decls_for_scope PROTO((tree, int));
+static void output_decl PROTO((tree, tree));
+static void shuffle_filename_entry PROTO((filename_entry *));
+static void generate_new_sfname_entry PROTO((void));
+static unsigned lookup_filename PROTO((char *));
+static void generate_srcinfo_entry PROTO((unsigned, unsigned));
+static void generate_macinfo_entry PROTO((char *, char *));
/* Definitions of defaults for assembler-dependent names of various
pseudo-ops and section names.
@@ -410,153 +554,153 @@ static unsigned lookup_filename ();
*/
#ifndef TEXT_BEGIN_LABEL
-#define TEXT_BEGIN_LABEL ".L_text_b"
+#define TEXT_BEGIN_LABEL "*.L_text_b"
#endif
#ifndef TEXT_END_LABEL
-#define TEXT_END_LABEL ".L_text_e"
+#define TEXT_END_LABEL "*.L_text_e"
#endif
#ifndef DATA_BEGIN_LABEL
-#define DATA_BEGIN_LABEL ".L_data_b"
+#define DATA_BEGIN_LABEL "*.L_data_b"
#endif
#ifndef DATA_END_LABEL
-#define DATA_END_LABEL ".L_data_e"
+#define DATA_END_LABEL "*.L_data_e"
#endif
#ifndef DATA1_BEGIN_LABEL
-#define DATA1_BEGIN_LABEL ".L_data1_b"
+#define DATA1_BEGIN_LABEL "*.L_data1_b"
#endif
#ifndef DATA1_END_LABEL
-#define DATA1_END_LABEL ".L_data1_e"
+#define DATA1_END_LABEL "*.L_data1_e"
#endif
#ifndef RODATA_BEGIN_LABEL
-#define RODATA_BEGIN_LABEL ".L_rodata_b"
+#define RODATA_BEGIN_LABEL "*.L_rodata_b"
#endif
#ifndef RODATA_END_LABEL
-#define RODATA_END_LABEL ".L_rodata_e"
+#define RODATA_END_LABEL "*.L_rodata_e"
#endif
#ifndef RODATA1_BEGIN_LABEL
-#define RODATA1_BEGIN_LABEL ".L_rodata1_b"
+#define RODATA1_BEGIN_LABEL "*.L_rodata1_b"
#endif
#ifndef RODATA1_END_LABEL
-#define RODATA1_END_LABEL ".L_rodata1_e"
+#define RODATA1_END_LABEL "*.L_rodata1_e"
#endif
#ifndef BSS_BEGIN_LABEL
-#define BSS_BEGIN_LABEL ".L_bss_b"
+#define BSS_BEGIN_LABEL "*.L_bss_b"
#endif
#ifndef BSS_END_LABEL
-#define BSS_END_LABEL ".L_bss_e"
+#define BSS_END_LABEL "*.L_bss_e"
#endif
#ifndef LINE_BEGIN_LABEL
-#define LINE_BEGIN_LABEL ".L_line_b"
+#define LINE_BEGIN_LABEL "*.L_line_b"
#endif
#ifndef LINE_LAST_ENTRY_LABEL
-#define LINE_LAST_ENTRY_LABEL ".L_line_last"
+#define LINE_LAST_ENTRY_LABEL "*.L_line_last"
#endif
#ifndef LINE_END_LABEL
-#define LINE_END_LABEL ".L_line_e"
+#define LINE_END_LABEL "*.L_line_e"
#endif
#ifndef DEBUG_BEGIN_LABEL
-#define DEBUG_BEGIN_LABEL ".L_debug_b"
+#define DEBUG_BEGIN_LABEL "*.L_debug_b"
#endif
#ifndef SFNAMES_BEGIN_LABEL
-#define SFNAMES_BEGIN_LABEL ".L_sfnames_b"
+#define SFNAMES_BEGIN_LABEL "*.L_sfnames_b"
#endif
#ifndef SRCINFO_BEGIN_LABEL
-#define SRCINFO_BEGIN_LABEL ".L_srcinfo_b"
+#define SRCINFO_BEGIN_LABEL "*.L_srcinfo_b"
#endif
#ifndef MACINFO_BEGIN_LABEL
-#define MACINFO_BEGIN_LABEL ".L_macinfo_b"
+#define MACINFO_BEGIN_LABEL "*.L_macinfo_b"
#endif
#ifndef DIE_BEGIN_LABEL_FMT
-#define DIE_BEGIN_LABEL_FMT ".L_D%u"
+#define DIE_BEGIN_LABEL_FMT "*.L_D%u"
#endif
#ifndef DIE_END_LABEL_FMT
-#define DIE_END_LABEL_FMT ".L_D%u_e"
+#define DIE_END_LABEL_FMT "*.L_D%u_e"
#endif
#ifndef PUB_DIE_LABEL_FMT
-#define PUB_DIE_LABEL_FMT ".L_P%u"
+#define PUB_DIE_LABEL_FMT "*.L_P%u"
#endif
#ifndef INSN_LABEL_FMT
-#define INSN_LABEL_FMT ".L_I%u_%u"
+#define INSN_LABEL_FMT "*.L_I%u_%u"
#endif
#ifndef BLOCK_BEGIN_LABEL_FMT
-#define BLOCK_BEGIN_LABEL_FMT ".L_B%u"
+#define BLOCK_BEGIN_LABEL_FMT "*.L_B%u"
#endif
#ifndef BLOCK_END_LABEL_FMT
-#define BLOCK_END_LABEL_FMT ".L_B%u_e"
+#define BLOCK_END_LABEL_FMT "*.L_B%u_e"
#endif
#ifndef SS_BEGIN_LABEL_FMT
-#define SS_BEGIN_LABEL_FMT ".L_s%u"
+#define SS_BEGIN_LABEL_FMT "*.L_s%u"
#endif
#ifndef SS_END_LABEL_FMT
-#define SS_END_LABEL_FMT ".L_s%u_e"
+#define SS_END_LABEL_FMT "*.L_s%u_e"
#endif
#ifndef EE_BEGIN_LABEL_FMT
-#define EE_BEGIN_LABEL_FMT ".L_e%u"
+#define EE_BEGIN_LABEL_FMT "*.L_e%u"
#endif
#ifndef EE_END_LABEL_FMT
-#define EE_END_LABEL_FMT ".L_e%u_e"
+#define EE_END_LABEL_FMT "*.L_e%u_e"
#endif
#ifndef MT_BEGIN_LABEL_FMT
-#define MT_BEGIN_LABEL_FMT ".L_t%u"
+#define MT_BEGIN_LABEL_FMT "*.L_t%u"
#endif
#ifndef MT_END_LABEL_FMT
-#define MT_END_LABEL_FMT ".L_t%u_e"
+#define MT_END_LABEL_FMT "*.L_t%u_e"
#endif
#ifndef LOC_BEGIN_LABEL_FMT
-#define LOC_BEGIN_LABEL_FMT ".L_l%u"
+#define LOC_BEGIN_LABEL_FMT "*.L_l%u"
#endif
#ifndef LOC_END_LABEL_FMT
-#define LOC_END_LABEL_FMT ".L_l%u_e"
+#define LOC_END_LABEL_FMT "*.L_l%u_e"
#endif
#ifndef BOUND_BEGIN_LABEL_FMT
-#define BOUND_BEGIN_LABEL_FMT ".L_b%u_%u_%c"
+#define BOUND_BEGIN_LABEL_FMT "*.L_b%u_%u_%c"
#endif
#ifndef BOUND_END_LABEL_FMT
-#define BOUND_END_LABEL_FMT ".L_b%u_%u_%c_e"
+#define BOUND_END_LABEL_FMT "*.L_b%u_%u_%c_e"
#endif
#ifndef DERIV_BEGIN_LABEL_FMT
-#define DERIV_BEGIN_LABEL_FMT ".L_d%u"
+#define DERIV_BEGIN_LABEL_FMT "*.L_d%u"
#endif
#ifndef DERIV_END_LABEL_FMT
-#define DERIV_END_LABEL_FMT ".L_d%u_e"
+#define DERIV_END_LABEL_FMT "*.L_d%u_e"
#endif
#ifndef SL_BEGIN_LABEL_FMT
-#define SL_BEGIN_LABEL_FMT ".L_sl%u"
+#define SL_BEGIN_LABEL_FMT "*.L_sl%u"
#endif
#ifndef SL_END_LABEL_FMT
-#define SL_END_LABEL_FMT ".L_sl%u_e"
+#define SL_END_LABEL_FMT "*.L_sl%u_e"
#endif
#ifndef BODY_BEGIN_LABEL_FMT
-#define BODY_BEGIN_LABEL_FMT ".L_b%u"
+#define BODY_BEGIN_LABEL_FMT "*.L_b%u"
#endif
#ifndef BODY_END_LABEL_FMT
-#define BODY_END_LABEL_FMT ".L_b%u_e"
+#define BODY_END_LABEL_FMT "*.L_b%u_e"
#endif
#ifndef FUNC_END_LABEL_FMT
-#define FUNC_END_LABEL_FMT ".L_f%u_e"
+#define FUNC_END_LABEL_FMT "*.L_f%u_e"
#endif
#ifndef TYPE_NAME_FMT
-#define TYPE_NAME_FMT ".L_T%u"
+#define TYPE_NAME_FMT "*.L_T%u"
#endif
#ifndef DECL_NAME_FMT
-#define DECL_NAME_FMT ".L_E%u"
+#define DECL_NAME_FMT "*.L_E%u"
#endif
#ifndef LINE_CODE_LABEL_FMT
-#define LINE_CODE_LABEL_FMT ".L_LC%u"
+#define LINE_CODE_LABEL_FMT "*.L_LC%u"
#endif
#ifndef SFNAMES_ENTRY_LABEL_FMT
-#define SFNAMES_ENTRY_LABEL_FMT ".L_F%u"
+#define SFNAMES_ENTRY_LABEL_FMT "*.L_F%u"
#endif
#ifndef LINE_ENTRY_LABEL_FMT
-#define LINE_ENTRY_LABEL_FMT ".L_LE%u"
+#define LINE_ENTRY_LABEL_FMT "*.L_LE%u"
#endif
/* Definitions of defaults for various types of primitive assembly language
@@ -575,14 +719,6 @@ static unsigned lookup_filename ();
fprintf ((FILE), "\t%s\n", POPSECTION_ASM_OP)
#endif
-#ifndef ASM_OUTPUT_SOURCE_FILENAME
-#define ASM_OUTPUT_SOURCE_FILENAME(FILE,NAME) \
- do { fprintf (FILE, "\t%s\t", FILE_ASM_OP); \
- output_quoted_string (FILE, NAME); \
- fputc ('\n', FILE); \
- } while (0)
-#endif
-
#ifndef ASM_OUTPUT_DWARF_DELTA2
#define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2) \
do { fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP); \
@@ -608,7 +744,7 @@ static unsigned lookup_filename ();
do { \
fprintf ((FILE), "\t%s\t0x%x", \
UNALIGNED_SHORT_ASM_OP, (unsigned) TAG); \
- if (flag_verbose_asm) \
+ if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_tag_name (TAG)); \
fputc ('\n', (FILE)); \
@@ -620,7 +756,7 @@ static unsigned lookup_filename ();
do { \
fprintf ((FILE), "\t%s\t0x%x", \
UNALIGNED_SHORT_ASM_OP, (unsigned) ATTR); \
- if (flag_verbose_asm) \
+ if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_attr_name (ATTR)); \
fputc ('\n', (FILE)); \
@@ -631,7 +767,7 @@ static unsigned lookup_filename ();
#define ASM_OUTPUT_DWARF_STACK_OP(FILE,OP) \
do { \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) OP); \
- if (flag_verbose_asm) \
+ if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_stack_op_name (OP)); \
fputc ('\n', (FILE)); \
@@ -643,7 +779,7 @@ static unsigned lookup_filename ();
do { \
fprintf ((FILE), "\t%s\t0x%x", \
UNALIGNED_SHORT_ASM_OP, (unsigned) FT); \
- if (flag_verbose_asm) \
+ if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_fund_type_name (FT)); \
fputc ('\n', (FILE)); \
@@ -654,7 +790,7 @@ static unsigned lookup_filename ();
#define ASM_OUTPUT_DWARF_FMT_BYTE(FILE,FMT) \
do { \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) FMT); \
- if (flag_verbose_asm) \
+ if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_fmt_byte_name (FMT)); \
fputc ('\n', (FILE)); \
@@ -665,7 +801,7 @@ static unsigned lookup_filename ();
#define ASM_OUTPUT_DWARF_TYPE_MODIFIER(FILE,MOD) \
do { \
fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) MOD); \
- if (flag_verbose_asm) \
+ if (flag_debug_asm) \
fprintf ((FILE), "\t%s %s", \
ASM_COMMENT_START, dwarf_typemod_name (MOD)); \
fputc ('\n', (FILE)); \
@@ -735,16 +871,6 @@ static unsigned lookup_filename ();
/************************ general utility functions **************************/
-inline char *
-xstrdup (s)
- register char *s;
-{
- register char *p = (char *) xmalloc (strlen (s) + 1);
-
- strcpy (p, s);
- return p;
-}
-
inline int
is_pseudo_reg (rtl)
register rtx rtl;
@@ -963,6 +1089,7 @@ dwarf_fmt_byte_name (fmt)
default: return "FMT_<unknown>";
}
}
+
static char *
dwarf_fund_type_name (ft)
register unsigned ft;
@@ -1009,7 +1136,7 @@ dwarf_fund_type_name (ft)
case FT_unsigned_int32: return "FT_unsigned_int32";
case FT_int64: return "FT_int64";
case FT_signed_int64: return "FT_signed_int64";
- case FT_unsigned_int64: return "FT_signed_int64";
+ case FT_unsigned_int64: return "FT_unsigned_int64";
case FT_real32: return "FT_real32";
case FT_real64: return "FT_real64";
@@ -1080,6 +1207,27 @@ block_ultimate_origin (block)
}
}
+/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT
+ of a virtual function may refer to a base class, so we check the 'this'
+ parameter. */
+
+static tree
+decl_class_context (decl)
+ tree decl;
+{
+ tree context = NULL_TREE;
+ if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
+ context = DECL_CONTEXT (decl);
+ else
+ context = TYPE_MAIN_VARIANT
+ (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
+
+ if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
+ context = NULL_TREE;
+
+ return context;
+}
+
static void
output_unsigned_leb128 (value)
register unsigned long value;
@@ -1094,7 +1242,7 @@ output_unsigned_leb128 (value)
if (value != 0) /* more bytes to follow */
byte |= 0x80;
fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
- if (flag_verbose_asm && value == 0)
+ if (flag_debug_asm && value == 0)
fprintf (asm_out_file, "\t%s ULEB128 number - value = %u",
ASM_COMMENT_START, orig_value);
fputc ('\n', asm_out_file);
@@ -1126,7 +1274,7 @@ output_signed_leb128 (value)
more = 1;
}
fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
- if (flag_verbose_asm && more == 0)
+ if (flag_debug_asm && more == 0)
fprintf (asm_out_file, "\t%s SLEB128 number - value = %d",
ASM_COMMENT_START, orig_value);
fputc ('\n', asm_out_file);
@@ -1148,7 +1296,7 @@ output_signed_leb128 (value)
FUNCTION_DECL node.
*/
-inline int
+static inline int
is_body_block (stmt)
register tree stmt;
{
@@ -1316,10 +1464,14 @@ fundamental_type_code (type)
qualifiers. */
static tree
-root_type (type)
+root_type_1 (type, count)
register tree type;
+ register int count;
{
- if (TREE_CODE (type) == ERROR_MARK)
+ /* Give up after searching 1000 levels, in case this is a recursive
+ pointer type. Such types are possible in Ada, but it is not possible
+ to represent them in DWARF1 debug info. */
+ if (count > 1000)
return error_mark_node;
switch (TREE_CODE (type))
@@ -1329,25 +1481,42 @@ root_type (type)
case POINTER_TYPE:
case REFERENCE_TYPE:
- return type_main_variant (root_type (TREE_TYPE (type)));
+ return root_type_1 (TREE_TYPE (type), count+1);
default:
- return type_main_variant (type);
+ return type;
}
}
+static tree
+root_type (type)
+ register tree type;
+{
+ type = root_type_1 (type, 0);
+ if (type != error_mark_node)
+ type = type_main_variant (type);
+ return type;
+}
+
/* Given a pointer to an arbitrary ..._TYPE tree node, write out a sequence
of zero or more Dwarf "type-modifier" bytes applicable to the type. */
static void
-write_modifier_bytes (type, decl_const, decl_volatile)
+write_modifier_bytes_1 (type, decl_const, decl_volatile, count)
register tree type;
register int decl_const;
register int decl_volatile;
+ register int count;
{
if (TREE_CODE (type) == ERROR_MARK)
return;
+ /* Give up after searching 1000 levels, in case this is a recursive
+ pointer type. Such types are possible in Ada, but it is not possible
+ to represent them in DWARF1 debug info. */
+ if (count > 1000)
+ return;
+
if (TYPE_READONLY (type) || decl_const)
ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_const);
if (TYPE_VOLATILE (type) || decl_volatile)
@@ -1356,12 +1525,12 @@ write_modifier_bytes (type, decl_const, decl_volatile)
{
case POINTER_TYPE:
ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_pointer_to);
- write_modifier_bytes (TREE_TYPE (type), 0, 0);
+ write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1);
return;
case REFERENCE_TYPE:
ASM_OUTPUT_DWARF_TYPE_MODIFIER (asm_out_file, MOD_reference_to);
- write_modifier_bytes (TREE_TYPE (type), 0, 0);
+ write_modifier_bytes_1 (TREE_TYPE (type), 0, 0, count+1);
return;
case ERROR_MARK:
@@ -1369,11 +1538,20 @@ write_modifier_bytes (type, decl_const, decl_volatile)
return;
}
}
+
+static void
+write_modifier_bytes (type, decl_const, decl_volatile)
+ register tree type;
+ register int decl_const;
+ register int decl_volatile;
+{
+ write_modifier_bytes_1 (type, decl_const, decl_volatile, 0);
+}
/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the
given input type is a Dwarf "fundamental" type. Otherwise return zero. */
-inline int
+static inline int
type_is_fundamental (type)
register tree type;
{
@@ -1454,7 +1632,7 @@ equate_decl_number_to_die_number (decl)
simply by re-generating the alternative name from the ..._TYPE node's
UID number. */
-inline void
+static inline void
equate_type_number_to_die_number (type)
register tree type;
{
@@ -1487,7 +1665,7 @@ output_reg_number (rtl)
}
fprintf (asm_out_file, "\t%s\t0x%x",
UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno));
- if (flag_verbose_asm)
+ if (flag_debug_asm)
{
fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
PRINT_REG (rtl, 0, asm_out_file);
@@ -1574,6 +1752,15 @@ output_mem_loc_descriptor (rtl)
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, INTVAL (rtl));
break;
+ case MULT:
+ /* If a pseudo-reg is optimized away, it is possible for it to
+ be replaced with a MEM containing a multiply. Use a GNU extension
+ to describe it. */
+ output_mem_loc_descriptor (XEXP (rtl, 0));
+ output_mem_loc_descriptor (XEXP (rtl, 1));
+ ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_MULT);
+ break;
+
default:
abort ();
}
@@ -1628,79 +1815,73 @@ output_bound_representation (bound, dim_num, u_or_l)
switch (TREE_CODE (bound))
{
- case ERROR_MARK:
- return;
+ case ERROR_MARK:
+ return;
/* All fixed-bounds are represented by INTEGER_CST nodes. */
- case INTEGER_CST:
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
- (unsigned) TREE_INT_CST_LOW (bound));
- break;
-
- /* Dynamic bounds may be represented by NOP_EXPR nodes containing
- SAVE_EXPR nodes. */
-
- case NOP_EXPR:
- bound = TREE_OPERAND (bound, 0);
- /* ... fall thru... */
-
- case SAVE_EXPR:
- {
- char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
- char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
- sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
- current_dienum, dim_num, u_or_l);
-
- sprintf (end_label, BOUND_END_LABEL_FMT,
- current_dienum, dim_num, u_or_l);
-
- ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
- ASM_OUTPUT_LABEL (asm_out_file, begin_label);
-
- /* If we are working on a bound for a dynamic dimension in C,
- the dynamic dimension in question had better have a static
- (zero) lower bound and a dynamic *upper* bound. */
+ case INTEGER_CST:
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+ (unsigned) TREE_INT_CST_LOW (bound));
+ break;
- if (u_or_l != 'u')
- abort ();
+ default:
- /* If optimization is turned on, the SAVE_EXPRs that describe
- how to access the upper bound values are essentially bogus.
- They only describe (at best) how to get at these values at
- the points in the generated code right after they have just
- been computed. Worse yet, in the typical case, the upper
- bound values will not even *be* computed in the optimized
- code, so these SAVE_EXPRs are entirely bogus.
-
- In order to compensate for this fact, we check here to see
- if optimization is enabled, and if so, we effectively create
- an empty location description for the (unknown and unknowable)
- upper bound.
-
- This should not cause too much trouble for existing (stupid?)
- debuggers because they have to deal with empty upper bounds
- location descriptions anyway in order to be able to deal with
- incomplete array types.
-
- Of course an intelligent debugger (GDB?) should be able to
- comprehend that a missing upper bound specification in a
- array type used for a storage class `auto' local array variable
- indicates that the upper bound is both unknown (at compile-
- time) and unknowable (at run-time) due to optimization.
- */
+ /* Dynamic bounds may be represented by NOP_EXPR nodes containing
+ SAVE_EXPR nodes, in which case we can do something, or as
+ an expression, which we cannot represent. */
+ {
+ char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
+ char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+ sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
+ current_dienum, dim_num, u_or_l);
+
+ sprintf (end_label, BOUND_END_LABEL_FMT,
+ current_dienum, dim_num, u_or_l);
+
+ ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
+ ASM_OUTPUT_LABEL (asm_out_file, begin_label);
+
+ /* If optimization is turned on, the SAVE_EXPRs that describe
+ how to access the upper bound values are essentially bogus.
+ They only describe (at best) how to get at these values at
+ the points in the generated code right after they have just
+ been computed. Worse yet, in the typical case, the upper
+ bound values will not even *be* computed in the optimized
+ code, so these SAVE_EXPRs are entirely bogus.
+
+ In order to compensate for this fact, we check here to see
+ if optimization is enabled, and if so, we effectively create
+ an empty location description for the (unknown and unknowable)
+ upper bound.
+
+ This should not cause too much trouble for existing (stupid?)
+ debuggers because they have to deal with empty upper bounds
+ location descriptions anyway in order to be able to deal with
+ incomplete array types.
+
+ Of course an intelligent debugger (GDB?) should be able to
+ comprehend that a missing upper bound specification in a
+ array type used for a storage class `auto' local array variable
+ indicates that the upper bound is both unknown (at compile-
+ time) and unknowable (at run-time) due to optimization. */
+
+ if (! optimize)
+ {
+ while (TREE_CODE (bound) == NOP_EXPR
+ || TREE_CODE (bound) == CONVERT_EXPR)
+ bound = TREE_OPERAND (bound, 0);
- if (! optimize)
- output_loc_descriptor
- (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
+ if (TREE_CODE (bound) == SAVE_EXPR)
+ output_loc_descriptor
+ (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX, 0));
+ }
- ASM_OUTPUT_LABEL (asm_out_file, end_label);
- }
- break;
+ ASM_OUTPUT_LABEL (asm_out_file, end_label);
+ }
+ break;
- default:
- abort ();
}
}
@@ -1725,7 +1906,7 @@ output_enumeral_list (link)
/* Given an unsigned value, round it up to the lowest multiple of `boundary'
which is not less than the value itself. */
-inline unsigned
+static inline unsigned
ceiling (value, boundary)
register unsigned value;
register unsigned boundary;
@@ -1737,7 +1918,7 @@ ceiling (value, boundary)
pointer to the declared type for the relevant field variable, or return
`integer_type_node' if the given node turns out to be an ERROR_MARK node. */
-inline tree
+static inline tree
field_type (decl)
register tree decl;
{
@@ -1756,7 +1937,7 @@ field_type (decl)
node, return the alignment in bits for the type, or else return
BITS_PER_WORD if the node actually turns out to be an ERROR_MARK node. */
-inline unsigned
+static inline unsigned
simple_type_align_in_bits (type)
register tree type;
{
@@ -1769,7 +1950,7 @@ simple_type_align_in_bits (type)
constant, or else return BITS_PER_WORD if the type actually turns out
to be an ERROR_MARK node. */
-inline unsigned
+static inline unsigned
simple_type_size_in_bits (type)
register tree type;
{
@@ -1901,6 +2082,25 @@ field_byte_offset (decl)
/* Compute the offset of the containing object in bytes. */
object_offset_in_bytes = object_offset_in_align_units * type_align_in_bytes;
+ /* The above code assumes that the field does not cross an alignment
+ boundary. This can happen if PCC_BITFIELD_TYPE_MATTERS is not defined,
+ or if the structure is packed. If this happens, then we get an object
+ which starts after the bitfield, which means that the bit offset is
+ negative. Gdb fails when given negative bit offsets. We avoid this
+ by recomputing using the first bit of the bitfield. This will give
+ us an object which does not completely contain the bitfield, but it
+ will be aligned, and it will contain the first bit of the bitfield. */
+ if (object_offset_in_bits > bitpos_int)
+ {
+ deepest_bitpos = bitpos_int + 1;
+ object_offset_in_bits
+ = ceiling (deepest_bitpos, type_align_in_bits) - type_size_in_bits;
+ object_offset_in_align_units = (object_offset_in_bits
+ / type_align_in_bits);
+ object_offset_in_bytes = (object_offset_in_align_units
+ * type_align_in_bytes);
+ }
+
return object_offset_in_bytes;
}
@@ -1913,7 +2113,7 @@ field_byte_offset (decl)
/* Generate an AT_sibling attribute. */
-inline void
+static inline void
sibling_attribute ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -1964,7 +2164,7 @@ location_attribute (rtl)
if (! is_pseudo_reg (rtl)
&& (GET_CODE (rtl) != MEM || ! is_pseudo_reg (XEXP (rtl, 0))))
- output_loc_descriptor (eliminate_regs (rtl, 0, NULL_RTX));
+ output_loc_descriptor (rtl);
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
@@ -1988,17 +2188,21 @@ location_attribute (rtl)
object" which will be given in the AT_byte_size attribute for this
bit-field. (See the `byte_size_attribute' function below.) It is
also used when calculating the value of the AT_bit_offset attribute.
- (See the `bit_offset_attribute' function below.)
-*/
+ (See the `bit_offset_attribute' function below.) */
static void
-data_member_location_attribute (decl)
- register tree decl;
+data_member_location_attribute (t)
+ register tree t;
{
- register unsigned object_offset_in_bytes = field_byte_offset (decl);
+ register unsigned object_offset_in_bytes;
char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+ if (TREE_CODE (t) == TREE_VEC)
+ object_offset_in_bytes = TREE_INT_CST_LOW (BINFO_OFFSET (t));
+ else
+ object_offset_in_bytes = field_byte_offset (t);
+
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location);
sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);
sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);
@@ -2186,7 +2390,7 @@ location_or_const_value_attribute (decl)
shouldn't be happening. All PARM_DECL nodes should get valid non-NULL
DECL_INCOMING_RTL values, but integrate.c doesn't currently generate
these values for inlined instances of inline function parameters, so
- when we see such cases, we are just SOL (shit-out-of-luck) for the time
+ when we see such cases, we are just out-of-luck for the time
being (until integrate.c gets fixed).
*/
@@ -2214,8 +2418,19 @@ location_or_const_value_attribute (decl)
if (rtl == NULL_RTX)
return;
+ rtl = eliminate_regs (rtl, 0, NULL_RTX, 0);
+#ifdef LEAF_REG_REMAP
+ if (leaf_function)
+ leaf_renumber_regs_insn (rtl);
+#endif
+
switch (GET_CODE (rtl))
{
+ case ADDRESSOF:
+ /* The address of a variable that was optimized away; don't emit
+ anything. */
+ break;
+
case CONST_INT:
case CONST_DOUBLE:
case CONST_STRING:
@@ -2232,6 +2447,15 @@ location_or_const_value_attribute (decl)
location_attribute (rtl);
break;
+ case CONCAT:
+ /* ??? CONCAT is used for complex variables, which may have the real
+ part stored in one place and the imag part stored somewhere else.
+ DWARF1 has no way to describe a variable that lives in two different
+ places, so we just describe where the first part lives, and hope that
+ the second part is stored after it. */
+ location_attribute (XEXP (rtl, 0));
+ break;
+
default:
abort (); /* Should never happen. */
}
@@ -2240,7 +2464,7 @@ location_or_const_value_attribute (decl)
/* Generate an AT_name attribute given some string value to be included as
the value of the attribute. */
-inline void
+static inline void
name_attribute (name_string)
register char *name_string;
{
@@ -2251,7 +2475,7 @@ name_attribute (name_string)
}
}
-inline void
+static inline void
fund_type_attribute (ft_code)
register unsigned ft_code;
{
@@ -2279,7 +2503,7 @@ mod_fund_type_attribute (type, decl_const, decl_volatile)
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
-inline void
+static inline void
user_def_type_attribute (type)
register tree type;
{
@@ -2312,7 +2536,7 @@ mod_u_d_type_attribute (type, decl_const, decl_volatile)
}
#ifdef USE_ORDERING_ATTRIBUTE
-inline void
+static inline void
ordering_attribute (ordering)
register unsigned ordering;
{
@@ -2369,7 +2593,7 @@ subscript_data_attribute (type)
if (! type_is_fundamental (domain))
abort ();
- /* Output the representation format byte for this dimension. */
+ /* Output the representation format byte for this dimension. */
ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file,
FMT_CODE (1,
@@ -2483,10 +2707,9 @@ byte_size_attribute (tree_node)
Note that it is the size (in bytes) of the hypothetical "containing
object" which will be given in the AT_byte_size attribute for this
- bit-field. (See `byte_size_attribute' above.)
-*/
+ bit-field. (See `byte_size_attribute' above.) */
-inline void
+static inline void
bit_offset_attribute (decl)
register tree decl;
{
@@ -2538,7 +2761,7 @@ bit_offset_attribute (decl)
/* For a FIELD_DECL node which represents a bit field, output an attribute
which specifies the length in bits of the given field. */
-inline void
+static inline void
bit_size_attribute (decl)
register tree decl;
{
@@ -2555,7 +2778,7 @@ bit_size_attribute (decl)
all of the enumeration constants associated with the given enumeration
type. */
-inline void
+static inline void
element_list_attribute (element)
register tree element;
{
@@ -2581,7 +2804,7 @@ element_list_attribute (element)
/* Generate an AT_stmt_list attribute. These are normally present only in
DIEs with a TAG_compile_unit tag. */
-inline void
+static inline void
stmt_list_attribute (label)
register char *label;
{
@@ -2593,7 +2816,7 @@ stmt_list_attribute (label)
/* Generate an AT_low_pc attribute for a label DIE, a lexical_block DIE or
for a subroutine DIE. */
-inline void
+static inline void
low_pc_attribute (asm_low_label)
register char *asm_low_label;
{
@@ -2604,7 +2827,7 @@ low_pc_attribute (asm_low_label)
/* Generate an AT_high_pc attribute for a lexical_block DIE or for a
subroutine DIE. */
-inline void
+static inline void
high_pc_attribute (asm_high_label)
register char *asm_high_label;
{
@@ -2614,7 +2837,7 @@ high_pc_attribute (asm_high_label)
/* Generate an AT_body_begin attribute for a subroutine DIE. */
-inline void
+static inline void
body_begin_attribute (asm_begin_label)
register char *asm_begin_label;
{
@@ -2624,7 +2847,7 @@ body_begin_attribute (asm_begin_label)
/* Generate an AT_body_end attribute for a subroutine DIE. */
-inline void
+static inline void
body_end_attribute (asm_end_label)
register char *asm_end_label;
{
@@ -2635,7 +2858,7 @@ body_end_attribute (asm_end_label)
/* Generate an AT_language attribute given a LANG value. These attributes
are used only within TAG_compile_unit DIEs. */
-inline void
+static inline void
language_attribute (language_code)
register unsigned language_code;
{
@@ -2643,7 +2866,7 @@ language_attribute (language_code)
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, language_code);
}
-inline void
+static inline void
member_attribute (context)
register tree context;
{
@@ -2659,7 +2882,7 @@ member_attribute (context)
}
}
-inline void
+static inline void
string_length_attribute (upper_bound)
register tree upper_bound;
{
@@ -2675,7 +2898,7 @@ string_length_attribute (upper_bound)
ASM_OUTPUT_LABEL (asm_out_file, end_label);
}
-inline void
+static inline void
comp_dir_attribute (dirname)
register char *dirname;
{
@@ -2683,7 +2906,7 @@ comp_dir_attribute (dirname)
ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
}
-inline void
+static inline void
sf_names_attribute (sf_names_start_label)
register char *sf_names_start_label;
{
@@ -2692,7 +2915,7 @@ sf_names_attribute (sf_names_start_label)
ASM_OUTPUT_DWARF_ADDR (asm_out_file, sf_names_start_label);
}
-inline void
+static inline void
src_info_attribute (src_info_start_label)
register char *src_info_start_label;
{
@@ -2701,7 +2924,7 @@ src_info_attribute (src_info_start_label)
ASM_OUTPUT_DWARF_ADDR (asm_out_file, src_info_start_label);
}
-inline void
+static inline void
mac_info_attribute (mac_info_start_label)
register char *mac_info_start_label;
{
@@ -2710,7 +2933,7 @@ mac_info_attribute (mac_info_start_label)
ASM_OUTPUT_DWARF_ADDR (asm_out_file, mac_info_start_label);
}
-inline void
+static inline void
prototyped_attribute (func_type)
register tree func_type;
{
@@ -2722,7 +2945,7 @@ prototyped_attribute (func_type)
}
}
-inline void
+static inline void
producer_attribute (producer)
register char *producer;
{
@@ -2730,7 +2953,7 @@ producer_attribute (producer)
ASM_OUTPUT_DWARF_STRING (asm_out_file, producer);
}
-inline void
+static inline void
inline_attribute (decl)
register tree decl;
{
@@ -2741,7 +2964,7 @@ inline_attribute (decl)
}
}
-inline void
+static inline void
containing_type_attribute (containing_type)
register tree containing_type;
{
@@ -2752,7 +2975,7 @@ containing_type_attribute (containing_type)
ASM_OUTPUT_DWARF_REF (asm_out_file, label);
}
-inline void
+static inline void
abstract_origin_attribute (origin)
register tree origin;
{
@@ -2777,7 +3000,7 @@ abstract_origin_attribute (origin)
}
#ifdef DWARF_DECL_COORDINATES
-inline void
+static inline void
src_coords_attribute (src_fileno, src_lineno)
register unsigned src_fileno;
register unsigned src_lineno;
@@ -2788,7 +3011,7 @@ src_coords_attribute (src_fileno, src_lineno)
}
#endif /* defined(DWARF_DECL_COORDINATES) */
-inline void
+static inline void
pure_or_virtual_attribute (func_decl)
register tree func_decl;
{
@@ -2856,16 +3079,22 @@ type_attribute (type, decl_const, decl_volatile)
register enum tree_code code = TREE_CODE (type);
register int root_type_modified;
- if (TREE_CODE (type) == ERROR_MARK)
+ if (code == ERROR_MARK)
return;
/* Handle a special case. For functions whose return type is void,
we generate *no* type attribute. (Note that no object may have
type `void', so this only applies to function return types. */
- if (TREE_CODE (type) == VOID_TYPE)
+ if (code == VOID_TYPE)
return;
+ /* If this is a subtype, find the underlying type. Eventually,
+ this should write out the appropriate subtype info. */
+ while ((code == INTEGER_TYPE || code == REAL_TYPE)
+ && TREE_TYPE (type) != 0)
+ type = TREE_TYPE (type), code = TREE_CODE (type);
+
root_type_modified = (code == POINTER_TYPE || code == REFERENCE_TYPE
|| decl_const || decl_volatile
|| TYPE_READONLY (type) || TYPE_VOLATILE (type));
@@ -2908,25 +3137,14 @@ type_tag (type)
/* Find the IDENTIFIER_NODE for the type name. */
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
t = TYPE_NAME (type);
-#if 0
- /* The g++ front end makes the TYPE_NAME of *each* tagged type point
- to a TYPE_DECL node, regardless of whether or not a `typedef' was
- involved. This is distinctly different from what the gcc front-end
- does. It always makes the TYPE_NAME for each tagged type be either
- NULL (signifying an anonymous tagged type) or else a pointer to an
- IDENTIFIER_NODE. Obviously, we would like to generate correct Dwarf
- for both C and C++, but given this inconsistency in the TREE
- representation of tagged types for C and C++ in the GNU front-ends,
- we cannot support both languages correctly unless we introduce some
- front-end specific code here, and rms objects to that, so we can
- only generate correct Dwarf for one of these two languages. C is
- more important, so for now we'll do the right thing for C and let
- g++ go fish. */
- else
- if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+ /* The g++ front end makes the TYPE_NAME of *each* tagged type point to
+ a TYPE_DECL node, regardless of whether or not a `typedef' was
+ involved. */
+ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ && ! DECL_IGNORED_P (TYPE_NAME (type)))
t = DECL_NAME (TYPE_NAME (type));
-#endif
+
/* Now get the name as a string, or invent one. */
if (t != 0)
name = IDENTIFIER_POINTER (t);
@@ -2935,7 +3153,7 @@ type_tag (type)
return (name == 0 || *name == '\0') ? 0 : name;
}
-inline void
+static inline void
dienum_push ()
{
/* Start by checking if the pending_sibling_stack needs to be expanded.
@@ -2956,13 +3174,13 @@ dienum_push ()
/* Pop the sibling stack so that the most recently pushed DIEnum becomes the
NEXT_DIE_NUM. */
-inline void
+static inline void
dienum_pop ()
{
pending_siblings--;
}
-inline tree
+static inline tree
member_declared_type (member)
register tree member;
{
@@ -3041,6 +3259,7 @@ output_set_type_die (arg)
#if 0
/* Implement this when there is a GNU FORTRAN or GNU Ada front end. */
+
static void
output_entry_point_die (arg)
register void *arg;
@@ -3217,17 +3436,21 @@ output_global_subroutine_die (arg)
equate_decl_number_to_die_number (decl);
else
{
- if (! DECL_EXTERNAL (decl))
+ if (! DECL_EXTERNAL (decl) && ! in_class
+ && decl == current_function_decl)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
high_pc_attribute (label);
- sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
- body_begin_attribute (label);
- sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
- body_end_attribute (label);
+ if (use_gnu_debug_info_extensions)
+ {
+ sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+ body_begin_attribute (label);
+ sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+ body_end_attribute (label);
+ }
}
}
}
@@ -3257,7 +3480,8 @@ output_global_variable_die (arg)
equate_decl_number_to_die_number (decl);
else
{
- if (!DECL_EXTERNAL (decl))
+ if (! DECL_EXTERNAL (decl) && ! in_class
+ && current_function_decl == decl_function_context (decl))
location_or_const_value_attribute (decl);
}
}
@@ -3383,7 +3607,7 @@ output_member_die (arg)
member_attribute (DECL_CONTEXT (decl));
type_attribute (member_declared_type (decl),
TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
- if (DECL_BIT_FIELD_TYPE (decl)) /* If this is a bit field... */
+ if (DECL_BIT_FIELD_TYPE (decl)) /* If this is a bit field... */
{
byte_size_attribute (decl);
bit_size_attribute (decl);
@@ -3396,9 +3620,9 @@ output_member_die (arg)
/* Don't generate either pointer_type DIEs or reference_type DIEs. Use
modified types instead.
- We keep this code here just in case these types of DIEs may be needed
- to represent certain things in other languages (e.g. Pascal) someday.
-*/
+ We keep this code here just in case these types of DIEs may be
+ needed to represent certain things in other languages (e.g. Pascal)
+ someday. */
static void
output_pointer_type_die (arg)
@@ -3465,6 +3689,8 @@ output_compile_unit_die (arg)
language_attribute (LANG_ADA83);
else if (strcmp (language_string, "GNU F77") == 0)
language_attribute (LANG_FORTRAN77);
+ else if (strcmp (language_string, "GNU Pascal") == 0)
+ language_attribute (LANG_PASCAL83);
else if (flag_traditional)
language_attribute (LANG_C);
else
@@ -3481,7 +3707,7 @@ output_compile_unit_die (arg)
comp_dir_attribute (wd);
}
- if (debug_info_level >= DINFO_LEVEL_NORMAL)
+ if (debug_info_level >= DINFO_LEVEL_NORMAL && use_gnu_debug_info_extensions)
{
sf_names_attribute (SFNAMES_BEGIN_LABEL);
src_info_attribute (SRCINFO_BEGIN_LABEL);
@@ -3506,6 +3732,33 @@ output_string_type_die (arg)
}
static void
+output_inheritance_die (arg)
+ register void *arg;
+{
+ register tree binfo = arg;
+
+ ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inheritance);
+ sibling_attribute ();
+ type_attribute (BINFO_TYPE (binfo), 0, 0);
+ data_member_location_attribute (binfo);
+ if (TREE_VIA_VIRTUAL (binfo))
+ {
+ ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
+ ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ }
+ if (TREE_VIA_PUBLIC (binfo))
+ {
+ ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
+ ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ }
+ else if (TREE_VIA_PROTECTED (binfo))
+ {
+ ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
+ ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+ }
+}
+
+static void
output_structure_type_die (arg)
register void *arg;
{
@@ -3569,10 +3822,13 @@ output_local_subroutine_die (arg)
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
high_pc_attribute (label);
- sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
- body_begin_attribute (label);
- sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
- body_end_attribute (label);
+ if (use_gnu_debug_info_extensions)
+ {
+ sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+ body_begin_attribute (label);
+ sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+ body_end_attribute (label);
+ }
}
}
}
@@ -3742,11 +3998,11 @@ end_sibling_chain ()
parameters as specified in some function type specification (except
for those which appear as part of a function *definition*).
- Note that we must be careful here to output all of the parameter DIEs
- *before* we output any DIEs needed to represent the types of the formal
- parameters. This keeps svr4 SDB happy because it (incorrectly) thinks
- that the first non-parameter DIE it sees ends the formal parameter list.
-*/
+ Note that we must be careful here to output all of the parameter
+ DIEs *before* we output any DIEs needed to represent the types of
+ the formal parameters. This keeps svr4 SDB happy because it
+ (incorrectly) thinks that the first non-parameter DIE it sees ends
+ the formal parameter list. */
static void
output_formal_types (function_or_method_type)
@@ -3859,10 +4115,9 @@ pend_type (type)
been output are instead placed onto the pending_types_list. Later on,
we force these (temporarily pended) types to be output simply by calling
`output_pending_types_for_scope' with an actual argument equal to the
- true scope of the types we temporarily pended.
-*/
+ true scope of the types we temporarily pended. */
-inline int
+static inline int
type_ok_for_scope (type, scope)
register tree type;
register tree scope;
@@ -3879,7 +4134,9 @@ type_ok_for_scope (type, scope)
(for C and C++ anyway) will be array types and function types. */
return is_tagged_type (type)
- ? (TYPE_CONTEXT (type) == scope)
+ ? (TYPE_CONTEXT (type) == scope
+ || (scope == NULL_TREE && is_tagged_type (TYPE_CONTEXT (type))
+ && TREE_ASM_WRITTEN (TYPE_CONTEXT (type))))
: (scope == NULL_TREE || ! is_tagged_type (scope));
}
@@ -3892,8 +4149,7 @@ type_ok_for_scope (type, scope)
Note that we have to process the list in beginning-to-end order,
because the call made here to output_type may cause yet more types
to be added to the end of the list, and we may have to output some
- of them too.
-*/
+ of them too. */
static void
output_pending_types_for_scope (containing_scope)
@@ -3946,7 +4202,33 @@ output_type (type, containing_scope)
type = type_main_variant (type);
if (TREE_ASM_WRITTEN (type))
- return;
+ {
+ if (finalizing && AGGREGATE_TYPE_P (type))
+ {
+ register tree member;
+
+ /* Some of our nested types might not have been defined when we
+ were written out before; force them out now. */
+
+ for (member = TYPE_FIELDS (type); member;
+ member = TREE_CHAIN (member))
+ if (TREE_CODE (member) == TYPE_DECL
+ && ! TREE_ASM_WRITTEN (TREE_TYPE (member)))
+ output_type (TREE_TYPE (member), containing_scope);
+ }
+ return;
+ }
+
+ /* If this is a nested type whose containing class hasn't been
+ written out yet, writing it out will cover this one, too. */
+
+ if (TYPE_CONTEXT (type)
+ && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+ && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+ {
+ output_type (TYPE_CONTEXT (type), containing_scope);
+ return;
+ }
/* Don't generate any DIEs for this type now unless it is OK to do so
(based upon what `type_ok_for_scope' tells us). */
@@ -3964,6 +4246,9 @@ output_type (type, containing_scope)
case POINTER_TYPE:
case REFERENCE_TYPE:
+ /* Prevent infinite recursion in cases where this is a recursive
+ type. Recursive types are possible in Ada. */
+ TREE_ASM_WRITTEN (type) = 1;
/* For these types, all that is required is that we output a DIE
(or a set of DIEs) to represent the "basis" type. */
output_type (TREE_TYPE (type), containing_scope);
@@ -4058,10 +4343,12 @@ output_type (type, containing_scope)
time, we will certainly know as much about each file-scope tagged
type as we are ever going to know, so at that point in time, we
can safely generate correct Dwarf descriptions for these file-
- scope tagged types.
- */
+ scope tagged types. */
- if (TYPE_SIZE (type) == 0 && TYPE_CONTEXT (type) == NULL && !finalizing)
+ if (TYPE_SIZE (type) == 0
+ && (TYPE_CONTEXT (type) == NULL
+ || TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't')
+ && !finalizing)
return; /* EARLY EXIT! Avoid setting TREE_ASM_WRITTEN. */
/* Prevent infinite recursion in cases where the type of some
@@ -4109,10 +4396,23 @@ output_type (type, containing_scope)
if (TYPE_SIZE (type))
{
+ /* First output info about the base classes. */
+ if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
+ {
+ register tree bases = TYPE_BINFO_BASETYPES (type);
+ register int n_bases = TREE_VEC_LENGTH (bases);
+ register int i;
+
+ for (i = 0; i < n_bases; i++)
+ output_die (output_inheritance_die, TREE_VEC_ELT (bases, i));
+ }
+
+ ++in_class;
+
{
register tree normal_member;
- /* First output info about the data members and type members. */
+ /* Now output info about the data members and type members. */
for (normal_member = TYPE_FIELDS (type);
normal_member;
@@ -4121,32 +4421,18 @@ output_type (type, containing_scope)
}
{
- register tree vec_base;
+ register tree func_member;
/* Now output info about the function members (if any). */
- vec_base = TYPE_METHODS (type);
- if (vec_base)
- {
- register tree first_func_member = TREE_VEC_ELT (vec_base, 0);
- register tree func_member;
-
- /* This isn't documented, but the first element of the
- vector of member functions can be NULL in cases where
- the class type in question didn't have either a
- constructor or a destructor declared for it. We have
- to make allowances for that here. */
-
- if (first_func_member == NULL)
- first_func_member = TREE_VEC_ELT (vec_base, 1);
-
- for (func_member = first_func_member;
- func_member;
- func_member = TREE_CHAIN (func_member))
- output_decl (func_member, type);
- }
+ for (func_member = TYPE_METHODS (type);
+ func_member;
+ func_member = TREE_CHAIN (func_member))
+ output_decl (func_member, type);
}
+ --in_class;
+
/* RECORD_TYPEs, UNION_TYPEs, and QUAL_UNION_TYPEs are themselves
scopes (at least in C++) so we must now output any nested
pending types which are local just to this type. */
@@ -4219,8 +4505,9 @@ output_tagged_type_instantiation (type)
the things which are local to the given block. */
static void
-output_block (stmt)
+output_block (stmt, depth)
register tree stmt;
+ int depth;
{
register int must_output_die = 0;
register tree origin;
@@ -4258,7 +4545,7 @@ output_block (stmt)
not represent a "body block inlining" before trying to set the
`must_output_die' flag. */
- if (origin == NULL || ! is_body_block (origin))
+ if (! is_body_block (origin ? origin : stmt))
{
/* Determine if this block directly contains any "significant"
local declarations which we will need to output DIEs for. */
@@ -4292,32 +4579,35 @@ output_block (stmt)
a "significant" local declaration gets restricted to include only
inlined function instances and local (nested) function definitions. */
- if (must_output_die)
+ if (origin_code == FUNCTION_DECL && BLOCK_ABSTRACT (stmt))
+ /* We don't care about an abstract inlined subroutine. */;
+ else if (must_output_die)
{
output_die ((origin_code == FUNCTION_DECL)
? output_inlined_subroutine_die
: output_lexical_block_die,
stmt);
- output_decls_for_scope (stmt);
+ output_decls_for_scope (stmt, depth);
end_sibling_chain ();
}
else
- output_decls_for_scope (stmt);
+ output_decls_for_scope (stmt, depth);
}
/* Output all of the decls declared within a given scope (also called
a `binding contour') and (recursively) all of it's sub-blocks. */
static void
-output_decls_for_scope (stmt)
+output_decls_for_scope (stmt, depth)
register tree stmt;
+ int depth;
{
/* Ignore blocks never really used to make RTL. */
if (! stmt || ! TREE_USED (stmt))
return;
- if (! BLOCK_ABSTRACT (stmt))
+ if (! BLOCK_ABSTRACT (stmt) && depth > 0)
next_block_number++;
/* Output the DIEs to represent all of the data objects, functions,
@@ -4342,10 +4632,28 @@ output_decls_for_scope (stmt)
for (subblocks = BLOCK_SUBBLOCKS (stmt);
subblocks;
subblocks = BLOCK_CHAIN (subblocks))
- output_block (subblocks);
+ output_block (subblocks, depth + 1);
}
}
+/* Is this a typedef we can avoid emitting? */
+
+inline int
+is_redundant_typedef (decl)
+ register tree decl;
+{
+ if (TYPE_DECL_IS_STUB (decl))
+ return 1;
+ if (DECL_ARTIFICIAL (decl)
+ && DECL_CONTEXT (decl)
+ && is_tagged_type (DECL_CONTEXT (decl))
+ && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
+ && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
+ /* Also ignore the artificial member typedef for the class name. */
+ return 1;
+ return 0;
+}
+
/* Output Dwarf .debug information for a decl described by DECL. */
static void
@@ -4406,6 +4714,13 @@ output_decl (decl, containing_scope)
output_type (TREE_TYPE (TREE_TYPE (decl)), containing_scope);
+ {
+ /* And its containing type. */
+ register tree origin = decl_class_context (decl);
+ if (origin)
+ output_type (origin, containing_scope);
+ }
+
/* If the following DIE will represent a function definition for a
function with "extern" linkage, output a special "pubnames" DIE
label just ahead of the actual DIE. A reference to this label
@@ -4442,7 +4757,7 @@ output_decl (decl, containing_scope)
we need to do here (and all we *can* do here) is to describe
the *types* of its formal parameters. */
- if (DECL_INITIAL (decl) == NULL_TREE)
+ if (decl != current_function_decl || in_class)
output_formal_types (TREE_TYPE (decl));
else
{
@@ -4521,7 +4836,7 @@ output_decl (decl, containing_scope)
if (fn_arg_types)
{
- /* this is the prototyped case, check for ... */
+ /* this is the prototyped case, check for ... */
if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
output_die (output_unspecified_parameters_die, decl);
}
@@ -4532,61 +4847,45 @@ output_decl (decl, containing_scope)
output_die (output_unspecified_parameters_die, decl);
}
}
- }
-
- /* Output Dwarf info for all of the stuff within the body of the
- function (if it has one - it may be just a declaration). */
- {
- register tree outer_scope = DECL_INITIAL (decl);
+ /* Output Dwarf info for all of the stuff within the body of the
+ function (if it has one - it may be just a declaration). */
- if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
{
- /* Note that here, `outer_scope' is a pointer to the outermost
- BLOCK node created to represent a function.
- This outermost BLOCK actually represents the outermost
- binding contour for the function, i.e. the contour in which
- the function's formal parameters and labels get declared.
-
- Curiously, it appears that the front end doesn't actually
- put the PARM_DECL nodes for the current function onto the
- BLOCK_VARS list for this outer scope. (They are strung
- off of the DECL_ARGUMENTS list for the function instead.)
- The BLOCK_VARS list for the `outer_scope' does provide us
- with a list of the LABEL_DECL nodes for the function however,
- and we output DWARF info for those here.
-
- Just within the `outer_scope' there will be another BLOCK
- node representing the function's outermost pair of curly
- braces. We mustn't generate a lexical_block DIE for this
- outermost pair of curly braces because that is not really an
- independent scope according to ANSI C rules. Rather, it is
- the same scope in which the parameters were declared. */
-
- {
- register tree label;
-
- for (label = BLOCK_VARS (outer_scope);
- label;
- label = TREE_CHAIN (label))
- output_decl (label, outer_scope);
- }
-
- /* Note here that `BLOCK_SUBBLOCKS (outer_scope)' points to a
- list of BLOCK nodes which is always only one element long.
- That one element represents the outermost pair of curley
- braces for the function body. */
+ register tree outer_scope = DECL_INITIAL (decl);
- output_decls_for_scope (BLOCK_SUBBLOCKS (outer_scope));
-
- /* Finally, force out any pending types which are local to the
- outermost block of this function definition. These will
- all have a TYPE_CONTEXT which points to the FUNCTION_DECL
- node itself. */
-
- output_pending_types_for_scope (decl);
+ if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
+ {
+ /* Note that here, `outer_scope' is a pointer to the outermost
+ BLOCK node created to represent a function.
+ This outermost BLOCK actually represents the outermost
+ binding contour for the function, i.e. the contour in which
+ the function's formal parameters and labels get declared.
+
+ Curiously, it appears that the front end doesn't actually
+ put the PARM_DECL nodes for the current function onto the
+ BLOCK_VARS list for this outer scope. (They are strung
+ off of the DECL_ARGUMENTS list for the function instead.)
+ The BLOCK_VARS list for the `outer_scope' does provide us
+ with a list of the LABEL_DECL nodes for the function however,
+ and we output DWARF info for those here.
+
+ Just within the `outer_scope' there will be a BLOCK node
+ representing the function's outermost pair of curly braces,
+ and any blocks used for the base and member initializers of
+ a C++ constructor function. */
+
+ output_decls_for_scope (outer_scope, 0);
+
+ /* Finally, force out any pending types which are local to the
+ outermost block of this function definition. These will
+ all have a TYPE_CONTEXT which points to the FUNCTION_DECL
+ node itself. */
+
+ output_pending_types_for_scope (decl);
+ }
}
- }
+ }
/* Generate a terminator for the list of stuff `owned' by this
function. */
@@ -4603,19 +4902,19 @@ output_decl (decl, containing_scope)
a return type or a formal parameter type of some function. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
- if (DECL_NAME (decl) != NULL
- || ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
+ if (! TYPE_DECL_IS_STUB (decl)
+ || (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
return;
- /* In the special case of a null-named TYPE_DECL node (representing
- the declaration of some type tag), if the given TYPE_DECL is
+ /* In the special case of a TYPE_DECL node representing
+ the declaration of some type tag, if the given TYPE_DECL is
marked as having been instantiated from some other (original)
TYPE_DECL node (e.g. one which was generated within the original
definition of an inline function) we have to generate a special
(abbreviated) TAG_structure_type, TAG_union_type, or
TAG_enumeration-type DIE here. */
- if (! DECL_NAME (decl) && DECL_ABSTRACT_ORIGIN (decl))
+ if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl))
{
output_tagged_type_instantiation (TREE_TYPE (decl));
return;
@@ -4623,16 +4922,7 @@ output_decl (decl, containing_scope)
output_type (TREE_TYPE (decl), containing_scope);
- /* Note that unlike the gcc front end (which generates a NULL named
- TYPE_DECL node for each complete tagged type, each array type,
- and each function type node created) the g++ front end generates
- a *named* TYPE_DECL node for each tagged type node created.
- Unfortunately, these g++ TYPE_DECL nodes cause us to output many
- superfluous and unnecessary TAG_typedef DIEs here. When g++ is
- fixed to stop generating these superfluous named TYPE_DECL nodes,
- the superfluous TAG_typedef DIEs will likewise cease. */
-
- if (DECL_NAME (decl))
+ if (! is_redundant_typedef (decl))
/* Output a DIE to represent the typedef itself. */
output_die (output_typedef_die, decl);
break;
@@ -4662,6 +4952,13 @@ output_decl (decl, containing_scope)
output_type (TREE_TYPE (decl), containing_scope);
+ {
+ /* And its containing type. */
+ register tree origin = decl_class_context (decl);
+ if (origin)
+ output_type (origin, containing_scope);
+ }
+
/* If the following DIE will represent a data object definition for a
data object with "extern" linkage, output a special "pubnames" DIE
label just ahead of the actual DIE. A reference to this label
@@ -4779,7 +5076,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
the compiler never generates any out-of-lines instances of such
things (despite the fact that they *are* definitions). The
important point is that the C front-end marks these "extern inline"
- functions as DECL_EXTERNAL, but we need to generate DWARf for them
+ functions as DECL_EXTERNAL, but we need to generate DWARF for them
anyway.
Note that the C++ front-end also plays some similar games for inline
@@ -4890,7 +5187,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
a return type or a formal parameter type of some function. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
- if (DECL_NAME (decl) != NULL
+ if (! TYPE_DECL_IS_STUB (decl)
|| ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
return;
@@ -4983,6 +5280,8 @@ dwarfout_begin_function ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
+ if (! use_gnu_debug_info_extensions)
+ return;
function_section (current_function_decl);
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
@@ -4996,6 +5295,8 @@ dwarfout_end_function ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
+ if (! use_gnu_debug_info_extensions)
+ return;
function_section (current_function_decl);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
@@ -5088,8 +5389,7 @@ generate_new_sfname_entry ()
calculated, and where at least one of the two symbol references is a
forward reference. (This bug could be tickled by our .debug_srcinfo
entries if we don't output their corresponding .debug_sfnames entries
- before them.)
-*/
+ before them.) */
static unsigned
lookup_filename (file_name)
@@ -5163,20 +5463,28 @@ dwarfout_line (filename, line)
register char *filename;
register unsigned line;
{
- if (debug_info_level >= DINFO_LEVEL_NORMAL)
+ if (debug_info_level >= DINFO_LEVEL_NORMAL
+ /* We can't emit line number info for functions in separate sections,
+ because the assembler can't subtract labels in different sections. */
+ && DECL_SECTION_NAME (current_function_decl) == NULL_TREE)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
static unsigned last_line_entry_num = 0;
static unsigned prev_file_entry_num = (unsigned) -1;
- register unsigned this_file_entry_num = lookup_filename (filename);
+ register unsigned this_file_entry_num;
function_section (current_function_decl);
sprintf (label, LINE_CODE_LABEL_FMT, ++last_line_entry_num);
ASM_OUTPUT_LABEL (asm_out_file, label);
fputc ('\n', asm_out_file);
- ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
+ if (use_gnu_debug_info_extensions)
+ this_file_entry_num = lookup_filename (filename);
+ else
+ this_file_entry_num = (unsigned) -1;
+
+ ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
if (this_file_entry_num != prev_file_entry_num)
{
char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -5212,6 +5520,9 @@ generate_macinfo_entry (type_and_offset, string)
register char *type_and_offset;
register char *string;
{
+ if (! use_gnu_debug_info_extensions)
+ return;
+
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
fprintf (asm_out_file, "\t%s\t%s\n", UNALIGNED_INT_ASM_OP, type_and_offset);
@@ -5228,7 +5539,10 @@ dwarfout_start_new_source_file (filename)
sprintf (label, SFNAMES_ENTRY_LABEL_FMT, lookup_filename (filename));
sprintf (type_and_offset, "0x%08x+%s-%s",
- ((unsigned) MACINFO_start << 24), label, SFNAMES_BEGIN_LABEL);
+ ((unsigned) MACINFO_start << 24),
+ /* Hack: skip leading '*' . */
+ (*label == '*') + label,
+ (*SFNAMES_BEGIN_LABEL == '*') + SFNAMES_BEGIN_LABEL);
generate_macinfo_entry (type_and_offset, "");
}
@@ -5371,32 +5685,36 @@ dwarfout_init (asm_out_file, main_input_filename)
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
- /* Output a starting label and an initial (compilation directory)
- entry for the .debug_sfnames section. The starting label will be
- referenced by the initial entry in the .debug_srcinfo section. */
+ if (use_gnu_debug_info_extensions)
+ {
+ /* Output a starting label and an initial (compilation directory)
+ entry for the .debug_sfnames section. The starting label will be
+ referenced by the initial entry in the .debug_srcinfo section. */
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
- ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
- {
- register char *pwd;
- register unsigned len;
- register char *dirname;
-
- pwd = getpwd ();
- if (!pwd)
- pfatal_with_name ("getpwd");
- len = strlen (pwd);
- dirname = (char *) xmalloc (len + 2);
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
+ {
+ register char *pwd;
+ register unsigned len;
+ register char *dirname;
+
+ pwd = getpwd ();
+ if (!pwd)
+ pfatal_with_name ("getpwd");
+ len = strlen (pwd);
+ dirname = (char *) xmalloc (len + 2);
- strcpy (dirname, pwd);
- strcpy (dirname + len, "/");
- ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
- free (dirname);
- }
- ASM_OUTPUT_POP_SECTION (asm_out_file);
+ strcpy (dirname, pwd);
+ strcpy (dirname + len, "/");
+ ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
+ free (dirname);
+ }
+ ASM_OUTPUT_POP_SECTION (asm_out_file);
+ }
- if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+ if (debug_info_level >= DINFO_LEVEL_VERBOSE
+ && use_gnu_debug_info_extensions)
{
/* Output a starting label for the .debug_macinfo section. This
label will be referenced by the AT_mac_info attribute in the
@@ -5417,21 +5735,24 @@ dwarfout_init (asm_out_file, main_input_filename)
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
- /* Generate the initial entry for the .debug_srcinfo section. */
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
- ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
- ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
+ if (use_gnu_debug_info_extensions)
+ {
+ /* Generate the initial entry for the .debug_srcinfo section. */
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
+ ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
+ ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
#ifdef DWARF_TIMESTAMPS
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
#else
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
#endif
- ASM_OUTPUT_POP_SECTION (asm_out_file);
+ ASM_OUTPUT_POP_SECTION (asm_out_file);
+ }
/* Generate the initial entry for the .debug_pubnames section. */
@@ -5503,7 +5824,7 @@ dwarfout_finish ()
(or blame). I didn't think of this scheme. I just conformed to it.
*/
- output_die (output_padded_null_die, (void *)0);
+ output_die (output_padded_null_die, (void *) 0);
dienum_pop ();
sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);
@@ -5569,14 +5890,17 @@ dwarfout_finish ()
ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
- /* Output a terminating entry for the .debug_srcinfo section. */
-
- fputc ('\n', asm_out_file);
- ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
- ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
- LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
- ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
- ASM_OUTPUT_POP_SECTION (asm_out_file);
+ if (use_gnu_debug_info_extensions)
+ {
+ /* Output a terminating entry for the .debug_srcinfo section. */
+
+ fputc ('\n', asm_out_file);
+ ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
+ ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
+ LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
+ ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
+ ASM_OUTPUT_POP_SECTION (asm_out_file);
+ }
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
diff --git a/gnu/usr.bin/gcc/emit-rtl.c b/gnu/usr.bin/gcc/emit-rtl.c
index 9600f2f63aa..d4b6a79a9a2 100644
--- a/gnu/usr.bin/gcc/emit-rtl.c
+++ b/gnu/usr.bin/gcc/emit-rtl.c
@@ -1,5 +1,5 @@
/* Emit RTL for the GNU C-Compiler expander.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
is the kind of rtx's they make and what arguments they use. */
#include "config.h"
+#include <stdio.h>
#ifdef __STDC__
#include <stdarg.h>
#else
@@ -43,10 +44,12 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "tree.h"
#include "flags.h"
+#include "except.h"
#include "function.h"
#include "expr.h"
#include "regs.h"
#include "insn-config.h"
+#include "recog.h"
#include "real.h"
#include "obstack.h"
@@ -57,9 +60,6 @@ Boston, MA 02111-1307, USA. */
#include "bc-optab.h"
#include "bc-emit.h"
-#include <stdio.h>
-
-
/* Opcode names */
#ifdef BCDEBUG_PRINT_CODE
char *opcode_name[] =
@@ -73,9 +73,9 @@ char *opcode_name[] =
/* Commonly used modes. */
-enum machine_mode byte_mode; /* Mode whose width is BITS_PER_UNIT. */
-enum machine_mode word_mode; /* Mode whose width is BITS_PER_WORD. */
-enum machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */
+enum machine_mode byte_mode; /* Mode whose width is BITS_PER_UNIT. */
+enum machine_mode word_mode; /* Mode whose width is BITS_PER_WORD. */
+enum machine_mode ptr_mode; /* Mode whose width is POINTER_SIZE. */
/* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
After rtl generation, it is 1 plus the largest register number used. */
@@ -159,6 +159,10 @@ rtx static_chain_rtx; /* (REG:Pmode STATIC_CHAIN_REGNUM) */
rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */
rtx pic_offset_table_rtx; /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */
+/* This is used to implement __builtin_return_address for some machines.
+ See for instance the MIPS port. */
+rtx return_address_pointer_rtx; /* (REG:Pmode RETURN_ADDRESS_POINTER_REGNUM) */
+
rtx virtual_incoming_args_rtx; /* (REG:Pmode VIRTUAL_INCOMING_ARGS_REGNUM) */
rtx virtual_stack_vars_rtx; /* (REG:Pmode VIRTUAL_STACK_VARS_REGNUM) */
rtx virtual_stack_dynamic_rtx; /* (REG:Pmode VIRTUAL_STACK_DYNAMIC_REGNUM) */
@@ -208,6 +212,11 @@ static char *last_filename = 0;
char *regno_pointer_flag;
int regno_pointer_flag_length;
+/* Indexed by pseudo register number, if nonzero gives the known alignment
+ for that pseudo (if regno_pointer_flag is set).
+ Allocated in parallel with regno_pointer_flag. */
+char *regno_pointer_align;
+
/* Indexed by pseudo register number, gives the rtx for that pseudo.
Allocated in parallel with regno_pointer_flag. */
@@ -240,6 +249,9 @@ struct sequence_stack *sequence_stack;
static struct sequence_stack *sequence_element_free_list;
static rtx sequence_result[SEQUENCE_RESULT_SIZE];
+/* During RTL generation, we also keep a list of free INSN rtl codes. */
+static rtx free_insn;
+
extern int rtx_equal_function_value_matters;
/* Filename and line number of last line-number note,
@@ -247,13 +259,9 @@ extern int rtx_equal_function_value_matters;
extern char *emit_filename;
extern int emit_lineno;
-rtx change_address ();
-void init_emit ();
-
-extern struct obstack *rtl_obstack;
-
-extern int stack_depth;
-extern int max_stack_depth;
+static rtx make_jump_insn_raw PROTO((rtx));
+static rtx make_call_insn_raw PROTO((rtx));
+static rtx find_line_node PROTO((rtx));
/* rtx gen_rtx (code, mode, [element1, ..., elementn])
**
@@ -345,6 +353,11 @@ gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...))
&& ! reload_in_progress)
return arg_pointer_rtx;
#endif
+#ifdef RETURN_ADDRESS_POINTER_REGNUM
+ if (return_address_pointer_rtx && regno == RETURN_ADDRESS_POINTER_REGNUM
+ && mode == Pmode && ! reload_in_progress)
+ return return_address_pointer_rtx;
+#endif
if (stack_pointer_rtx && regno == STACK_POINTER_REGNUM && mode == Pmode
&& ! reload_in_progress)
return stack_pointer_rtx;
@@ -452,6 +465,25 @@ gen_rtvec_v (n, argp)
return rt_val;
}
+
+rtvec
+gen_rtvec_vv (n, argp)
+ int n;
+ rtunion *argp;
+{
+ register int i;
+ register rtvec rt_val;
+
+ if (n == 0)
+ return NULL_RTVEC; /* Don't allocate an empty rtvec... */
+
+ rt_val = rtvec_alloc (n); /* Allocate an rtvec... */
+
+ for (i = 0; i < n; i++)
+ rt_val->elem[i].rtx = (argp++)->rtx;
+
+ return rt_val;
+}
/* Generate a REG rtx for a new pseudo register of mode MODE.
This pseudo is assigned the next sequential register number. */
@@ -497,12 +529,17 @@ gen_reg_rtx (mode)
{
rtx *new1;
char *new =
- (char *) oballoc (regno_pointer_flag_length * 2);
+ (char *) savealloc (regno_pointer_flag_length * 2);
bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);
regno_pointer_flag = new;
- new1 = (rtx *) oballoc (regno_pointer_flag_length * 2 * sizeof (rtx));
+ new = (char *) savealloc (regno_pointer_flag_length * 2);
+ bcopy (regno_pointer_align, new, regno_pointer_flag_length);
+ bzero (&new[regno_pointer_flag_length], regno_pointer_flag_length);
+ regno_pointer_align = new;
+
+ new1 = (rtx *) savealloc (regno_pointer_flag_length * 2 * sizeof (rtx));
bcopy ((char *) regno_reg_rtx, (char *) new1,
regno_pointer_flag_length * sizeof (rtx));
bzero ((char *) &new1[regno_pointer_flag_length],
@@ -517,13 +554,35 @@ gen_reg_rtx (mode)
return val;
}
-/* Identify REG as a probable pointer register. */
+/* Identify REG (which may be a CONCAT) as a user register. */
+
+void
+mark_user_reg (reg)
+ rtx reg;
+{
+ if (GET_CODE (reg) == CONCAT)
+ {
+ REG_USERVAR_P (XEXP (reg, 0)) = 1;
+ REG_USERVAR_P (XEXP (reg, 1)) = 1;
+ }
+ else if (GET_CODE (reg) == REG)
+ REG_USERVAR_P (reg) = 1;
+ else
+ abort ();
+}
+
+/* Identify REG as a probable pointer register and show its alignment
+ as ALIGN, if nonzero. */
void
-mark_reg_pointer (reg)
+mark_reg_pointer (reg, align)
rtx reg;
+ int align;
{
REGNO_POINTER_FLAG (REGNO (reg)) = 1;
+
+ if (align)
+ REGNO_POINTER_ALIGN (REGNO (reg)) = align;
}
/* Return 1 plus largest pseudo reg number used in the current function. */
@@ -726,7 +785,7 @@ gen_lowpart_common (mode, x)
low = CONST_DOUBLE_LOW (x), high = CONST_DOUBLE_HIGH (x);
/* REAL_VALUE_TARGET_DOUBLE takes the addressing order of the
- target machine. */
+ target machine. */
if (WORDS_BIG_ENDIAN)
i[0] = high, i[1] = low;
else
@@ -754,6 +813,26 @@ gen_lowpart_common (mode, x)
return CONST_DOUBLE_FROM_REAL_VALUE (u.d, mode);
}
#endif
+
+ /* We need an extra case for machines where HOST_BITS_PER_WIDE_INT is the
+ same as sizeof (double), such as the alpha. We only handle the
+ REAL_ARITHMETIC case, which is easy. Testing HOST_BITS_PER_WIDE_INT
+ is not strictly necessary, but is done to restrict this code to cases
+ where it is known to work. */
+#ifdef REAL_ARITHMETIC
+ else if (mode == SFmode
+ && GET_CODE (x) == CONST_INT
+ && GET_MODE_BITSIZE (mode) * 2 == HOST_BITS_PER_WIDE_INT)
+ {
+ REAL_VALUE_TYPE r;
+ HOST_WIDE_INT i;
+
+ i = INTVAL (x);
+ r = REAL_VALUE_FROM_TARGET_SINGLE (i);
+ return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
+ }
+#endif
+
/* Similarly, if this is converting a floating-point value into a
single-word integer. Only do this is the host and target parameters are
compatible. */
@@ -766,7 +845,7 @@ gen_lowpart_common (mode, x)
&& GET_CODE (x) == CONST_DOUBLE
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == BITS_PER_WORD)
- return operand_subword (x, 0, 0, GET_MODE (x));
+ return operand_subword (x, word, 0, GET_MODE (x));
/* Similarly, if this is converting a floating-point value into a
two-word integer, we can do this one word at a time and make an
@@ -782,8 +861,10 @@ gen_lowpart_common (mode, x)
&& GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
&& GET_MODE_BITSIZE (mode) == 2 * BITS_PER_WORD)
{
- rtx lowpart = operand_subword (x, WORDS_BIG_ENDIAN, 0, GET_MODE (x));
- rtx highpart = operand_subword (x, ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));
+ rtx lowpart
+ = operand_subword (x, word + WORDS_BIG_ENDIAN, 0, GET_MODE (x));
+ rtx highpart
+ = operand_subword (x, word + ! WORDS_BIG_ENDIAN, 0, GET_MODE (x));
if (lowpart && GET_CODE (lowpart) == CONST_INT
&& highpart && GET_CODE (highpart) == CONST_INT)
@@ -863,6 +944,7 @@ gen_lowpart (mode, x)
result = gen_lowpart_common (mode, copy_to_reg (x));
if (result == 0)
abort ();
+ return result;
}
else if (GET_CODE (x) == MEM)
{
@@ -880,6 +962,8 @@ gen_lowpart (mode, x)
return change_address (x, mode, plus_constant (XEXP (x, 0), offset));
}
+ else if (GET_CODE (x) == ADDRESSOF)
+ return gen_lowpart (mode, force_reg (GET_MODE (x), x));
else
abort ();
}
@@ -947,7 +1031,7 @@ gen_highpart (mode, x)
*/
if (REGNO (x) < FIRST_PSEUDO_REGISTER
- /* integrate.c can't handle parts of a return value register. */
+ /* integrate.c can't handle parts of a return value register. */
&& (! REG_FUNCTION_VALUE_P (x)
|| ! rtx_equal_function_value_matters)
/* We want to keep the stack, frame, and arg pointers special. */
@@ -974,6 +1058,8 @@ subreg_lowpart_p (x)
{
if (GET_CODE (x) != SUBREG)
return 1;
+ else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
+ return 0;
if (WORDS_BIG_ENDIAN
&& GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD)
@@ -1132,6 +1218,20 @@ operand_subword (op, i, validate_address, mode)
else
abort ();
}
+ else if (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD
+ && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && GET_MODE_BITSIZE (mode) > 64
+ && GET_CODE (op) == CONST_DOUBLE)
+ {
+ long k[4];
+ REAL_VALUE_TYPE rv;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+
+ if (BITS_PER_WORD == 32)
+ return GEN_INT ((HOST_WIDE_INT) k[i]);
+ }
#else /* no REAL_ARITHMETIC */
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
@@ -1173,6 +1273,7 @@ operand_subword (op, i, validate_address, mode)
if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
&& HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
|| flag_pretend_float)
+ && sizeof (float) * 8 == HOST_BITS_PER_WIDE_INT
&& GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
&& GET_CODE (op) == CONST_DOUBLE)
@@ -1185,6 +1286,22 @@ operand_subword (op, i, validate_address, mode)
u.f = d;
return GEN_INT (u.i);
}
+ if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT
+ && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
+ || flag_pretend_float)
+ && sizeof (double) * 8 == HOST_BITS_PER_WIDE_INT
+ && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && GET_MODE_SIZE (mode) == UNITS_PER_WORD
+ && GET_CODE (op) == CONST_DOUBLE)
+ {
+ double d;
+ union {double d; HOST_WIDE_INT i; } u;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (d, op);
+
+ u.d = d;
+ return GEN_INT (u.i);
+ }
#endif /* no REAL_ARITHMETIC */
/* The only remaining cases that we can handle are integers.
@@ -1314,6 +1431,9 @@ change_address (memref, mode, addr)
else
addr = memory_address (mode, addr);
+ if (rtx_equal_p (addr, XEXP (memref, 0)) && mode == GET_MODE (memref))
+ return memref;
+
new = gen_rtx (MEM, mode, addr);
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref);
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref);
@@ -1330,7 +1450,8 @@ gen_label_rtx ()
label = (output_bytecode
? gen_rtx (CODE_LABEL, VOIDmode, NULL, bc_get_bytecode_label ())
- : gen_rtx (CODE_LABEL, VOIDmode, 0, 0, 0, label_num++, NULL_PTR));
+ : gen_rtx (CODE_LABEL, VOIDmode, 0, NULL_RTX,
+ NULL_RTX, label_num++, NULL_PTR));
LABEL_NUSES (label) = 0;
return label;
@@ -1346,7 +1467,8 @@ gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno,
last_labelno, max_parm_regnum, max_regnum, args_size,
pops_args, stack_slots, forced_labels, function_flags,
outgoing_args_size, original_arg_vector,
- original_decl_initial)
+ original_decl_initial, regno_rtx, regno_flag,
+ regno_align, parm_reg_stack_loc)
rtx first_insn, first_parm_insn;
int first_labelno, last_labelno, max_parm_regnum, max_regnum, args_size;
int pops_args;
@@ -1356,6 +1478,10 @@ gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno,
int outgoing_args_size;
rtvec original_arg_vector;
rtx original_decl_initial;
+ rtvec regno_rtx;
+ char *regno_flag;
+ char *regno_align;
+ rtvec parm_reg_stack_loc;
{
rtx header = gen_rtx (INLINE_HEADER, VOIDmode,
cur_insn_uid++, NULL_RTX,
@@ -1363,20 +1489,31 @@ gen_inline_header_rtx (first_insn, first_parm_insn, first_labelno,
first_labelno, last_labelno,
max_parm_regnum, max_regnum, args_size, pops_args,
stack_slots, forced_labels, function_flags,
- outgoing_args_size,
- original_arg_vector, original_decl_initial);
+ outgoing_args_size, original_arg_vector,
+ original_decl_initial,
+ regno_rtx, regno_flag, regno_align,
+ parm_reg_stack_loc);
return header;
}
/* Install new pointers to the first and last insns in the chain.
+ Also, set cur_insn_uid to one higher than the last in use.
Used for an inline-procedure after copying the insn chain. */
void
set_new_first_and_last_insn (first, last)
rtx first, last;
{
+ rtx insn;
+
first_insn = first;
last_insn = last;
+ cur_insn_uid = 0;
+
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ cur_insn_uid = MAX (cur_insn_uid, INSN_UID (insn));
+
+ cur_insn_uid++;
}
/* Set the range of label numbers found in the current function.
@@ -1408,6 +1545,7 @@ save_emit_status (p)
p->last_linenum = last_linenum;
p->last_filename = last_filename;
p->regno_pointer_flag = regno_pointer_flag;
+ p->regno_pointer_align = regno_pointer_align;
p->regno_pointer_flag_length = regno_pointer_flag_length;
p->regno_reg_rtx = regno_reg_rtx;
}
@@ -1432,13 +1570,17 @@ restore_emit_status (p)
last_linenum = p->last_linenum;
last_filename = p->last_filename;
regno_pointer_flag = p->regno_pointer_flag;
+ regno_pointer_align = p->regno_pointer_align;
regno_pointer_flag_length = p->regno_pointer_flag_length;
regno_reg_rtx = p->regno_reg_rtx;
- /* Clear our cache of rtx expressions for start_sequence and gen_sequence. */
+ /* Clear our cache of rtx expressions for start_sequence and
+ gen_sequence. */
sequence_element_free_list = 0;
for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
sequence_result[i] = 0;
+
+ free_insn = 0;
}
/* Go through all the RTL insn bodies and copy any invalid shared structure.
@@ -1500,7 +1642,7 @@ copy_rtx_if_shared (orig)
case PC:
case CC0:
case SCRATCH:
- /* SCRATCH must be shared because they represent distinct values. */
+ /* SCRATCH must be shared because they represent distinct values. */
return x;
case CONST:
@@ -1540,6 +1682,10 @@ copy_rtx_if_shared (orig)
x->used = 1;
return x;
}
+ break;
+
+ default:
+ break;
}
/* This rtx may not be shared. If it has already been seen,
@@ -1580,7 +1726,7 @@ copy_rtx_if_shared (orig)
int len = XVECLEN (x, i);
if (copied && len > 0)
- XVEC (x, i) = gen_rtvec_v (len, &XVECEXP (x, i, 0));
+ XVEC (x, i) = gen_rtvec_vv (len, XVEC (x, i)->elem);
for (j = 0; j < len; j++)
XVECEXP (x, i, j) = copy_rtx_if_shared (XVECEXP (x, i, j));
}
@@ -1629,6 +1775,9 @@ reset_used_flags (x)
case BARRIER:
/* The chain of insns is not being copied. */
return;
+
+ default:
+ break;
}
x->used = 0;
@@ -1811,7 +1960,7 @@ prev_nonnote_insn (insn)
/* Return the next INSN, CALL_INSN or JUMP_INSN after INSN;
or 0, if there is none. This routine does not look inside
- SEQUENCEs. */
+ SEQUENCEs. */
rtx
next_real_insn (insn)
@@ -2086,9 +2235,17 @@ make_insn_raw (pattern)
{
register rtx insn;
- insn = rtx_alloc (INSN);
- INSN_UID (insn) = cur_insn_uid++;
+ /* If in RTL generation phase, see if FREE_INSN can be used. */
+ if (free_insn != 0 && rtx_equal_function_value_matters)
+ {
+ insn = free_insn;
+ free_insn = NEXT_INSN (free_insn);
+ PUT_CODE (insn, INSN);
+ }
+ else
+ insn = rtx_alloc (INSN);
+ INSN_UID (insn) = cur_insn_uid++;
PATTERN (insn) = pattern;
INSN_CODE (insn) = -1;
LOG_LINKS (insn) = NULL;
@@ -3055,12 +3212,17 @@ gen_sequence ()
(Now that we cache SEQUENCE expressions, it isn't worth special-casing
the case of an empty list.) */
if (len == 1
+ && ! RTX_FRAME_RELATED_P (first_insn)
&& (GET_CODE (first_insn) == INSN
|| GET_CODE (first_insn) == JUMP_INSN
/* Don't discard the call usage field. */
|| (GET_CODE (first_insn) == CALL_INSN
&& CALL_INSN_FUNCTION_USAGE (first_insn) == NULL_RTX)))
- return PATTERN (first_insn);
+ {
+ NEXT_INSN (first_insn) = free_insn;
+ free_insn = first_insn;
+ return PATTERN (first_insn);
+ }
/* Put them in a vector. See if we already have a SEQUENCE of the
appropriate length around. */
@@ -3082,145 +3244,6 @@ gen_sequence ()
return result;
}
-/* Set up regno_reg_rtx, reg_rtx_no and regno_pointer_flag
- according to the chain of insns starting with FIRST.
-
- Also set cur_insn_uid to exceed the largest uid in that chain.
-
- This is used when an inline function's rtl is saved
- and passed to rest_of_compilation later. */
-
-static void restore_reg_data_1 ();
-
-void
-restore_reg_data (first)
- rtx first;
-{
- register rtx insn;
- int i;
- register int max_uid = 0;
-
- for (insn = first; insn; insn = NEXT_INSN (insn))
- {
- if (INSN_UID (insn) >= max_uid)
- max_uid = INSN_UID (insn);
-
- switch (GET_CODE (insn))
- {
- case NOTE:
- case CODE_LABEL:
- case BARRIER:
- break;
-
- case JUMP_INSN:
- case CALL_INSN:
- case INSN:
- restore_reg_data_1 (PATTERN (insn));
- break;
- }
- }
-
- /* Don't duplicate the uids already in use. */
- cur_insn_uid = max_uid + 1;
-
- /* If any regs are missing, make them up.
-
- ??? word_mode is not necessarily the right mode. Most likely these REGs
- are never used. At some point this should be checked. */
-
- for (i = FIRST_PSEUDO_REGISTER; i < reg_rtx_no; i++)
- if (regno_reg_rtx[i] == 0)
- regno_reg_rtx[i] = gen_rtx (REG, word_mode, i);
-}
-
-static void
-restore_reg_data_1 (orig)
- rtx orig;
-{
- register rtx x = orig;
- register int i;
- register enum rtx_code code;
- register char *format_ptr;
-
- code = GET_CODE (x);
-
- switch (code)
- {
- case QUEUED:
- case CONST_INT:
- case CONST_DOUBLE:
- case SYMBOL_REF:
- case CODE_LABEL:
- case PC:
- case CC0:
- case LABEL_REF:
- return;
-
- case REG:
- if (REGNO (x) >= FIRST_PSEUDO_REGISTER)
- {
- /* Make sure regno_pointer_flag and regno_reg_rtx are large
- enough to have an element for this pseudo reg number. */
- if (REGNO (x) >= reg_rtx_no)
- {
- reg_rtx_no = REGNO (x);
-
- if (reg_rtx_no >= regno_pointer_flag_length)
- {
- int newlen = MAX (regno_pointer_flag_length * 2,
- reg_rtx_no + 30);
- rtx *new1;
- char *new = (char *) oballoc (newlen);
- bzero (new, newlen);
- bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
-
- new1 = (rtx *) oballoc (newlen * sizeof (rtx));
- bzero ((char *) new1, newlen * sizeof (rtx));
- bcopy ((char *) regno_reg_rtx, (char *) new1,
- regno_pointer_flag_length * sizeof (rtx));
-
- regno_pointer_flag = new;
- regno_reg_rtx = new1;
- regno_pointer_flag_length = newlen;
- }
- reg_rtx_no ++;
- }
- regno_reg_rtx[REGNO (x)] = x;
- }
- return;
-
- case MEM:
- if (GET_CODE (XEXP (x, 0)) == REG)
- mark_reg_pointer (XEXP (x, 0));
- restore_reg_data_1 (XEXP (x, 0));
- return;
- }
-
- /* Now scan the subexpressions recursively. */
-
- format_ptr = GET_RTX_FORMAT (code);
-
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- {
- switch (*format_ptr++)
- {
- case 'e':
- restore_reg_data_1 (XEXP (x, i));
- break;
-
- case 'E':
- if (XVEC (x, i) != NULL)
- {
- register int j;
-
- for (j = 0; j < XVECLEN (x, i); j++)
- restore_reg_data_1 (XVECEXP (x, i, j));
- }
- break;
- }
- }
-}
-
/* Initialize data structures and variables in this file
before generating rtl for each function. */
@@ -3244,17 +3267,22 @@ init_emit ()
sequence_element_free_list = 0;
for (i = 0; i < SEQUENCE_RESULT_SIZE; i++)
sequence_result[i] = 0;
+ free_insn = 0;
/* Init the tables that describe all the pseudo regs. */
regno_pointer_flag_length = LAST_VIRTUAL_REGISTER + 101;
regno_pointer_flag
- = (char *) oballoc (regno_pointer_flag_length);
+ = (char *) savealloc (regno_pointer_flag_length);
bzero (regno_pointer_flag, regno_pointer_flag_length);
+ regno_pointer_align
+ = (char *) savealloc (regno_pointer_flag_length);
+ bzero (regno_pointer_align, regno_pointer_flag_length);
+
regno_reg_rtx
- = (rtx *) oballoc (regno_pointer_flag_length * sizeof (rtx));
+ = (rtx *) savealloc (regno_pointer_flag_length * sizeof (rtx));
bzero ((char *) regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx));
/* Put copies of all the virtual register rtx into regno_reg_rtx. */
@@ -3275,6 +3303,23 @@ init_emit ()
REGNO_POINTER_FLAG (VIRTUAL_STACK_DYNAMIC_REGNUM) = 1;
REGNO_POINTER_FLAG (VIRTUAL_OUTGOING_ARGS_REGNUM) = 1;
+#ifdef STACK_BOUNDARY
+ REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
+ REGNO_POINTER_ALIGN (FRAME_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
+ REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM)
+ = STACK_BOUNDARY / BITS_PER_UNIT;
+ REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT;
+
+ REGNO_POINTER_ALIGN (VIRTUAL_INCOMING_ARGS_REGNUM)
+ = STACK_BOUNDARY / BITS_PER_UNIT;
+ REGNO_POINTER_ALIGN (VIRTUAL_STACK_VARS_REGNUM)
+ = STACK_BOUNDARY / BITS_PER_UNIT;
+ REGNO_POINTER_ALIGN (VIRTUAL_STACK_DYNAMIC_REGNUM)
+ = STACK_BOUNDARY / BITS_PER_UNIT;
+ REGNO_POINTER_ALIGN (VIRTUAL_OUTGOING_ARGS_REGNUM)
+ = STACK_BOUNDARY / BITS_PER_UNIT;
+#endif
+
#ifdef INIT_EXPANDERS
INIT_EXPANDERS;
#endif
@@ -3392,6 +3437,11 @@ init_emit_once (line_numbers)
else
arg_pointer_rtx = gen_rtx (REG, Pmode, ARG_POINTER_REGNUM);
+#ifdef RETURN_ADDRESS_POINTER_REGNUM
+ return_address_pointer_rtx = gen_rtx (REG, Pmode,
+ RETURN_ADDRESS_POINTER_REGNUM);
+#endif
+
/* Create the virtual registers. Do so here since the following objects
might reference them. */
diff --git a/gnu/usr.bin/gcc/enquire.c b/gnu/usr.bin/gcc/enquire.c
index 763b1a44c9d..178d029d192 100644
--- a/gnu/usr.bin/gcc/enquire.c
+++ b/gnu/usr.bin/gcc/enquire.c
@@ -1,5 +1,5 @@
/* Everything you wanted to know about your machine and C compiler,
- but didn't know who to ask. */
+ but didn't know who to ask. */
#ifndef VERSION
#define VERSION "4.3"
@@ -307,7 +307,7 @@
#endif /* NO_FILE */
#endif /* FILENAME */
-/* If PASS isn't defined, then this is the first pass over this file. */
+/* If PASS isn't defined, then this is the first pass over this file. */
#ifndef PASS
#ifndef SEP
#define PASS 1
@@ -387,6 +387,11 @@
#endif /* STDC */
/* include files */
+/* Stdio.h might include limits.h, and limits.h might include float.h, and
+ float.h is probably the float.h put together by the gcc makefile to
+ cause errors. We use our special define to assure float.h that we don't
+ really need it. */
+#define __GCC_FLOAT_NOT_NEEDED
#include <stdio.h>
#ifdef STDC
@@ -416,6 +421,13 @@
#ifdef VERIFY
#include "limits.h"
+#endif
+
+#ifndef SYS_FLOAT_H_WRAP
+#define SYS_FLOAT_H_WRAP 0
+#endif
+
+#if SYS_FLOAT_H_WRAP || defined VERIFY
#include "float.h"
#endif
@@ -472,7 +484,8 @@ Procedure endian ARGS((int bits_per_byte));
int exponent ARGS((Long_double x, double *fract, int *exp));
int floor_log ARGS((int base, Long_double x));
Procedure f_define ARGS((char *desc, char *extra, char *sort, char *name,
- int prec, Long_double val, char *mark));
+ int prec, Long_double val, Long_double req,
+ char *mark));
Procedure i_define ARGS((char *desc, char *extra, char *sort, char *name,
long val, long lim, long req, char *mark));
Procedure u_define ARGS((char *desc, char *extra, char *sort, char *name,
@@ -615,7 +628,7 @@ Procedure croak(place) int place; {
farewell(bugs+1); /* An exit isn't essential here, but avoids loops */
}
-/* This is here in case alloca.c is used, which calls this. */
+/* This is here in case alloca.c is used, which calls this. */
char *xmalloc(size) unsigned size; {
char *value = (char *)malloc(size);
if (value == 0) {
@@ -699,6 +712,8 @@ int main(argc, argv) int argc; char *argv[]; {
if (F) {
printf ("#ifndef _FLOAT_H___\n");
printf ("#define _FLOAT_H___\n");
+ if (SYS_FLOAT_H_WRAP)
+ printf ("#include_next <float.h>\n");
}
#ifdef ID
printf("%sProduced on %s by enquire version %s, CWI, Amsterdam%s\n",
@@ -767,7 +782,7 @@ int main(argc, argv) int argc; char *argv[]; {
size/=2;
}
- Vprintf("%sMemory mallocatable ~= %ld Kbytes%s\n",
+ Vprintf("%sMemory allocable ~= %ld Kbytes%s\n",
co, (total+511)/512, oc);
}
#endif
@@ -793,6 +808,8 @@ Procedure describe(description, extra) char *description, *extra; {
Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
char *desc, *extra, *sort, *name; long val, lim, req; char *mark; {
+ if (SYS_FLOAT_H_WRAP && F && val == req)
+ return;
/* Produce a #define for a signed int type */
describe(desc, extra);
printf("#undef %s%s\n", sort, name);
@@ -801,21 +818,19 @@ Procedure i_define(desc, extra, sort, name, val, lim, req, mark)
} else if (val + lim < 0) {
/* We may not produce a constant like -1024 if the max
allowable value is 1023. It has then to be output as
- -1023-1. lim is the max allowable value. */
+ -1023-1. lim is the max allowable value. */
printf("#define %s%s (%ld%s%ld%s)\n",
sort, name, -lim, mark, val+lim, mark);
} else {
printf("#define %s%s (%ld%s)\n", sort, name, val, mark);
}
- /* If VERIFY is not set, val and req are just the same value;
- if it is set, val is the value as calculated, and req is
- the #defined constant
- */
+#ifdef VERIFY
if (val != req) {
printf("%s*** Verify failed for above #define!\n", co);
printf(" Compiler has %ld for value%s\n\n", req, oc);
bugs++;
}
+#endif
Vprintf("\n");
}
@@ -825,17 +840,21 @@ Procedure u_define(desc, extra, sort, name, val, req, mark)
describe(desc, extra);
printf("#undef %s%s\n", sort, name);
printf("#define %s%s %lu%s%s\n", sort, name, val, U, mark);
+#ifdef VERIFY
if (val != req) {
printf("%s*** Verify failed for above #define!\n", co);
printf(" Compiler has %lu for value%s\n\n", req, oc);
bugs++;
}
+#endif
Vprintf("\n");
}
-Procedure f_define(desc, extra, sort, name, precision, val, mark)
+Procedure f_define(desc, extra, sort, name, precision, val, req, mark)
char *desc, *extra, *sort, *name; int precision;
- Long_double val; char *mark; {
+ Long_double val, req; char *mark; {
+ if (SYS_FLOAT_H_WRAP && F && val == req)
+ return;
/* Produce a #define for a float/double/long double */
describe(desc, extra);
printf ("#undef %s%s\n", sort, name);
@@ -927,7 +946,7 @@ char *fake_f_rep(type, val) char *type; Long_double val; {
union { unsigned int i[4]; Long_double ld;} u;
u.i[0] = u.i[1] = u.i[2] = u.i[3] = 0;
u.ld = val;
- sprintf(buf, "(__extension__ ((union __convert_long_double) {0x%x, 0x%x, 0x%x, 0x%x}).__convert_long_double_d)",
+ sprintf(buf, "(__extension__ ((union __convert_long_double) {__convert_long_double_i: {0x%x, 0x%x, 0x%x, 0x%x}}).__convert_long_double_d)",
u.i[0], u.i[1], u.i[2], u.i[3]);
return buf;
}
@@ -1085,7 +1104,7 @@ int promotions() {
eek_a_bug("promotions don't work properly in conditional expressions\n");
}
- showtype("unsigned short promotes to", Promoted((unsigned short)0));
+ showtype("unsigned short promotes to", Promoted((unsigned short) 0));
showtype("long+unsigned gives", sl+ui);
return 0;
}
@@ -1103,7 +1122,7 @@ Procedure check_defines() {
usign= Signed;
#else
/* Implementations promote unsigned short differently */
- usign= is_signed((unsigned short)0);
+ usign= is_signed((unsigned short) 0);
#endif
if (L) {
@@ -1549,7 +1568,7 @@ if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
/* Alignment constants ********************************************/
#define alignment(TYPE) \
- ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *)0))
+ ((long)((char *)&((struct{char c; TYPE d;}*)0)->d - (char *) 0))
Vprintf("\n%sALIGNMENTS%s\n", co, oc);
@@ -1585,18 +1604,20 @@ if (V) printf ("%s%s %s %s%s\n", co, "Type size_t is",
Vprintf("\n%sPROPERTIES OF POINTERS%s\n", co, oc);
- if ((long) (char *) &variable == (long) (int *) &variable)
+ if ((long) (char *) &variable == (long) (int *) &variable) {
Vprintf("%sChar and int pointer formats seem identical%s\n",
co, oc);
- else
+ } else {
Vprintf("%sChar and int pointer formats are different%s\n",
co, oc);
- if ((long) (char *) &variable == (long) (function *) &variable)
+ }
+ if ((long) (char *) &variable == (long) (function *) &variable) {
Vprintf("%sChar and function pointer formats seem identical%s\n",
co, oc);
- else
+ } else {
Vprintf("%sChar and function pointer formats are different%s\n",
co, oc);
+ }
if (V) {
if ("abcd"=="abcd")
@@ -1740,7 +1761,6 @@ extern char *f_rep();
#define UPROP usprop
#define Uname "USHRT"
-#ifdef VERIFY
#ifdef SHRT_MAX
#define I_MAX SHRT_MAX
#endif
@@ -1784,7 +1804,6 @@ extern char *f_rep();
#ifdef FLT_MAX_10_EXP
#define F_MAX_10_EXP FLT_MAX_10_EXP
#endif
-#endif /* VERIFY */
#endif /* PASS1 */
@@ -1826,7 +1845,6 @@ extern char *f_rep();
#define UPROP uiprop
#define Uname "UINT"
-#ifdef VERIFY
#ifdef INT_MAX
#define I_MAX INT_MAX
#endif
@@ -1864,7 +1882,6 @@ extern char *f_rep();
#ifdef DBL_MAX_10_EXP
#define F_MAX_10_EXP DBL_MAX_10_EXP
#endif
-#endif /* VERIFY */
#endif /* PASS2 */
@@ -1912,7 +1929,6 @@ extern char *f_rep();
#define UPROP ulprop
#define Uname "ULONG"
-#ifdef VERIFY
#ifdef LONG_MAX
#define I_MAX LONG_MAX
#endif
@@ -1950,52 +1966,53 @@ extern char *f_rep();
#ifdef LDBL_MAX_10_EXP
#define F_MAX_10_EXP LDBL_MAX_10_EXP
#endif
-#endif /* VERIFY */
#endif /* PASS3 */
+#define UNDEFINED (-2)
+
#ifndef I_MAX
-#define I_MAX int_max
+#define I_MAX ((unsigned long) UNDEFINED)
#endif
#ifndef I_MIN
-#define I_MIN int_min
+#define I_MIN ((unsigned long) UNDEFINED)
#endif
#ifndef U_MAX
-#define U_MAX u_max
+#define U_MAX ((unsigned long) UNDEFINED)
#endif
#ifndef F_RADIX
-#define F_RADIX f_radix
+#define F_RADIX UNDEFINED
#endif
#ifndef F_MANT_DIG
-#define F_MANT_DIG f_mant_dig
+#define F_MANT_DIG UNDEFINED
#endif
#ifndef F_DIG
-#define F_DIG f_dig
+#define F_DIG UNDEFINED
#endif
#ifndef F_ROUNDS
-#define F_ROUNDS f_rounds
+#define F_ROUNDS UNDEFINED
#endif
#ifndef F_EPSILON
-#define F_EPSILON f_epsilon
+#define F_EPSILON ((Number) UNDEFINED)
#endif
#ifndef F_MIN_EXP
-#define F_MIN_EXP f_min_exp
+#define F_MIN_EXP UNDEFINED
#endif
#ifndef F_MIN
-#define F_MIN f_min
+#define F_MIN ((Number) UNDEFINED)
#endif
#ifndef F_MIN_10_EXP
-#define F_MIN_10_EXP f_min_10_exp
+#define F_MIN_10_EXP UNDEFINED
#endif
#ifndef F_MAX_EXP
-#define F_MAX_EXP f_max_exp
+#define F_MAX_EXP UNDEFINED
#endif
#ifndef F_MAX
-#define F_MAX f_max
+#define F_MAX ((Number) UNDEFINED)
#endif
#ifndef F_MAX_10_EXP
-#define F_MAX_10_EXP f_max_10_exp
+#define F_MAX_10_EXP UNDEFINED
#endif
#ifndef VERIFY
@@ -2400,7 +2417,9 @@ int FPROP(bits_per_byte) int bits_per_byte; {
}
if (PASS == 1) { /* only for FLT */
flt_rounds= f_rounds;
- if (F)
+ /* Prefer system float.h definition of F_ROUNDS,
+ since it's more likely to be right than our "1". */
+ if (F && (!SYS_FLOAT_H_WRAP || F_ROUNDS == UNDEFINED))
i_define(D_FLT_ROUNDS, "", "FLT", "_ROUNDS",
(long) f_rounds, 1L, (long) F_ROUNDS, "");
} else if (f_rounds != flt_rounds) {
@@ -2487,7 +2506,9 @@ int FPROP(bits_per_byte) int bits_per_byte; {
/* Possible loss of precision warnings here from non-stdc compilers */
if (F) f_define(D_EPSILON, thing,
- Fname, "_EPSILON", digs, (Long_double) f_epsilon, MARK);
+ Fname, "_EPSILON", digs,
+ (Long_double) f_epsilon,
+ (Long_double) F_EPSILON, MARK);
if (V || F) F_check(digs, (Long_double) f_epsilon);
Unexpected(21);
if (F) Validate(digs, (Long_double) f_epsilon, (Long_double) F_EPSILON,
@@ -2565,7 +2586,9 @@ int FPROP(bits_per_byte) int bits_per_byte; {
/* Possible loss of precision warnings here from non-stdc compilers */
if (setjmp(lab) == 0) {
if (F) f_define(D_MIN, thing,
- Fname, "_MIN", digs, (Long_double) f_min, MARK);
+ Fname, "_MIN", digs,
+ (Long_double) f_min,
+ (Long_double) F_MIN, MARK);
if (V || F) F_check(digs, (Long_double) f_min);
} else {
eek_a_bug("xxx_MIN caused a trap");
@@ -2659,7 +2682,9 @@ int FPROP(bits_per_byte) int bits_per_byte; {
if (setjmp(lab)==0) {
/* Possible loss of precision warnings here from non-stdc compilers */
if (F) f_define(D_MAX, thing,
- Fname, "_MAX", digs, (Long_double) f_max, MARK);
+ Fname, "_MAX", digs,
+ (Long_double) f_max,
+ (Long_double) F_MAX, MARK);
if (V || F) F_check(digs, (Long_double) f_max);
} else {
eek_a_bug("xxx_MAX caused a trap");
@@ -2686,7 +2711,7 @@ int FPROP(bits_per_byte) int bits_per_byte; {
mantbits=floor_log(2, (Long_double)f_radix)*f_mant_dig;
if (mantbits == 64
&& iexp == 15
- && f_max_exp+f_min_exp > 0 /* ??? f_min_exp may be wrong. */
+ && f_max_exp+f_min_exp > 0 /* ??? f_min_exp may be wrong. */
&& mantbits+iexp+17 == (int)sizeof(Number)*bits_per_byte) {
Vprintf("%sArithmetic probably doesn't use a hidden bit%s\n", co, oc);
Vprintf("%sIt's probably 80387 or 68881 extended real%s\n", co, oc);
diff --git a/gnu/usr.bin/gcc/explow.c b/gnu/usr.bin/gcc/explow.c
index 1491217cb93..fd75ecf331c 100644
--- a/gnu/usr.bin/gcc/explow.c
+++ b/gnu/usr.bin/gcc/explow.c
@@ -1,5 +1,5 @@
/* Subroutines for manipulating rtx's in semantically interesting ways.
- Copyright (C) 1987, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "tree.h"
#include "flags.h"
@@ -31,7 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-codes.h"
static rtx break_out_memory_refs PROTO((rtx));
-
+static void emit_stack_probe PROTO((rtx));
/* Return an rtx for the sum of X and the integer C.
This function should be used via the `plus_constant' macro. */
@@ -78,10 +79,15 @@ plus_constant_wide (x, c)
if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
{
+ /* Any rtl we create here must go in a saveable obstack, since
+ we might have been called from within combine. */
+ push_obstacks_nochange ();
+ rtl_in_saveable_obstack ();
tem
= force_const_mem (GET_MODE (x),
plus_constant (get_pool_constant (XEXP (x, 0)),
c));
+ pop_obstacks ();
if (memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
return tem;
}
@@ -119,6 +125,10 @@ plus_constant_wide (x, c)
return gen_rtx (PLUS, mode,
XEXP (x, 0),
plus_constant (XEXP (x, 1), c));
+ break;
+
+ default:
+ break;
}
if (c != 0)
@@ -251,7 +261,8 @@ expr_size (exp)
&& contains_placeholder_p (size))
size = build (WITH_RECORD_EXPR, sizetype, size, exp);
- return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
+ return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype),
+ EXPAND_MEMORY_USE_BAD);
}
/* Return a copy of X in which all memory references
@@ -304,8 +315,11 @@ convert_memory_address (to_mode, x)
enum machine_mode to_mode;
rtx x;
{
+ enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
rtx temp;
+ /* Here we handle some special cases. If none of them apply, fall through
+ to the default case. */
switch (GET_CODE (x))
{
case CONST_INT:
@@ -313,28 +327,41 @@ convert_memory_address (to_mode, x)
return x;
case LABEL_REF:
- return gen_rtx (LABEL_REF, to_mode, XEXP (x, 0));
+ temp = gen_rtx (LABEL_REF, to_mode, XEXP (x, 0));
+ LABEL_REF_NONLOCAL_P (temp) = LABEL_REF_NONLOCAL_P (x);
+ return temp;
case SYMBOL_REF:
temp = gen_rtx (SYMBOL_REF, to_mode, XSTR (x, 0));
SYMBOL_REF_FLAG (temp) = SYMBOL_REF_FLAG (x);
+ CONSTANT_POOL_ADDRESS_P (temp) = CONSTANT_POOL_ADDRESS_P (x);
return temp;
- case PLUS:
- case MULT:
- return gen_rtx (GET_CODE (x), to_mode,
- convert_memory_address (to_mode, XEXP (x, 0)),
- convert_memory_address (to_mode, XEXP (x, 1)));
-
case CONST:
return gen_rtx (CONST, to_mode,
convert_memory_address (to_mode, XEXP (x, 0)));
+ case PLUS:
+ case MULT:
+ /* For addition the second operand is a small constant, we can safely
+ permute the conversion and addition operation. We can always safely
+ permute them if we are making the address narrower. In addition,
+ always permute the operations if this is a constant. */
+ if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
+ || (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && (INTVAL (XEXP (x, 1)) + 20000 < 40000
+ || CONSTANT_P (XEXP (x, 0)))))
+ return gen_rtx (GET_CODE (x), to_mode,
+ convert_memory_address (to_mode, XEXP (x, 0)),
+ convert_memory_address (to_mode, XEXP (x, 1)));
+ break;
+
default:
- return convert_modes (to_mode,
- to_mode == ptr_mode ? Pmode : ptr_mode,
- x, POINTERS_EXTEND_UNSIGNED);
+ break;
}
+
+ return convert_modes (to_mode, from_mode,
+ x, POINTERS_EXTEND_UNSIGNED);
}
#endif
@@ -388,6 +415,9 @@ memory_address (mode, x)
{
register rtx oldx = x;
+ if (GET_CODE (x) == ADDRESSOF)
+ return x;
+
#ifdef POINTERS_EXTEND_UNSIGNED
if (GET_MODE (x) == ptr_mode)
x = convert_memory_address (Pmode, x);
@@ -493,11 +523,11 @@ memory_address (mode, x)
if (oldx == x)
return x;
else if (GET_CODE (x) == REG)
- mark_reg_pointer (x);
+ mark_reg_pointer (x, 1);
else if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == REG
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
- mark_reg_pointer (XEXP (x, 0));
+ mark_reg_pointer (XEXP (x, 0), 1);
/* OLDX may have been the address on a temporary. Update the address
to indicate that X is now used. */
@@ -723,11 +753,15 @@ promote_mode (type, mode, punsignedp, for_call)
#endif
#ifdef POINTERS_EXTEND_UNSIGNED
+ case REFERENCE_TYPE:
case POINTER_TYPE:
mode = Pmode;
unsignedp = POINTERS_EXTEND_UNSIGNED;
break;
#endif
+
+ default:
+ break;
}
*punsignedp = unsignedp;
@@ -806,7 +840,8 @@ round_push (size)
else
{
/* CEIL_DIV_EXPR needs to worry about the addition overflowing,
- but we know it can't. So add ourselves and then do TRUNC_DIV_EXPR. */
+ but we know it can't. So add ourselves and then do
+ TRUNC_DIV_EXPR. */
size = expand_binop (Pmode, add_optab, size, GEN_INT (align - 1),
NULL_RTX, 1, OPTAB_LIB_WIDEN);
size = expand_divmod (0, TRUNC_DIV_EXPR, Pmode, size, GEN_INT (align),
@@ -866,6 +901,8 @@ emit_stack_save (save_level, psave, after)
}
break;
#endif
+ default:
+ break;
}
/* If there is no save area and we have to allocate one, do so. Otherwise
@@ -946,6 +983,8 @@ emit_stack_restore (save_level, sa, after)
fcn = gen_restore_stack_nonlocal;
break;
#endif
+ default:
+ break;
}
if (sa != 0)
@@ -1008,7 +1047,7 @@ allocate_dynamic_stack_space (size, target, known_align)
If we have to align, we must leave space in SIZE for the hole
that might result from the alignment operation. */
-#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) || defined (ALLOCATE_OUTGOING_ARGS) || ! defined (STACK_BOUNDARY)
+#if defined (STACK_DYNAMIC_OFFSET) || defined (STACK_POINTER_OFFSET) || ! defined (STACK_BOUNDARY)
#define MUST_ALIGN 1
#else
#define MUST_ALIGN (STACK_BOUNDARY < BIGGEST_ALIGNMENT)
@@ -1065,50 +1104,57 @@ allocate_dynamic_stack_space (size, target, known_align)
do_pending_stack_adjust ();
+ /* If needed, check that we have the required amount of stack. Take into
+ account what has already been checked. */
+ if (flag_stack_check && ! STACK_CHECK_BUILTIN)
+ probe_stack_range (STACK_CHECK_MAX_FRAME_SIZE + STACK_CHECK_PROTECT, size);
+
/* Don't use a TARGET that isn't a pseudo. */
if (target == 0 || GET_CODE (target) != REG
|| REGNO (target) < FIRST_PSEUDO_REGISTER)
target = gen_reg_rtx (Pmode);
- mark_reg_pointer (target);
-
-#ifndef STACK_GROWS_DOWNWARD
- emit_move_insn (target, virtual_stack_dynamic_rtx);
-#endif
+ mark_reg_pointer (target, known_align / BITS_PER_UNIT);
/* Perform the required allocation from the stack. Some systems do
this differently than simply incrementing/decrementing from the
- stack pointer. */
+ stack pointer, such as acquiring the space by calling malloc(). */
#ifdef HAVE_allocate_stack
if (HAVE_allocate_stack)
{
- enum machine_mode mode
- = insn_operand_mode[(int) CODE_FOR_allocate_stack][0];
-
- size = convert_modes (mode, ptr_mode, size, 1);
+ enum machine_mode mode;
if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][0]
&& ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][0])
+ (target, Pmode)))
+ target = copy_to_mode_reg (Pmode, target);
+ mode = insn_operand_mode[(int) CODE_FOR_allocate_stack][1];
+ size = convert_modes (mode, ptr_mode, size, 1);
+ if (insn_operand_predicate[(int) CODE_FOR_allocate_stack][1]
+ && ! ((*insn_operand_predicate[(int) CODE_FOR_allocate_stack][1])
(size, mode)))
size = copy_to_mode_reg (mode, size);
- emit_insn (gen_allocate_stack (size));
+ emit_insn (gen_allocate_stack (target, size));
}
else
#endif
{
+#ifndef STACK_GROWS_DOWNWARD
+ emit_move_insn (target, virtual_stack_dynamic_rtx);
+#endif
size = convert_modes (Pmode, ptr_mode, size, 1);
anti_adjust_stack (size);
- }
-
#ifdef STACK_GROWS_DOWNWARD
emit_move_insn (target, virtual_stack_dynamic_rtx);
#endif
+ }
if (MUST_ALIGN)
{
/* CEIL_DIV_EXPR needs to worry about the addition overflowing,
- but we know it can't. So add ourselves and then do TRUNC_DIV_EXPR. */
+ but we know it can't. So add ourselves and then do
+ TRUNC_DIV_EXPR. */
target = expand_binop (Pmode, add_optab, target,
GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1),
NULL_RTX, 1, OPTAB_LIB_WIDEN);
@@ -1134,6 +1180,137 @@ allocate_dynamic_stack_space (size, target, known_align)
return target;
}
+/* Emit one stack probe at ADDRESS, an address within the stack. */
+
+static void
+emit_stack_probe (address)
+ rtx address;
+{
+ rtx memref = gen_rtx (MEM, word_mode, address);
+
+ MEM_VOLATILE_P (memref) = 1;
+
+ if (STACK_CHECK_PROBE_LOAD)
+ emit_move_insn (gen_reg_rtx (word_mode), memref);
+ else
+ emit_move_insn (memref, const0_rtx);
+}
+
+/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
+ FIRST is a constant and size is a Pmode RTX. These are offsets from the
+ current stack pointer. STACK_GROWS_DOWNWARD says whether to add or
+ subtract from the stack. If SIZE is constant, this is done
+ with a fixed number of probes. Otherwise, we must make a loop. */
+
+#ifdef STACK_GROWS_DOWNWARD
+#define STACK_GROW_OP MINUS
+#else
+#define STACK_GROW_OP PLUS
+#endif
+
+void
+probe_stack_range (first, size)
+ HOST_WIDE_INT first;
+ rtx size;
+{
+ /* First see if we have an insn to check the stack. Use it if so. */
+#ifdef HAVE_check_stack
+ if (HAVE_check_stack)
+ {
+ rtx last_addr = force_operand (gen_rtx (STACK_GROW_OP, Pmode,
+ stack_pointer_rtx,
+ plus_constant (size, first)),
+ NULL_RTX);
+
+ if (insn_operand_predicate[(int) CODE_FOR_check_stack][0]
+ && ! ((*insn_operand_predicate[(int) CODE_FOR_check_stack][0])
+ (last_address, Pmode)))
+ last_address = copy_to_mode_reg (Pmode, last_address);
+
+ emit_insn (gen_check_stack (last_address));
+ return;
+ }
+#endif
+
+ /* If we have to generate explicit probes, see if we have a constant
+ small number of them to generate. If so, that's the easy case. */
+ if (GET_CODE (size) == CONST_INT && INTVAL (size) < 10)
+ {
+ HOST_WIDE_INT offset;
+
+ /* Start probing at FIRST + N * STACK_CHECK_PROBE_INTERVAL
+ for values of N from 1 until it exceeds LAST. If only one
+ probe is needed, this will not generate any code. Then probe
+ at LAST. */
+ for (offset = first + STACK_CHECK_PROBE_INTERVAL;
+ offset < INTVAL (size);
+ offset = offset + STACK_CHECK_PROBE_INTERVAL)
+ emit_stack_probe (gen_rtx (STACK_GROW_OP, Pmode,
+ stack_pointer_rtx, GEN_INT (offset)));
+
+ emit_stack_probe (gen_rtx (STACK_GROW_OP, Pmode, stack_pointer_rtx,
+ plus_constant (size, first)));
+ }
+
+ /* In the variable case, do the same as above, but in a loop. We emit loop
+ notes so that loop optimization can be done. */
+ else
+ {
+ rtx test_addr
+ = force_operand (gen_rtx (STACK_GROW_OP, Pmode, stack_pointer_rtx,
+ GEN_INT (first
+ + STACK_CHECK_PROBE_INTERVAL)),
+ NULL_RTX);
+ rtx last_addr
+ = force_operand (gen_rtx (STACK_GROW_OP, Pmode, stack_pointer_rtx,
+ plus_constant (size, first)),
+ NULL_RTX);
+ rtx incr = GEN_INT (STACK_CHECK_PROBE_INTERVAL);
+ rtx loop_lab = gen_label_rtx ();
+ rtx test_lab = gen_label_rtx ();
+ rtx end_lab = gen_label_rtx ();
+ rtx temp;
+
+ if (GET_CODE (test_addr) != REG
+ || REGNO (test_addr) < FIRST_PSEUDO_REGISTER)
+ test_addr = force_reg (Pmode, test_addr);
+
+ emit_note (NULL_PTR, NOTE_INSN_LOOP_BEG);
+ emit_jump (test_lab);
+
+ emit_label (loop_lab);
+ emit_stack_probe (test_addr);
+
+ emit_note (NULL_PTR, NOTE_INSN_LOOP_CONT);
+
+#ifdef STACK_GROWS_DOWNWARD
+#define CMP_OPCODE GTU
+ temp = expand_binop (Pmode, sub_optab, test_addr, incr, test_addr,
+ 1, OPTAB_WIDEN);
+#else
+#define CMP_OPCODE LTU
+ temp = expand_binop (Pmode, add_optab, test_addr, incr, test_addr,
+ 1, OPTAB_WIDEN);
+#endif
+
+ if (temp != test_addr)
+ abort ();
+
+ emit_label (test_lab);
+ emit_cmp_insn (test_addr, last_addr, CMP_OPCODE, NULL_RTX, Pmode, 1, 0);
+ emit_jump_insn ((*bcc_gen_fctn[(int) CMP_OPCODE]) (loop_lab));
+ emit_jump (end_lab);
+ emit_note (NULL_PTR, NOTE_INSN_LOOP_END);
+ emit_label (end_lab);
+
+ /* If will be doing stupid optimization, show test_addr is still live. */
+ if (obey_regdecls)
+ emit_insn (gen_rtx (USE, VOIDmode, test_addr));
+
+ emit_stack_probe (last_addr);
+ }
+}
+
/* Return an rtx representing the register or memory location
in which a scalar value of data type VALTYPE
was returned by a function call to function FUNC.
diff --git a/gnu/usr.bin/gcc/expr.h b/gnu/usr.bin/gcc/expr.h
index cac73819602..8fafea2fef3 100644
--- a/gnu/usr.bin/gcc/expr.h
+++ b/gnu/usr.bin/gcc/expr.h
@@ -1,5 +1,5 @@
/* Definitions for code generation pass of GNU compiler.
- Copyright (C) 1987, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,13 +18,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. */
-
-#ifndef __STDC__
-#ifndef const
-#define const
-#endif
-#endif
-
/* The default branch cost is 1. */
#ifndef BRANCH_COST
#define BRANCH_COST 1
@@ -52,9 +45,27 @@ Boston, MA 02111-1307, USA. */
EXPAND_SUM means it is ok to return a PLUS rtx or MULT rtx.
EXPAND_INITIALIZER is similar but also record any labels on forced_labels.
EXPAND_CONST_ADDRESS means it is ok to return a MEM whose address
- is a constant that is not a legitimate address. */
+ is a constant that is not a legitimate address.
+ EXPAND_MEMORY_USE_* are explained below. */
enum expand_modifier {EXPAND_NORMAL, EXPAND_SUM,
- EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER};
+ EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER,
+ EXPAND_MEMORY_USE_WO, EXPAND_MEMORY_USE_RW,
+ EXPAND_MEMORY_USE_BAD, EXPAND_MEMORY_USE_DONT};
+
+/* Argument for chkr_* functions.
+ MEMORY_USE_RO: the pointer reads memory.
+ MEMORY_USE_WO: the pointer writes to memory.
+ MEMORY_USE_RW: the pointer modifies memory (ie it reads and writes). An
+ example is (*ptr)++
+ MEMORY_USE_BAD: use this if you don't know the behavior of the pointer, or
+ if you know there are no pointers. Using an INDIRECT_REF
+ with MEMORY_USE_BAD will abort.
+ MEMORY_USE_TW: just test for writing, without update. Special.
+ MEMORY_USE_DONT: the memory is neither read nor written. This is used by
+ '->' and '.'. */
+enum memory_use_mode {MEMORY_USE_BAD = 0, MEMORY_USE_RO = 1,
+ MEMORY_USE_WO = 2, MEMORY_USE_RW = 3,
+ MEMORY_USE_TW = 6, MEMORY_USE_DONT = 99};
/* List of labels that must never be deleted. */
extern rtx forced_labels;
@@ -115,12 +126,6 @@ extern tree nonlocal_labels;
These are the arguments to function calls that have already returned. */
extern int pending_stack_adjust;
-/* A list of all cleanups which belong to the arguments of
- function calls being expanded by expand_call. */
-#ifdef TREE_CODE /* Don't lose if tree.h not included. */
-extern tree cleanups_this_call;
-#endif
-
/* When temporaries are created by TARGET_EXPRs, they are created at
this level of temp_slot_level, so that they can remain allocated
until no longer needed. CLEANUP_POINT_EXPRs define the lifetime
@@ -163,7 +168,7 @@ struct args_size
((SIZE).var == 0 ? GEN_INT ((SIZE).constant) \
: expand_expr (size_binop (PLUS_EXPR, (SIZE).var, \
size_int ((SIZE).constant)), \
- NULL_RTX, VOIDmode, 0))
+ NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD))
/* Convert the implicit sum in a `struct args_size' into a tree. */
#define ARGS_SIZE_TREE(SIZE) \
@@ -228,6 +233,46 @@ enum direction {none, upward, downward}; /* Value has this type. */
#ifndef RETURN_IN_MEMORY
#define RETURN_IN_MEMORY(TYPE) (TYPE_MODE (TYPE) == BLKmode)
#endif
+
+/* Provide default values for the macros controlling stack checking. */
+
+#ifndef STACK_CHECK_BUILTIN
+#define STACK_CHECK_BUILTIN 0
+#endif
+
+/* The default interval is one page. */
+#ifndef STACK_CHECK_PROBE_INTERVAL
+#define STACK_CHECK_PROBE_INTERVAL 4096
+#endif
+
+/* The default is to do a store into the stack. */
+#ifndef STACK_CHECK_PROBE_LOAD
+#define STACK_CHECK_PROBE_LOAD 0
+#endif
+
+/* This value is arbitrary, but should be sufficient for most machines. */
+#ifndef STACK_CHECK_PROTECT
+#define STACK_CHECK_PROTECT (75 * UNITS_PER_WORD)
+#endif
+
+/* Make the maximum frame size be the largest we can and still only need
+ one probe per function. */
+#ifndef STACK_CHECK_MAX_FRAME_SIZE
+#define STACK_CHECK_MAX_FRAME_SIZE \
+ (STACK_CHECK_PROBE_INTERVAL - UNITS_PER_WORD)
+#endif
+
+/* This is arbitrary, but should be large enough everywhere. */
+#ifndef STACK_CHECK_FIXED_FRAME_SIZE
+#define STACK_CHECK_FIXED_FRAME_SIZE (4 * UNITS_PER_WORD)
+#endif
+
+/* Provide a reasonable default for the maximum size of an object to
+ allocate in the fixed frame. We may need to be able to make this
+ controllable by the user at some point. */
+#ifndef STACK_CHECK_MAX_VAR_SIZE
+#define STACK_CHECK_MAX_VAR_SIZE (STACK_CHECK_MAX_FRAME_SIZE / 100)
+#endif
/* Optabs are tables saying how to generate insn bodies
for various machine modes and numbers of operands.
@@ -365,6 +410,14 @@ extern rtx bcmp_libfunc;
extern rtx memset_libfunc;
extern rtx bzero_libfunc;
+extern rtx throw_libfunc;
+extern rtx sjthrow_libfunc;
+extern rtx sjpopnthrow_libfunc;
+extern rtx terminate_libfunc;
+extern rtx setjmp_libfunc;
+extern rtx longjmp_libfunc;
+extern rtx get_dynamic_handler_chain_libfunc;
+
extern rtx eqhf2_libfunc;
extern rtx nehf2_libfunc;
extern rtx gthf2_libfunc;
@@ -447,6 +500,13 @@ extern rtx fixunsxfti_libfunc;
extern rtx fixunstfsi_libfunc;
extern rtx fixunstfdi_libfunc;
extern rtx fixunstfti_libfunc;
+
+/* For check-memory-usage. */
+extern rtx chkr_check_addr_libfunc;
+extern rtx chkr_set_right_libfunc;
+extern rtx chkr_copy_bitmap_libfunc;
+extern rtx chkr_check_exec_libfunc;
+extern rtx chkr_check_str_libfunc;
typedef rtx (*rtxfun) ();
@@ -471,6 +531,9 @@ extern enum insn_code movcc_gen_code[NUM_MACHINE_MODES];
/* This array records the insn_code of insns to perform block moves. */
extern enum insn_code movstr_optab[NUM_MACHINE_MODES];
+/* This array records the insn_code of insns to perform block clears. */
+extern enum insn_code clrstr_optab[NUM_MACHINE_MODES];
+
/* Define functions given in optabs.c. */
/* Expand a binary operation given optab and rtx operands. */
@@ -582,6 +645,10 @@ extern rtx expand_and PROTO((rtx, rtx, rtx));
extern rtx emit_store_flag PROTO((rtx, enum rtx_code, rtx, rtx,
enum machine_mode, int, int));
+/* Like emit_store_flag, but always succeeds. */
+extern rtx emit_store_flag_force PROTO((rtx, enum rtx_code, rtx, rtx,
+ enum machine_mode, int, int));
+
/* Functions from loop.c: */
/* Given a JUMP_INSN, return a description of the test being made. */
@@ -614,7 +681,7 @@ extern rtx convert_to_mode PROTO((enum machine_mode, rtx, int));
extern rtx convert_modes PROTO((enum machine_mode, enum machine_mode, rtx, int));
/* Emit code to move a block Y to a block X. */
-extern void emit_block_move PROTO((rtx, rtx, rtx, int));
+extern rtx emit_block_move PROTO((rtx, rtx, rtx, int));
/* Copy all or part of a value X into registers starting at REGNO.
The number of registers to be filled is NREGS. */
@@ -624,15 +691,25 @@ extern void move_block_to_reg PROTO((int, rtx, int, enum machine_mode));
The number of registers to be filled is NREGS. */
extern void move_block_from_reg PROTO((int, rtx, int, int));
+/* Load a BLKmode value into non-consecutive registers represented by a
+ PARALLEL. */
+extern void emit_group_load PROTO((rtx, rtx));
+/* Store a BLKmode value from non-consecutive registers represented by a
+ PARALLEL. */
+extern void emit_group_store PROTO((rtx, rtx));
+
/* Mark REG as holding a parameter for the next CALL_INSN. */
-extern void use_reg PROTO((rtx*, rtx));
+extern void use_reg PROTO((rtx *, rtx));
/* Mark NREGS consecutive regs, starting at REGNO, as holding parameters
for the next CALL_INSN. */
-extern void use_regs PROTO((rtx*, int, int));
+extern void use_regs PROTO((rtx *, int, int));
+/* Mark a PARALLEL as holding a parameter for the next CALL_INSN. */
+extern void use_group_regs PROTO((rtx *, rtx));
/* Write zeros through the storage of OBJECT.
- If OBJECT has BLKmode, SIZE is its length in bytes. */
-extern void clear_storage PROTO((rtx, rtx));
+ If OBJECT has BLKmode, SIZE is its length in bytes and ALIGN is its
+ alignment. */
+extern rtx clear_storage PROTO((rtx, rtx, int));
/* Emit insns to set X from Y. */
extern rtx emit_move_insn PROTO((rtx, rtx));
@@ -673,6 +750,8 @@ extern rtx store_expr PROTO((tree, rtx, int));
Useful after calling expand_expr with 1 as sum_ok. */
extern rtx force_operand PROTO((rtx, rtx));
+extern rtx expand_builtin_setjmp PROTO((rtx, rtx));
+
#ifdef TREE_CODE
/* Generate code for computing expression EXP.
An rtx for the computed value is returned. The value is never null.
@@ -693,9 +772,6 @@ extern void clear_pending_stack_adjust PROTO((void));
extern void do_pending_stack_adjust PROTO((void));
#ifdef TREE_CODE
-/* Expand all cleanups up to OLD_CLEANUPS. */
-extern void expand_cleanups_to PROTO((tree));
-
/* Generate code to evaluate EXP and jump to LABEL if the value is zero. */
extern void jumpifnot PROTO((tree, rtx));
@@ -828,8 +904,12 @@ extern void emit_stack_restore PROTO((enum save_level, rtx, rtx));
says how many bytes. */
extern rtx allocate_dynamic_stack_space PROTO((rtx, rtx, int));
-/* Emit code to copy function value to a new temp reg and return that reg. */
-extern rtx function_value ();
+/* Probe a range of stack addresses from FIRST to FIRST+SIZE, inclusive.
+ FIRST is a constant and size is a Pmode RTX. These are offsets from the
+ current stack pointer. STACK_GROWS_DOWNWARD says whether to add or
+ subtract from the stack. If SIZE is constant, this is done
+ with a fixed number of probes. Otherwise, we must make a loop. */
+extern void probe_stack_range PROTO((HOST_WIDE_INT, rtx));
/* Return an rtx that refers to the value returned by a library call
in its original home. This becomes invalid if any more code is emitted. */
@@ -839,12 +919,11 @@ extern rtx hard_libcall_value PROTO((enum machine_mode));
of STACK_BOUNDARY / BITS_PER_UNIT. */
extern rtx round_push PROTO((rtx));
-extern void emit_block_move PROTO((rtx, rtx, rtx, int));
-
extern rtx store_bit_field PROTO((rtx, int, int, enum machine_mode, rtx, int, int));
extern rtx extract_bit_field PROTO((rtx, int, int, int, rtx, enum machine_mode, enum machine_mode, int, int));
extern rtx expand_mult PROTO((enum machine_mode, rtx, rtx, rtx, int));
extern rtx expand_mult_add PROTO((rtx, rtx, rtx, rtx,enum machine_mode, int));
+extern rtx expand_mult_highpart_adjust PROTO((enum machine_mode, rtx, rtx, rtx, rtx, int));
extern rtx assemble_static_space PROTO((int));
@@ -852,3 +931,13 @@ extern rtx assemble_static_space PROTO((int));
It is up to the language front end to install a hook
if it has any such codes that expand_expr needs to know about. */
extern rtx (*lang_expand_expr) ();
+
+#ifdef TREE_CODE
+/* Build bytecode call descriptor for function SUBR. */
+extern rtx bc_build_calldesc PROTO((tree));
+
+/* Emit a type code to be used by the runtime support in handling
+ parameter passing. The type code consists of the machine mode
+ plus the minimal alignment shifted left 8 bits. */
+extern tree bc_runtime_type_code PROTO((tree));
+#endif
diff --git a/gnu/usr.bin/gcc/extend.texi b/gnu/usr.bin/gcc/extend.texi
index e85799c610d..297bc32a0a0 100644
--- a/gnu/usr.bin/gcc/extend.texi
+++ b/gnu/usr.bin/gcc/extend.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
+@c Copyright (C) 1988,89,92,93,94,96 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -62,6 +62,7 @@ C++ Language}, for extensions that apply @emph{only} to C++.
* Incomplete Enums:: @code{enum foo;}, with details to follow.
* Function Names:: Printable strings which are the name of the current
function.
+* Return Address:: Getting the return or frame address of a function.
@end menu
@end ifset
@ifclear INTERNALS
@@ -107,6 +108,7 @@ C++ Language}, for extensions that apply @emph{only} to C++.
* Incomplete Enums:: @code{enum foo;}, with details to follow.
* Function Names:: Printable strings which are the name of the current
function.
+* Return Address:: Getting the return or frame address of a function.
@end menu
@end ifclear
@@ -235,12 +237,12 @@ example:
@section Labels as Values
@cindex labels as values
@cindex computed gotos
-@cindex goto with computed label
+@cindex goto with computed label
@cindex address of a label
You can get the address of a label defined in the current function
(or a containing function) with the unary operator @samp{&&}. The
-value has type @code{void *}. This value is a constant and can be used
+value has type @code{void *}. This value is a constant and can be used
wherever a constant of that type is valid. For example:
@example
@@ -286,7 +288,7 @@ use that rather than an array unless the problem does not fit a
Another use of label values is in an interpreter for threaded code.
The labels within the interpreter function can be stored in the
-threaded code for super-fast dispatching.
+threaded code for super-fast dispatching.
You can use this mechanism to jump to code in a different function. If
you do that, totally unpredictable things will happen. The best way to
@@ -364,9 +366,7 @@ does not refer to anything that has gone out of scope, you should be
safe.
GNU CC implements taking the address of a nested function using a
-technique called @dfn{trampolines}. A paper describing them is
-available from @samp{maya.idiap.ch} in directory @file{pub/tmb},
-file @file{usenix88-lexic.ps.Z}.
+technique called @dfn{trampolines}.
A nested function can jump to a label inherited from a containing
function, provided the label was explicitly declared in the containing
@@ -727,11 +727,11 @@ effects of recomputing it.
@cindex multiprecision arithmetic
GNU C supports data types for integers that are twice as long as
-@code{long int}. Simply write @code{long long int} for a signed
-integer, or @code{unsigned long long int} for an unsigned integer.
-To make an integer constant of type @code{long long int}, add the suffix
-@code{LL} to the integer. To make an integer constant of type
-@code{unsigned long long int}, add the suffix @code{ULL} to the integer.
+@code{int}. Simply write @code{long long int} for a signed integer, or
+@code{unsigned long long int} for an unsigned integer. To make an
+integer constant of type @code{long long int}, add the suffix @code{LL}
+to the integer. To make an integer constant of type @code{unsigned long
+long int}, add the suffix @code{ULL} to the integer.
You can use these types in arithmetic like any other integer types.
Addition, subtraction, and bitwise boolean operations on these types
@@ -783,7 +783,7 @@ the imaginary part is on the stack (or vice-versa). None of the
supported debugging info formats has a way to represent noncontiguous
allocation like this, so GNU CC describes a noncontiguous complex
variable as if it were two separate variables of noncomplex type.
-If the variable's actual name is @code{foo}, the two fictitious
+If the variable's actual name is @code{foo}, the two fictitious
variables are named @code{foo$real} and @code{foo$imag}. You can
examine and set these two fictitious variables with your debugger.
@@ -1017,7 +1017,7 @@ foo (float f, float g)
@cindex constructor expressions
@cindex initializations in expressions
@cindex structures, constructor expression
-@cindex expressions, constructor
+@cindex expressions, constructor
GNU C supports constructor expressions. A constructor looks like
a cast containing an initializer. Its value is an object of the
@@ -1118,7 +1118,7 @@ plus one.
In a structure initializer, specify the name of a field to initialize
with @samp{@var{fieldname}:} before the element value. For example,
-given the following structure,
+given the following structure,
@example
struct point @{ int x, y; @};
@@ -1217,7 +1217,7 @@ write this:
case 1 ... 5:
@end example
-@noindent
+@noindent
rather than this:
@example
@@ -1227,7 +1227,7 @@ case 1...5:
@node Cast to Union
@section Cast to a Union Type
@cindex cast to a union
-@cindex union, casting to a
+@cindex union, casting to a
A cast to union type is similar to other casts, except that the type
specified is a union type. You can specify the type either with
@@ -1333,7 +1333,7 @@ earlier than 2.5. An alternative way to declare that a function does
not return, which works in the current version and in some older
versions, is as follows:
-@smallexample
+@smallexample
typedef void voidfn ();
volatile voidfn fatal;
@@ -1416,6 +1416,34 @@ for the ANSI library functions @code{printf}, @code{fprintf},
warnings are requested (using @samp{-Wformat}), so there is no need to
modify the header file @file{stdio.h}.
+@item format_arg (@var{string-index})
+@cindex @code{format_arg} function attribute
+The @code{format_arg} attribute specifies that a function takes
+@code{printf} or @code{scanf} style arguments, modifies it (for example,
+to translate it into another language), and passes it to a @code{printf}
+or @code{scanf} style function. For example, the declaration:
+
+@smallexample
+extern char *
+my_dgettext (char *my_domain, const char *my_format)
+ __attribute__ ((format_arg (2)));
+@end smallexample
+
+@noindent
+causes the compiler to check the arguments in calls to
+@code{my_dgettext} whose result is passed to a @code{printf} or
+@code{scanf} type function for consistency with the @code{printf} style
+format string argument @code{my_format}.
+
+The parameter @var{string-index} specifies which argument is the format
+string argument (starting from 1).
+
+The @code{format-arg} attribute allows you to identify your own
+functions which modify format strings, so that GNU CC can check the
+calls to @code{printf} and @code{scanf} function whose operands are a
+call to one of your own function. The compiler always treats
+@code{gettext}, @code{dgettext}, and @code{dcgettext} in this manner.
+
@item section ("section-name")
@cindex @code{section} function attribute
Normally, the compiler places the code it generates in the @code{text} section.
@@ -1453,7 +1481,8 @@ These attributes are not currently implemented for Objective C.
@item unused
This attribute, attached to a function, means that the function is meant
to be possibly unused. GNU CC will not produce a warning for this
-function.
+function. GNU C++ does not currently support this attribute as
+definitions without parameters are valid in C++.
@item weak
@cindex @code{weak} attribute
@@ -1477,6 +1506,8 @@ void f () __attribute__ ((weak, alias ("__f")));
declares @samp{f} to be a weak alias for @samp{__f}. In C++, the
mangled name for the target must be used.
+Not all target machines support this attribute.
+
@item regparm (@var{number})
@cindex functions that are passed arguments in registers on the 386
On the Intel 386, the @code{regparm} attribute causes the compiler to
@@ -1491,12 +1522,115 @@ On the Intel 386, the @code{stdcall} attribute causes the compiler to
assume that the called function will pop off the stack space used to
pass arguments, unless it takes a variable number of arguments.
+The PowerPC compiler for Windows NT currently ignores the @code{stdcall}
+attribute.
+
@item cdecl
@cindex functions that do pop the argument stack on the 386
On the Intel 386, the @code{cdecl} attribute causes the compiler to
-assume that the called function will pop off the stack space used to
-pass arguments, unless it takes a variable number of arguments. This is
+assume that the calling function will pop off the stack space used to
+pass arguments. This is
useful to override the effects of the @samp{-mrtd} switch.
+
+The PowerPC compiler for Windows NT currently ignores the @code{cdecl}
+attribute.
+
+@item longcall
+@cindex functions called via pointer on the RS/6000 and PowerPC
+On the RS/6000 and PowerPC, the @code{longcall} attribute causes the
+compiler to always call the function via a pointer, so that functions
+which reside further than 64 megabytes (67,108,864 bytes) from the
+current location can be called.
+
+@item dllimport
+@cindex functions which are imported from a dll on PowerPC Windows NT
+On the PowerPC running Windows NT, the @code{dllimport} attribute causes
+the compiler to call the function via a global pointer to the function
+pointer that is set up by the Windows NT dll library. The pointer name
+is formed by combining @code{__imp_} and the function name.
+
+@item dllexport
+@cindex functions which are exported from a dll on PowerPC Windows NT
+On the PowerPC running Windows NT, the @code{dllexport} attribute causes
+the compiler to provide a global pointer to the function pointer, so
+that it can be called with the @code{dllimport} attribute. The pointer
+name is formed by combining @code{__imp_} and the function name.
+
+@item exception (@var{except-func} [, @var{except-arg}])
+@cindex functions which specify exception handling on PowerPC Windows NT
+On the PowerPC running Windows NT, the @code{exception} attribute causes
+the compiler to modify the structured exception table entry it emits for
+the declared function. The string or identifier @var{except-func} is
+placed in the third entry of the structured exception table. It
+represents a function, which is called by the exception handling
+mechanism if an exception occurs. If it was specified, the string or
+identifier @var{except-arg} is placed in the fourth entry of the
+structured exception table.
+
+@item function_vector
+@cindex calling functions through the function vector on the H8/300 processors
+Use this option on the H8/300 and H8/300H to indicate that the specified
+function should be called through the function vector. Calling a
+function through the function vector will reduce code size, however;
+the function vector has a limited size (maximum 128 entries on the H8/300
+and 64 entries on the H8/300H) and shares space with the interrupt vector.
+
+You must use GAS and GLD from GNU binutils version 2.7 or later for
+this option to work correctly.
+
+@item interrupt_handler
+@cindex interrupt handler functions on the H8/300 processors
+Use this option on the H8/300 and H8/300H to indicate that the specified
+function is an interrupt handler. The compiler will generate function
+entry and exit sequences suitable for use in an interrupt handler when this
+attribute is present.
+
+@item eightbit_data
+@cindex eight bit data on the H8/300 and H8/300H
+Use this option on the H8/300 and H8/300H to indicate that the specified
+variable should be placed into the eight bit data section.
+The compiler will generate more efficient code for certain operations
+on data in the eight bit data area. Note the eight bit data area is limited to
+256 bytes of data.
+
+You must use GAS and GLD from GNU binutils version 2.7 or later for
+this option to work correctly.
+
+@item tiny_data
+@cindex tiny data section on the H8/300H
+Use this option on the H8/300H to indicate that the specified
+variable should be placed into the tiny data section.
+The compiler will generate more efficient code for loads and stores
+on data in the tiny data section. Note the tiny data area is limited to
+slightly under 32kbytes of data.
+
+@item interrupt
+@cindex interrupt handlers on the M32R/D
+Use this option on the M32R/D to indicate that the specified
+function is an interrupt handler. The compiler will generate function
+entry and exit sequences suitable for use in an interrupt handler when this
+attribute is present.
+
+@item model (@var{model-name})
+@cindex function addressability on the M32R/D
+Use this attribute on the M32R/D to set the addressability of an object,
+and the code generated for a function.
+The identifier @var{model-name} is one of @code{small}, @code{medium},
+or @code{large}, representing each of the code models.
+
+Small model objects live in the lower 16MB of memory (so that their
+addresses can be loaded with the @code{ld24} instruction), and are
+callable with the @code{bl} instruction.
+
+Medium model objects may live anywhere in the 32 bit address space (the
+compiler will generate @code{seth/add3} instructions to load their addresses),
+and are callable with the @code{bl} instruction.
+
+Large model objects may live anywhere in the 32 bit address space (the
+compiler will generate @code{seth/add3} instructions to load their addresses),
+and may not be reachable with the @code{bl} instruction (the compiler will
+generate the much slower @code{seth/add3/jl} instruction sequence).
+
@end table
You can specify multiple attributes in a declaration by separating them
@@ -1533,7 +1667,7 @@ old-style non-prototype definition. Consider the following example:
@example
/* @r{Use prototypes unless the compiler is old-fashioned.} */
-#if __STDC__
+#ifdef __STDC__
#define P(x) x
#else
#define P(x) ()
@@ -1599,24 +1733,10 @@ with traditional constructs like @code{dividend//*comment*/divisor}.
@cindex dollar signs in identifier names
@cindex identifier names, dollar signs in
-In GNU C, you may use dollar signs in identifier names. This is because
-many traditional C implementations allow such identifiers.
-
-On some machines, dollar signs are allowed in identifiers if you specify
-@w{@samp{-traditional}}. On a few systems they are allowed by default,
-even if you do not use @w{@samp{-traditional}}. But they are never
-allowed if you specify @w{@samp{-ansi}}.
-
-There are certain ANSI C programs (obscure, to be sure) that would
-compile incorrectly if dollar signs were permitted in identifiers. For
-example:
-
-@example
-#define foo(a) #a
-#define lose(b) foo (b)
-#define test$
-lose (test)
-@end example
+In GNU C, you may normally use dollar signs in identifier names.
+This is because many traditional C implementations allow such identifiers.
+However, dollar signs in identifiers are not supported on a few target
+machines, typically because the target assembler does not allow them.
@node Character Escapes
@section The Character @key{ESC} in Constants
@@ -1797,7 +1917,7 @@ section. For example, this small program uses several specific section names:
struct duart a __attribute__ ((section ("DUART_A"))) = @{ 0 @};
struct duart b __attribute__ ((section ("DUART_B"))) = @{ 0 @};
char stack[10000] __attribute__ ((section ("STACK"))) = @{ 0 @};
-int init_data_copy __attribute__ ((section ("INITDATACOPY"))) = 0;
+int init_data __attribute__ ((section ("INITDATA"))) = 0;
main()
@{
@@ -1805,7 +1925,7 @@ main()
init_sp (stack + sizeof (stack));
/* Initialize initialized data */
- memcpy (&init_data_copy, &data, &edata - &data);
+ memcpy (&init_data, &data, &edata - &data);
/* Turn on the serial ports */
init_duart (&a);
@@ -1833,11 +1953,12 @@ If you need to map the entire contents of a module to a particular
section, consider using the facilities of the linker instead.
@item transparent_union
-This attribute, attached to a function argument variable which is a
-union, means to pass the argument in the same way that the first union
-member would be passed. You can also use this attribute on a
-@code{typedef} for a union data type; then it applies to all function
-arguments with that type.
+This attribute, attached to a function parameter which is a union, means
+that the corresponding argument may have the type of any union member,
+but the argument is passed as if its type were that of the first union
+member. For more details see @xref{Type Attributes}. You can also use
+this attribute on a @code{typedef} for a union data type; then it
+applies to all function parameters with that type.
@item unused
This attribute, attached to a variable, means that the variable is meant
@@ -1846,6 +1967,20 @@ variable.
@item weak
The @code{weak} attribute is described in @xref{Function Attributes}.
+
+@item model (@var{model-name})
+@cindex variable addressability on the M32R/D
+Use this attribute on the M32R/D to set the addressability of an object.
+The identifier @var{model-name} is one of @code{small}, @code{medium},
+or @code{large}, representing each of the code models.
+
+Small model objects live in the lower 16MB of memory (so that their
+addresses can be loaded with the @code{ld24} instruction).
+
+Medium and large model objects may live anywhere in the 32 bit address space
+(the compiler will generate @code{seth/add3} instructions to load their
+addresses).
+
@end table
To specify multiple attributes, separate them by commas within the
@@ -1889,7 +2024,7 @@ typedef int more_aligned_int __attribute__ ((aligned (8));
@end smallexample
@noindent
-force the compiler to insure (as fas as it can) that each variable whose
+force the compiler to insure (as far as it can) that each variable whose
type is @code{struct S} or @code{more_aligned_int} will be allocated and
aligned @emph{at least} on a 8-byte boundary. On a Sparc, having all
variables of type @code{struct S} aligned to 8-byte boundaries allows
@@ -1969,21 +2104,76 @@ flag on the line is equivalent to specifying the @code{packed}
attribute on all @code{enum} definitions.
You may only specify this attribute after a closing curly brace on an
-@code{enum} definition, not in a @code{typedef} declaration.
+@code{enum} definition, not in a @code{typedef} declaration, unless that
+declaration also contains the definition of the @code{enum}.
@item transparent_union
This attribute, attached to a @code{union} type definition, indicates
-that any variable having that union type should, if passed to a
-function, be passed in the same way that the first union member would be
-passed. For example:
+that any function parameter having that union type causes calls to that
+function to be treated in a special way.
+
+First, the argument corresponding to a transparent union type can be of
+any type in the union; no cast is required. Also, if the union contains
+a pointer type, the corresponding argument can be a null pointer
+constant or a void pointer expression; and if the union contains a void
+pointer type, the corresponding argument can be any pointer expression.
+If the union member type is a pointer, qualifiers like @code{const} on
+the referenced type must be respected, just as with normal pointer
+conversions.
+
+Second, the argument is passed to the function using the calling
+conventions of first member of the transparent union, not the calling
+conventions of the union itself. All members of the union must have the
+same machine representation; this is necessary for this argument passing
+to work properly.
+
+Transparent unions are designed for library functions that have multiple
+interfaces for compatibility reasons. For example, suppose the
+@code{wait} function must accept either a value of type @code{int *} to
+comply with Posix, or a value of type @code{union wait *} to comply with
+the 4.1BSD interface. If @code{wait}'s parameter were @code{void *},
+@code{wait} would accept both kinds of arguments, but it would also
+accept any other pointer type and this would make argument type checking
+less useful. Instead, @code{<sys/wait.h>} might define the interface
+as follows:
+
+@smallexample
+typedef union
+ @{
+ int *__ip;
+ union wait *__up;
+ @} wait_status_ptr_t __attribute__ ((__transparent_union__));
+
+pid_t wait (wait_status_ptr_t);
+@end smallexample
+
+This interface allows either @code{int *} or @code{union wait *}
+arguments to be passed, using the @code{int *} calling convention.
+The program can call @code{wait} with arguments of either type:
+
+@example
+int w1 () @{ int w; return wait (&w); @}
+int w2 () @{ union wait w; return wait (&w); @}
+@end example
+
+With this interface, @code{wait}'s implementation might look like this:
@example
-union foo
+pid_t wait (wait_status_ptr_t p)
@{
- char a;
- int x[2];
-@} __attribute__ ((transparent_union));
+ return waitpid (-1, p.__ip, 0);
+@}
@end example
+
+@item unused
+When attached to a type (including a @code{union} or a @code{struct}),
+this attribute means that variables of that type are meant to appear
+possibly unused. GNU CC will not produce a warning for any variables of
+that type, even if the variable appears to do nothing. This is often
+the case with lock or thread classes, which are usually defined and then
+not referenced, but contain constructors and destructors that have
+nontrivial bookkeeping functions.
+
@end table
To specify multiple attributes, separate them by commas within the
@@ -2085,14 +2275,14 @@ did the easy thing, and turned it off.
@cindex assembler instructions
@cindex registers
-In an assembler instruction using @code{asm}, you can now specify the
-operands of the instruction using C expressions. This means no more
-guessing which registers or memory locations will contain the data you want
+In an assembler instruction using @code{asm}, you can specify the
+operands of the instruction using C expressions. This means you need not
+guess which registers or memory locations will contain the data you want
to use.
-You must specify an assembler instruction template much like what appears
-in a machine description, plus an operand constraint string for each
-operand.
+You must specify an assembler instruction template much like what
+appears in a machine description, plus an operand constraint string for
+each operand.
For example, here is how to use the 68881's @code{fsinx} instruction:
@@ -2103,64 +2293,66 @@ asm ("fsinx %1,%0" : "=f" (result) : "f" (angle));
@noindent
Here @code{angle} is the C expression for the input operand while
@code{result} is that of the output operand. Each has @samp{"f"} as its
-operand constraint, saying that a floating point register is required. The
-@samp{=} in @samp{=f} indicates that the operand is an output; all output
-operands' constraints must use @samp{=}. The constraints use the same
-language used in the machine description (@pxref{Constraints}).
-
-Each operand is described by an operand-constraint string followed by the C
-expression in parentheses. A colon separates the assembler template from
-the first output operand, and another separates the last output operand
-from the first input, if any. Commas separate output operands and separate
-inputs. The total number of operands is limited to ten or to the maximum
-number of operands in any instruction pattern in the machine description,
-whichever is greater.
-
-If there are no output operands, and there are input operands, then there
-must be two consecutive colons surrounding the place where the output
+operand constraint, saying that a floating point register is required.
+The @samp{=} in @samp{=f} indicates that the operand is an output; all
+output operands' constraints must use @samp{=}. The constraints use the
+same language used in the machine description (@pxref{Constraints}).
+
+Each operand is described by an operand-constraint string followed by
+the C expression in parentheses. A colon separates the assembler
+template from the first output operand and another separates the last
+output operand from the first input, if any. Commas separate the
+operands within each group. The total number of operands is limited to
+ten or to the maximum number of operands in any instruction pattern in
+the machine description, whichever is greater.
+
+If there are no output operands but there are input operands, you must
+place two consecutive colons surrounding the place where the output
operands would go.
Output operand expressions must be lvalues; the compiler can check this.
-The input operands need not be lvalues. The compiler cannot check whether
-the operands have data types that are reasonable for the instruction being
-executed. It does not parse the assembler instruction template and does
-not know what it means, or whether it is valid assembler input. The
-extended @code{asm} feature is most often used for machine instructions
-that the compiler itself does not know exist. If the output expression
-cannot be directly addressed (for example, it is a bit field), your
-constraint must allow a register. In that case, GNU CC will use
-the register as the output of the @code{asm}, and then store that
-register into the output.
-
-The output operands must be write-only; GNU CC will assume that the values
-in these operands before the instruction are dead and need not be
-generated. Extended asm does not support input-output or read-write
-operands. For this reason, the constraint character @samp{+}, which
-indicates such an operand, may not be used.
-
-When the assembler instruction has a read-write operand, or an operand
-in which only some of the bits are to be changed, you must logically
-split its function into two separate operands, one input operand and one
-write-only output operand. The connection between them is expressed by
-constraints which say they need to be in the same location when the
-instruction executes. You can use the same C expression for both
-operands, or different expressions. For example, here we write the
-(fictitious) @samp{combine} instruction with @code{bar} as its read-only
-source operand and @code{foo} as its read-write destination:
+The input operands need not be lvalues. The compiler cannot check
+whether the operands have data types that are reasonable for the
+instruction being executed. It does not parse the assembler instruction
+template and does not know what it means or even whether it is valid
+assembler input. The extended @code{asm} feature is most often used for
+machine instructions the compiler itself does not know exist. If
+the output expression cannot be directly addressed (for example, it is a
+bit field), your constraint must allow a register. In that case, GNU CC
+will use the register as the output of the @code{asm}, and then store
+that register into the output.
+
+The ordinary output operands must be write-only; GNU CC will assume that
+the values in these operands before the instruction are dead and need
+not be generated. Extended asm supports input-output or read-write
+operands. Use the constraint character @samp{+} to indicate such an
+operand and list it with the output operands.
+
+When the constraints for the read-write operand (or the operand in which
+only some of the bits are to be changed) allows a register, you may, as
+an alternative, logically split its function into two separate operands,
+one input operand and one write-only output operand. The connection
+between them is expressed by constraints which say they need to be in
+the same location when the instruction executes. You can use the same C
+expression for both operands, or different expressions. For example,
+here we write the (fictitious) @samp{combine} instruction with
+@code{bar} as its read-only source operand and @code{foo} as its
+read-write destination:
@example
asm ("combine %2,%0" : "=r" (foo) : "0" (foo), "g" (bar));
@end example
@noindent
-The constraint @samp{"0"} for operand 1 says that it must occupy the same
-location as operand 0. A digit in constraint is allowed only in an input
-operand, and it must refer to an output operand.
+The constraint @samp{"0"} for operand 1 says that it must occupy the
+same location as operand 0. A digit in constraint is allowed only in an
+input operand and it must refer to an output operand.
Only a digit in the constraint can guarantee that one operand will be in
-the same place as another. The mere fact that @code{foo} is the value of
-both operands is not enough to guarantee that they will be in the same
-place in the generated assembler code. The following would not work:
+the same place as another. The mere fact that @code{foo} is the value
+of both operands is not enough to guarantee that they will be in the
+same place in the generated assembler code. The following would not
+work reliably:
@example
asm ("combine %2,%0" : "=r" (foo) : "r" (foo), "g" (bar));
@@ -2174,10 +2366,10 @@ register (copying it afterward to @code{foo}'s own address). Of course,
since the register for operand 1 is not even mentioned in the assembler
code, the result will not work, but GNU CC can't tell that.
-Some instructions clobber specific hard registers. To describe this, write
-a third colon after the input operands, followed by the names of the
-clobbered hard registers (given as strings). Here is a realistic example
-for the Vax:
+Some instructions clobber specific hard registers. To describe this,
+write a third colon after the input operands, followed by the names of
+the clobbered hard registers (given as strings). Here is a realistic
+example for the VAX:
@example
asm volatile ("movc3 %0,%1,%2"
@@ -2187,32 +2379,32 @@ asm volatile ("movc3 %0,%1,%2"
@end example
If you refer to a particular hardware register from the assembler code,
-then you will probably have to list the register after the third colon
-to tell the compiler that the register's value is modified. In many
-assemblers, the register names begin with @samp{%}; to produce one
-@samp{%} in the assembler code, you must write @samp{%%} in the input.
-
-If your assembler instruction can alter the condition code register,
-add @samp{cc} to the list of clobbered registers. GNU CC on some
-machines represents the condition codes as a specific hardware
-register; @samp{cc} serves to name this register. On other machines,
-the condition code is handled differently, and specifying @samp{cc}
-has no effect. But it is valid no matter what the machine.
+you will probably have to list the register after the third colon to
+tell the compiler the register's value is modified. In some assemblers,
+the register names begin with @samp{%}; to produce one @samp{%} in the
+assembler code, you must write @samp{%%} in the input.
+
+If your assembler instruction can alter the condition code register, add
+@samp{cc} to the list of clobbered registers. GNU CC on some machines
+represents the condition codes as a specific hardware register;
+@samp{cc} serves to name this register. On other machines, the
+condition code is handled differently, and specifying @samp{cc} has no
+effect. But it is valid no matter what the machine.
If your assembler instruction modifies memory in an unpredictable
-fashion, add @samp{memory} to the list of clobbered registers.
-This will cause GNU CC to not keep memory values cached in
-registers across the assembler instruction.
+fashion, add @samp{memory} to the list of clobbered registers. This
+will cause GNU CC to not keep memory values cached in registers across
+the assembler instruction.
-You can put multiple assembler instructions together in a single @code{asm}
-template, separated either with newlines (written as @samp{\n}) or with
-semicolons if the assembler allows such semicolons. The GNU assembler
-allows semicolons and all Unix assemblers seem to do so. The input
-operands are guaranteed not to use any of the clobbered registers, and
-neither will the output operands' addresses, so you can read and write the
-clobbered registers as many times as you like. Here is an example of
-multiple instructions in a template; it assumes that the subroutine
-@code{_foo} accepts arguments in registers 9 and 10:
+You can put multiple assembler instructions together in a single
+@code{asm} template, separated either with newlines (written as
+@samp{\n}) or with semicolons if the assembler allows such semicolons.
+The GNU assembler allows semicolons and most Unix assemblers seem to do
+so. The input operands are guaranteed not to use any of the clobbered
+registers, and neither will the output operands' addresses, so you can
+read and write the clobbered registers as many times as you like. Here
+is an example of multiple instructions in a template; it assumes the
+subroutine @code{_foo} accepts arguments in registers 9 and 10:
@example
asm ("movl %0,r9;movl %1,r10;call _foo"
@@ -2221,16 +2413,16 @@ asm ("movl %0,r9;movl %1,r10;call _foo"
: "r9", "r10");
@end example
-Unless an output operand has the @samp{&} constraint modifier, GNU CC may
-allocate it in the same register as an unrelated input operand, on the
-assumption that the inputs are consumed before the outputs are produced.
+Unless an output operand has the @samp{&} constraint modifier, GNU CC
+may allocate it in the same register as an unrelated input operand, on
+the assumption the inputs are consumed before the outputs are produced.
This assumption may be false if the assembler code actually consists of
more than one instruction. In such a case, use @samp{&} for each output
-operand that may not overlap an input.
-@xref{Modifiers}.
+operand that may not overlap an input. @xref{Modifiers}.
-If you want to test the condition code produced by an assembler instruction,
-you must include a branch and a label in the @code{asm} construct, as follows:
+If you want to test the condition code produced by an assembler
+instruction, you must include a branch and a label in the @code{asm}
+construct, as follows:
@example
asm ("clr %0;frob %1;beq 0f;mov #1,%0;0:"
@@ -2243,8 +2435,8 @@ This assumes your assembler supports local labels, as the GNU assembler
and most Unix assemblers do.
Speaking of labels, jumps from one @code{asm} to another are not
-supported. The compiler's optimizers do not know about these jumps,
-and therefore they cannot take account of them when deciding how to
+supported. The compiler's optimizers do not know about these jumps, and
+therefore they cannot take account of them when deciding how to
optimize.
@cindex macros containing @code{asm}
@@ -2263,8 +2455,8 @@ Here the variable @code{__arg} is used to make sure that the instruction
operates on a proper @code{double} value, and to accept only those
arguments @code{x} which can convert automatically to a @code{double}.
-Another way to make sure the instruction operates on the correct data type
-is to use a cast in the @code{asm}. This is different from using a
+Another way to make sure the instruction operates on the correct data
+type is to use a cast in the @code{asm}. This is different from using a
variable @code{__arg} in that it converts more different types. For
example, if the desired type were @code{int}, casting the argument to
@code{int} would accept a pointer with no complaint, while assigning the
@@ -2272,27 +2464,40 @@ argument to an @code{int} variable named @code{__arg} would warn about
using a pointer unless the caller explicitly casts it.
If an @code{asm} has output operands, GNU CC assumes for optimization
-purposes that the instruction has no side effects except to change the
-output operands. This does not mean that instructions with a side effect
-cannot be used, but you must be careful, because the compiler may eliminate
-them if the output operands aren't used, or move them out of loops, or
-replace two with one if they constitute a common subexpression. Also, if
-your instruction does have a side effect on a variable that otherwise
-appears not to change, the old value of the variable may be reused later if
-it happens to be found in a register.
+purposes the instruction has no side effects except to change the output
+operands. This does not mean instructions with a side effect cannot be
+used, but you must be careful, because the compiler may eliminate them
+if the output operands aren't used, or move them out of loops, or
+replace two with one if they constitute a common subexpression. Also,
+if your instruction does have a side effect on a variable that otherwise
+appears not to change, the old value of the variable may be reused later
+if it happens to be found in a register.
You can prevent an @code{asm} instruction from being deleted, moved
significantly, or combined, by writing the keyword @code{volatile} after
the @code{asm}. For example:
@example
-#define set_priority(x) \
-asm volatile ("set_priority %0": /* no outputs */ : "g" (x))
-@end example
+#define get_and_set_priority(new) \
+(@{ int __old; \
+ asm volatile ("get_and_set_priority %0, %1": "=g" (__old) : "g" (new)); \
+ __old; @})
+b@end example
@noindent
-An instruction without output operands will not be deleted or moved
-significantly, regardless, unless it is unreachable.
+If you write an @code{asm} instruction with no outputs, GNU CC will know
+the instruction has side-effects and will not delete the instruction or
+move it outside of loops. If the side-effects of your instruction are
+not purely external, but will affect variables in your program in ways
+other than reading the inputs and clobbering the specified registers or
+memory, you should write the @code{volatile} keyword to prevent future
+versions of GNU CC from moving the instruction around within a core
+region.
+
+An @code{asm} instruction without any operands or clobbers (and ``old
+style'' @code{asm}) will not be deleted or moved significantly,
+regardless, unless it is unreachable, the same wasy as if you had
+written a @code{volatile} keyword.
Note that even a volatile @code{asm} instruction can be moved in ways
that appear insignificant to the compiler, such as across jump
@@ -2495,7 +2700,7 @@ Of course, it will not do to use more than a few of those.
@node Local Reg Vars
@subsection Specifying Registers for Local Variables
-@cindex local variables, specifying registers
+@cindex local variables, specifying registers
@cindex specifying registers for local variables
@cindex registers for local variables
@@ -2631,6 +2836,49 @@ For example, @samp{#ifdef __FUNCTION__} does not have any special
meaning inside a function, since the preprocessor does not do anything
special with the identifier @code{__FUNCTION__}.
+@node Return Address
+@section Getting the Return or Frame Address of a Function
+
+These functions may be used to get information about the callers of a
+function.
+
+@table @code
+@item __builtin_return_address (@var{level})
+This function returns the return address of the current function, or of
+one of its callers. The @var{level} argument is number of frames to
+scan up the call stack. A value of @code{0} yields the return address
+of the current function, a value of @code{1} yields the return address
+of the caller of the current function, and so forth.
+
+The @var{level} argument must be a constant integer.
+
+On some machines it may be impossible to determine the return address of
+any function other than the current one; in such cases, or when the top
+of the stack has been reached, this function will return @code{0}.
+
+This function should only be used with a non-zero argument for debugging
+purposes.
+
+@item __builtin_frame_address (@var{level})
+This function is similar to @code{__builtin_return_address}, but it
+returns the address of the function frame rather than the return address
+of the function. Calling @code{__builtin_frame_address} with a value of
+@code{0} yields the frame address of the current function, a value of
+@code{1} yields the frame address of the caller of the current function,
+and so forth.
+
+The frame is the area on the stack which holds local variables and saved
+registers. The frame address is normally the address of the first word
+pushed on to the stack by the function. However, the exact definition
+depends upon the processor and the calling convention. If the processor
+has a dedicated frame pointer register, and the function has a frame,
+then @code{__builtin_frame_address} will return the value of the frame
+pointer register.
+
+The caveats that apply to @code{__builtin_return_address} apply to this
+function as well.
+@end table
+
@node C++ Extensions
@chapter Extensions to the C++ Language
@cindex extensions, C++ language
@@ -2672,7 +2920,7 @@ C++ programs:
@group
@var{type}
@var{functionname} (@var{args}) return @var{resultname};
-@{
+@{
@dots{}
@var{body}
@dots{}
@@ -2691,7 +2939,7 @@ m ()
@{
X b;
b.a = 23;
- return b;
+ return b;
@}
@end example
@@ -2720,7 +2968,7 @@ at the outset, and assigning to its @code{a} field directly:
X
m () return r;
@{
- r.a = 23;
+ r.a = 23;
@}
@end example
@@ -2731,13 +2979,13 @@ are executed @strong{before} any of the body of @code{m}.
Functions of this type impose no additional restrictions; in particular,
you can execute @code{return} statements, or return implicitly by
reaching the end of the function body (``falling off the edge'').
-Cases like
+Cases like
@example
X
m () return r (23);
@{
- return;
+ return;
@}
@end example
@@ -2751,7 +2999,7 @@ X
m () return r;
@{
X b;
- return b;
+ return b;
@}
@end example
@@ -2807,7 +3055,7 @@ behavior. For example, @code{MIN (i++, j++)} will fail, incrementing
the smaller counter twice. A GNU C extension allows you to write safe
macros that avoid this kind of problem (@pxref{Naming Types,,Naming an
Expression's Type}). However, writing @code{MIN} and @code{MAX} as
-macros also forces you to use function-call notation notation for a
+macros also forces you to use function-call notation for a
fundamental arithmetic operation. Using GNU C++ extensions, you can
write @w{@samp{int min = i <? j;}} instead.
@@ -2822,9 +3070,7 @@ works correctly.
@cindex destructors vs @code{goto}
In C++ programs, you can safely use the @code{goto} statement. When you
use it to exit a block which contains aggregates requiring destructors,
-the destructors will run before the @code{goto} transfers control. (In
-ANSI C++, @code{goto} is restricted to targets within the current
-block.)
+the destructors will run before the @code{goto} transfers control.
@cindex constructors vs @code{goto}
The compiler still forbids using @code{goto} to @emph{enter} a scope
@@ -2901,7 +3147,8 @@ If you use @samp{#pragma implementation} with no argument, it applies to
an include file with the same basename@footnote{A file's @dfn{basename}
was the name stripped of all leading path information and of trailing
suffixes, such as @samp{.h} or @samp{.C} or @samp{.cc}.} as your source
-file. For example, in @file{allclass.cc}, @samp{#pragma implementation}
+file. For example, in @file{allclass.cc}, giving just
+@samp{#pragma implementation}
by itself is equivalent to @samp{#pragma implementation "allclass.h"}.
In versions of GNU C++ prior to 2.6.0 @file{allclass.h} was treated as
@@ -2958,41 +3205,99 @@ problem, which I will refer to as the Borland model and the Cfront model.
@table @asis
@item Borland model
Borland C++ solved the template instantiation problem by adding the code
-equivalent of common blocks to their linker; template instances
-are emitted in each translation unit that uses them, and they are
-collapsed together at run time. The advantage of this model is that the
-linker only has to consider the object files themselves; there is no
-external complexity to worry about. This disadvantage is that
-compilation time is increased because the template code is being
-compiled repeatedly. Code written for this model tends to include
-definitions of all member templates in the header file, since they must
-be seen to be compiled.
+equivalent of common blocks to their linker; the compiler emits template
+instances in each translation unit that uses them, and the linker
+collapses them together. The advantage of this model is that the linker
+only has to consider the object files themselves; there is no external
+complexity to worry about. This disadvantage is that compilation time
+is increased because the template code is being compiled repeatedly.
+Code written for this model tends to include definitions of all
+templates in the header file, since they must be seen to be
+instantiated.
@item Cfront model
The AT&T C++ translator, Cfront, solved the template instantiation
problem by creating the notion of a template repository, an
-automatically maintained place where template instances are stored. As
-individual object files are built, notes are placed in the repository to
-record where templates and potential type arguments were seen so that
-the subsequent instantiation step knows where to find them. At link
-time, any needed instances are generated and linked in. The advantages
-of this model are more optimal compilation speed and the ability to use
-the system linker; to implement the Borland model a compiler vendor also
+automatically maintained place where template instances are stored. A
+more modern version of the repository works as follows: As individual
+object files are built, the compiler places any template definitions and
+instantiations encountered in the repository. At link time, the link
+wrapper adds in the objects in the repository and compiles any needed
+instances that were not previously emitted. The advantages of this
+model are more optimal compilation speed and the ability to use the
+system linker; to implement the Borland model a compiler vendor also
needs to replace the linker. The disadvantages are vastly increased
-complexity, and thus potential for error; theoretically, this should be
-just as transparent, but in practice it has been very difficult to build
+complexity, and thus potential for error; for some code this can be
+just as transparent, but in practice it can been very difficult to build
multiple programs in one directory and one program in multiple
-directories using Cfront. Code written for this model tends to separate
-definitions of non-inline member templates into a separate file, which
-is magically found by the link preprocessor when a template needs to be
-instantiated.
+directories. Code written for this model tends to separate definitions
+of non-inline member templates into a separate file, which should be
+compiled separately.
@end table
-Currently, g++ implements neither automatic model. In the mean time,
-you have three options for dealing with template instantiations:
+When used with GNU ld version 2.8 or later on an ELF system such as
+Linux/GNU or Solaris 2, or on Microsoft Windows, g++ supports the
+Borland model. On other systems, g++ implements neither automatic
+model.
+
+A future version of g++ will support a hybrid model whereby the compiler
+will emit any instantiations for which the template definition is
+included in the compile, and store template definitions and
+instantiation context information into the object file for the rest.
+The link wrapper will extract that information as necessary and invoke
+the compiler to produce the remaining instantiations. The linker will
+then combine duplicate instantiations.
+
+In the mean time, you have the following options for dealing with
+template instantiations:
@enumerate
@item
+Compile your code with @samp{-fno-implicit-templates} to disable the
+implicit generation of template instances, and explicitly instantiate
+all the ones you use. This approach requires more knowledge of exactly
+which instances you need than do the others, but it's less
+mysterious and allows greater control. You can scatter the explicit
+instantiations throughout your program, perhaps putting them in the
+translation units where the instances are used or the translation units
+that define the templates themselves; you can put all of the explicit
+instantiations you need into one big file; or you can create small files
+like
+
+@example
+#include "Foo.h"
+#include "Foo.cc"
+
+template class Foo<int>;
+template ostream& operator <<
+ (ostream&, const Foo<int>&);
+@end example
+
+for each of the instances you need, and create a template instantiation
+library from those.
+
+If you are using Cfront-model code, you can probably get away with not
+using @samp{-fno-implicit-templates} when compiling files that don't
+@samp{#include} the member template definitions.
+
+If you use one big file to do the instantiations, you may want to
+compile it without @samp{-fno-implicit-templates} so you get all of the
+instances required by your explicit instantiations (but not by any
+other files) without having to specify them as well.
+
+g++ has extended the template instantiation syntax outlined in the
+Working Paper to allow forward declaration of explicit instantiations,
+explicit instantiation of members of template classes and instantiation
+of the compiler support data for a template class (i.e. the vtable)
+without instantiating any of its members:
+
+@example
+extern template int max (int, int);
+template void Foo<int>::f ();
+inline template class Foo<int>;
+@end example
+
+@item
Do nothing. Pretend g++ does implement automatic instantiation
management. Code written for the Borland model will work fine, but
each translation unit will contain instances of each of the templates it
@@ -3003,16 +3308,16 @@ duplication.
Add @samp{#pragma interface} to all files containing template
definitions. For each of these files, add @samp{#pragma implementation
"@var{filename}"} to the top of some @samp{.C} file which
-@samp{#include}s it. Then compile everything with -fexternal-templates.
-The templates will then only be expanded in the translation unit which
-implements them (i.e. has a @samp{#pragma implementation} line for the
-file where they live); all other files will use external references. If
-you're lucky, everything should work properly. If you get undefined
-symbol errors, you need to make sure that each template instance which
-is used in the program is used in the file which implements that
-template. If you don't have any use for a particular instance in that
-file, you can just instantiate it explicitly, using the syntax from the
-latest C++ working paper:
+@samp{#include}s it. Then compile everything with
+@samp{-fexternal-templates}. The templates will then only be expanded
+in the translation unit which implements them (i.e. has a @samp{#pragma
+implementation} line for the file where they live); all other files will
+use external references. If you're lucky, everything should work
+properly. If you get undefined symbol errors, you need to make sure
+that each template instance which is used in the program is used in the
+file which implements that template. If you don't have any use for a
+particular instance in that file, you can just instantiate it
+explicitly, using the syntax from the latest C++ working paper:
@example
template class A<int>;
@@ -3024,37 +3329,15 @@ using code written for the Cfront model, the file containing a class
template and the file containing its member templates should be
implemented in the same translation unit.
-A slight variation on this approach is to use the flag
--falt-external-templates instead; this flag causes template instances to
-be emitted in the translation unit that implements the header where they
-are first instantiated, rather than the one which implements the file
-where the templates are defined. This header must be the same in all
-translation units, or things are likely to break.
+A slight variation on this approach is to instead use the flag
+@samp{-falt-external-templates}; this flag causes template
+instances to be emitted in the translation unit that implements the
+header where they are first instantiated, rather than the one which
+implements the file where the templates are defined. This header must
+be the same in all translation units, or things are likely to break.
@xref{C++ Interface,,Declarations and Definitions in One Header}, for
more discussion of these pragmas.
-
-@item
-Explicitly instantiate all the template instances you use, and compile
-with -fno-implicit-templates. This is probably your best bet; it may
-require more knowledge of exactly which templates you are using, but
-it's less mysterious than the previous approach, and it doesn't require
-any @samp{#pragma}s or other g++-specific code. You can scatter the
-instantiations throughout your program, you can create one big file to
-do all the instantiations, or you can create tiny files like
-
-@example
-#include "Foo.h"
-#include "Foo.cc"
-
-template class Foo<int>;
-@end example
-
-for each instance you need, and create a template instantiation library
-from those. I'm partial to the last, but your mileage may vary. If you
-are using Cfront-model code, you can probably get away with not using
--fno-implicit-templates when compiling files that don't @samp{#include}
-the member template definitions.
@end enumerate
@node C++ Signatures
@@ -3128,7 +3411,7 @@ S * p = &obj;
@noindent
defines a signature pointer @code{p} and initializes it to point to an
-object of type @code{C}.
+object of type @code{C}.
The member function call @w{@samp{int i = p->foo ();}}
executes @samp{obj.foo ()}.
diff --git a/gnu/usr.bin/gcc/final.c b/gnu/usr.bin/gcc/final.c
index 481782ea995..05edac03b7a 100644
--- a/gnu/usr.bin/gcc/final.c
+++ b/gnu/usr.bin/gcc/final.c
@@ -1,5 +1,5 @@
/* Convert RTL to assembler code and output it, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -67,6 +67,7 @@ Boston, MA 02111-1307, USA. */
#include "hard-reg-set.h"
#include "defaults.h"
#include "output.h"
+#include "except.h"
/* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
@@ -95,6 +96,10 @@ Boston, MA 02111-1307, USA. */
#define INT_TYPE_SIZE BITS_PER_WORD
#endif
+#ifndef LONG_TYPE_SIZE
+#define LONG_TYPE_SIZE BITS_PER_WORD
+#endif
+
/* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a
null default for it to save conditionalization later. */
#ifndef CC_STATUS_INIT
@@ -135,6 +140,9 @@ static char *last_filename;
used if profile_block_flag is set. */
static int count_basic_blocks;
+/* Number of instrumented arcs when profile_arc_flag is set. */
+extern int count_instrumented_arcs;
+
/* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't abort.
The precise value is the insn being output, to pass to error_for_asm. */
@@ -276,10 +284,14 @@ static void add_bb PROTO((FILE *));
static int add_bb_string PROTO((char *, int));
static void output_source_line PROTO((FILE *, rtx));
static rtx walk_alter_subreg PROTO((rtx));
-static int alter_cond PROTO((rtx));
static void output_asm_name PROTO((void));
static void output_operand PROTO((rtx, int));
+#ifdef LEAF_REGISTERS
static void leaf_renumber_regs PROTO((rtx));
+#endif
+#ifdef HAVE_cc0
+static int alter_cond PROTO((rtx));
+#endif
extern char *getpwd ();
@@ -309,14 +321,21 @@ end_final (filename)
{
int i;
- if (profile_block_flag)
+ if (profile_block_flag || profile_arc_flag)
{
char name[20];
int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
- int size = (POINTER_SIZE / BITS_PER_UNIT) * count_basic_blocks;
- int rounded = size;
+ int size, rounded;
struct bb_list *ptr;
struct bb_str *sptr;
+ int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
+ int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
+
+ if (profile_block_flag)
+ size = long_bytes * count_basic_blocks;
+ else
+ size = long_bytes * count_instrumented_arcs;
+ rounded = size;
rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
@@ -324,8 +343,8 @@ end_final (filename)
data_section ();
- /* Output the main header, of 10 words:
- 0: 1 if this file's initialized, else 0.
+ /* Output the main header, of 11 words:
+ 0: 1 if this file is initialized, else 0.
1: address of file name (LPBX1).
2: address of table of counts (LPBX2).
3: number of counts in the table.
@@ -337,53 +356,73 @@ end_final (filename)
6: Number of bytes in this header.
7: address of table of function names (LPBX4).
8: address of table of line numbers (LPBX5) or 0.
- 9: address of table of file names (LPBX6) or 0. */
+ 9: address of table of file names (LPBX6) or 0.
+ 10: space reserved for basic block profiling. */
ASM_OUTPUT_ALIGN (asm_out_file, align);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
/* zero word */
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ assemble_integer (const0_rtx, long_bytes, 1);
/* address of filename */
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), pointer_bytes, 1);
/* address of count table */
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), pointer_bytes, 1);
- /* count of the # of basic blocks */
- assemble_integer (GEN_INT (count_basic_blocks), UNITS_PER_WORD, 1);
+ /* count of the # of basic blocks or # of instrumented arcs */
+ if (profile_block_flag)
+ assemble_integer (GEN_INT (count_basic_blocks), long_bytes, 1);
+ else
+ assemble_integer (GEN_INT (count_instrumented_arcs), long_bytes,
+ 1);
/* zero word (link field) */
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ assemble_integer (const0_rtx, pointer_bytes, 1);
/* address of basic block start address table */
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
+ if (profile_block_flag)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), pointer_bytes,
+ 1);
+ }
+ else
+ assemble_integer (const0_rtx, pointer_bytes, 1);
/* byte count for extended structure. */
- assemble_integer (GEN_INT (10 * UNITS_PER_WORD), UNITS_PER_WORD, 1);
+ assemble_integer (GEN_INT (10 * UNITS_PER_WORD), long_bytes, 1);
/* address of function name table */
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 4);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
+ if (profile_block_flag)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 4);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), pointer_bytes,
+ 1);
+ }
+ else
+ assemble_integer (const0_rtx, pointer_bytes, 1);
/* address of line number and filename tables if debugging. */
- if (write_symbols != NO_DEBUG)
+ if (write_symbols != NO_DEBUG && profile_block_flag)
{
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 5);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), pointer_bytes, 1);
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 6);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), pointer_bytes, 1);
}
else
{
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, 1);
}
+ /* space for extension ptr (link field) */
+ assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+
/* Output the file name changing the suffix to .d for Sun tcov
compatibility. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
@@ -396,12 +435,15 @@ end_final (filename)
strcat (data_file, "/");
strcat (data_file, filename);
strip_off_ending (data_file, len);
- strcat (data_file, ".d");
+ if (profile_block_flag)
+ strcat (data_file, ".d");
+ else
+ strcat (data_file, ".da");
assemble_string (data_file, strlen (data_file) + 1);
}
/* Make space for the table of counts. */
- if (flag_no_common || size == 0)
+ if (size == 0)
{
/* Realign data section. */
ASM_OUTPUT_ALIGN (asm_out_file, align);
@@ -417,63 +459,79 @@ end_final (filename)
ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded);
else
#endif
+#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
+ ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, size,
+ BIGGEST_ALIGNMENT);
+#else
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
BIGGEST_ALIGNMENT);
#else
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
#endif
+#endif
}
/* Output any basic block strings */
- readonly_data_section ();
- if (sbb_head)
+ if (profile_block_flag)
{
- ASM_OUTPUT_ALIGN (asm_out_file, align);
- for (sptr = sbb_head; sptr != 0; sptr = sptr->next)
+ readonly_data_section ();
+ if (sbb_head)
{
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBC", sptr->label_num);
- assemble_string (sptr->string, sptr->length);
+ ASM_OUTPUT_ALIGN (asm_out_file, align);
+ for (sptr = sbb_head; sptr != 0; sptr = sptr->next)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBC",
+ sptr->label_num);
+ assemble_string (sptr->string, sptr->length);
+ }
}
}
/* Output the table of addresses. */
- /* Realign in new section */
- ASM_OUTPUT_ALIGN (asm_out_file, align);
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3);
- for (i = 0; i < count_basic_blocks; i++)
+ if (profile_block_flag)
{
- ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),
- UNITS_PER_WORD, 1);
+ /* Realign in new section */
+ ASM_OUTPUT_ALIGN (asm_out_file, align);
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 3);
+ for (i = 0; i < count_basic_blocks; i++)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),
+ pointer_bytes, 1);
+ }
}
/* Output the table of function names. */
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 4);
- for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)
+ if (profile_block_flag)
{
- if (ptr->func_label_num >= 0)
+ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 4);
+ for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)
{
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBC", ptr->func_label_num);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),
- UNITS_PER_WORD, 1);
+ if (ptr->func_label_num >= 0)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBC",
+ ptr->func_label_num);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),
+ pointer_bytes, 1);
+ }
+ else
+ assemble_integer (const0_rtx, pointer_bytes, 1);
}
- else
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
- }
- for ( ; i < count_basic_blocks; i++)
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ for ( ; i < count_basic_blocks; i++)
+ assemble_integer (const0_rtx, pointer_bytes, 1);
+ }
- if (write_symbols != NO_DEBUG)
+ if (write_symbols != NO_DEBUG && profile_block_flag)
{
/* Output the table of line numbers. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 5);
for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)
- assemble_integer (GEN_INT (ptr->line_num), UNITS_PER_WORD, 1);
+ assemble_integer (GEN_INT (ptr->line_num), long_bytes, 1);
for ( ; i < count_basic_blocks; i++)
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ assemble_integer (const0_rtx, long_bytes, 1);
/* Output the table of file names. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 6);
@@ -481,22 +539,27 @@ end_final (filename)
{
if (ptr->file_label_num >= 0)
{
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBC", ptr->file_label_num);
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBC",
+ ptr->file_label_num);
assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name),
- UNITS_PER_WORD, 1);
+ pointer_bytes, 1);
}
else
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ assemble_integer (const0_rtx, pointer_bytes, 1);
}
for ( ; i < count_basic_blocks; i++)
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ assemble_integer (const0_rtx, pointer_bytes, 1);
}
/* End with the address of the table of addresses,
so we can find it easily, as the last word in the file's text. */
- ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
- assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), UNITS_PER_WORD, 1);
+ if (profile_block_flag)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
+ assemble_integer (gen_rtx (SYMBOL_REF, Pmode, name), pointer_bytes,
+ 1);
+ }
}
}
@@ -618,6 +681,10 @@ get_attr_length (insn)
length += get_attr_length (XVECEXP (body, 0, i));
else
length = insn_default_length (insn);
+ break;
+
+ default:
+ break;
}
#ifdef ADJUST_INSN_LENGTH
@@ -650,6 +717,13 @@ shorten_branches (first)
rtx body;
int uid;
+ /* In order to make sure that all instructions have valid length info,
+ we must split them before we compute the address/length info. */
+
+ for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ insn = try_split (PATTERN (insn), insn, 1);
+
/* Compute maximum UID and allocate arrays. */
for (insn = first; insn; insn = NEXT_INSN (insn))
if (INSN_UID (insn) > max_uid)
@@ -673,6 +747,8 @@ shorten_branches (first)
if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
|| GET_CODE (insn) == CODE_LABEL)
continue;
+ if (INSN_DELETED_P (insn))
+ continue;
body = PATTERN (insn);
if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
@@ -685,9 +761,12 @@ shorten_branches (first)
insn_lengths[uid] = (XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC)
* GET_MODE_SIZE (GET_MODE (body)));
- /* Account for possible alignment. */
- insn_lengths[uid]
- += unitsize - (insn_current_address & (unitsize - 1));
+ /* We don't know what address the ADDR_VEC/ADDR_DIFF_VEC will end
+ up at after branch shortening. As a result, it is impossible
+ to determine how much padding we need at this point. Therefore,
+ assume worst possible alignment. */
+ insn_lengths[uid] += unitsize - 1;
+
#else
;
#endif
@@ -705,7 +784,7 @@ shorten_branches (first)
#endif
/* Inside a delay slot sequence, we do not do any branch shortening
if the shortening could change the number of delay slots
- of the branch. */
+ of the branch. */
for (i = 0; i < XVECLEN (body, 0); i++)
{
rtx inner_insn = XVECEXP (body, 0, i);
@@ -890,10 +969,16 @@ final_start_function (first, file, optimize)
last_linenum = high_block_linenum = high_function_linenum
= NOTE_LINE_NUMBER (first);
+#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
+ /* Output DWARF definition of the function. */
+ if (dwarf2out_do_frame ())
+ dwarf2out_begin_prologue ();
+#endif
+
/* For SDB and XCOFF, the function beginning must be marked between
the function label and the prologue. We always need this, even when
-g1 was used. Defer on MIPS systems so that parameter descriptions
- follow function entry. */
+ follow function entry. */
#if defined(SDB_DEBUGGING_INFO) && !defined(MIPS_DEBUGGING_INFO)
if (write_symbols == SDB_DEBUG)
sdbout_begin_function (last_linenum);
@@ -921,6 +1006,11 @@ final_start_function (first, file, optimize)
profile_function (file);
#endif /* PROFILE_BEFORE_PROLOGUE */
+#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
+ if (dwarf2out_do_frame ())
+ dwarf2out_frame_debug (NULL_RTX);
+#endif
+
#ifdef FUNCTION_PROLOGUE
/* First output the function prologue: code to set up the stack frame. */
FUNCTION_PROLOGUE (file, get_frame_size ());
@@ -944,9 +1034,8 @@ final_start_function (first, file, optimize)
of the function name. */
if (profile_block_flag)
{
- char *junk = "function";
- bb_func_label_num =
- add_bb_string ((*decl_printable_name) (current_function_decl, &junk), FALSE);
+ bb_func_label_num
+ = add_bb_string ((*decl_printable_name) (current_function_decl, 2), FALSE);
}
}
@@ -957,7 +1046,7 @@ profile_after_prologue (file)
#ifdef FUNCTION_BLOCK_PROFILER
if (profile_block_flag)
{
- FUNCTION_BLOCK_PROFILER (file, profile_label_no);
+ FUNCTION_BLOCK_PROFILER (file, count_basic_blocks);
}
#endif /* FUNCTION_BLOCK_PROFILER */
@@ -971,58 +1060,54 @@ static void
profile_function (file)
FILE *file;
{
- int align = MIN (BIGGEST_ALIGNMENT, POINTER_SIZE);
+ int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
int sval = current_function_returns_struct;
int cxt = current_function_needs_context;
data_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
- assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
+ assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, 1);
- text_section ();
+ function_section (current_function_decl);
-#ifdef STRUCT_VALUE_INCOMING_REGNUM
+#if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_INCOMING_REGNUM);
#else
-#ifdef STRUCT_VALUE_REGNUM
+#if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_PUSH (file, STRUCT_VALUE_REGNUM);
#endif
#endif
-#if 0
-#ifdef STATIC_CHAIN_INCOMING_REGNUM
+#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
-#ifdef STATIC_CHAIN_REGNUM
+#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_PUSH (file, STATIC_CHAIN_REGNUM);
#endif
#endif
-#endif /* 0 */
FUNCTION_PROFILER (file, profile_label_no);
-#if 0
-#ifdef STATIC_CHAIN_INCOMING_REGNUM
+#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_INCOMING_REGNUM);
#else
-#ifdef STATIC_CHAIN_REGNUM
+#if defined(STATIC_CHAIN_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
ASM_OUTPUT_REG_POP (file, STATIC_CHAIN_REGNUM);
#endif
#endif
-#endif /* 0 */
-#ifdef STRUCT_VALUE_INCOMING_REGNUM
+#if defined(STRUCT_VALUE_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_INCOMING_REGNUM);
#else
-#ifdef STRUCT_VALUE_REGNUM
+#if defined(STRUCT_VALUE_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (sval)
ASM_OUTPUT_REG_POP (file, STRUCT_VALUE_REGNUM);
#endif
@@ -1076,6 +1161,11 @@ final_end_function (first, file, optimize)
dwarfout_end_epilogue ();
#endif
+#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
+ if (dwarf2out_do_frame ())
+ dwarf2out_end_epilogue ();
+#endif
+
#ifdef XCOFF_DEBUGGING_INFO
if (write_symbols == XCOFF_DEBUG)
xcoffout_end_epilogue (file);
@@ -1113,6 +1203,8 @@ add_bb (file)
count of times it was entered. */
#ifdef BLOCK_PROFILER
BLOCK_PROFILER (file, count_basic_blocks);
+#endif
+#ifdef HAVE_cc0
CC_STATUS_INIT;
#endif
@@ -1148,7 +1240,7 @@ add_bb_string (string, perm_p)
string = p;
}
else
- for (ptr = sbb_head; ptr != (struct bb_str *)0; ptr = ptr->next)
+ for (ptr = sbb_head; ptr != (struct bb_str *) 0; ptr = ptr->next)
if (ptr->string == string)
break;
@@ -1192,6 +1284,8 @@ final (first, file, optimize, prescan)
last_ignored_compare = 0;
new_block = 1;
+ check_exception_handler_labels ();
+
/* Make a map indicating which line numbers appear in this function.
When producing SDB debugging info, delete troublesome line number
notes from inlined functions in other files as well as duplicate
@@ -1239,7 +1333,12 @@ final (first, file, optimize, prescan)
/* Output the insns. */
for (insn = NEXT_INSN (first); insn;)
- insn = final_scan_insn (insn, file, optimize, prescan, 0);
+ {
+#ifdef HAVE_ATTR_length
+ insn_current_address = insn_addresses[INSN_UID (insn)];
+#endif
+ insn = final_scan_insn (insn, file, optimize, prescan, 0);
+ }
/* Do basic-block profiling here
if the last insn was a conditional branch. */
@@ -1294,6 +1393,25 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
break;
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_BLOCK_NUMBER (insn));
+ add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
+#ifdef ASM_OUTPUT_EH_REGION_BEG
+ ASM_OUTPUT_EH_REGION_BEG (file, NOTE_BLOCK_NUMBER (insn));
+#endif
+ break;
+ }
+
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_BLOCK_NUMBER (insn));
+#ifdef ASM_OUTPUT_EH_REGION_END
+ ASM_OUTPUT_EH_REGION_END (file, NOTE_BLOCK_NUMBER (insn));
+#endif
+ break;
+ }
+
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
{
#ifdef FUNCTION_END_PROLOGUE
@@ -1317,7 +1435,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
{
#if defined(SDB_DEBUGGING_INFO) && defined(MIPS_DEBUGGING_INFO)
/* MIPS stabs require the parameter descriptions to be after the
- function entry point rather than before. */
+ function entry point rather than before. */
if (write_symbols == SDB_DEBUG)
sdbout_begin_function (last_linenum);
else
@@ -1340,11 +1458,8 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
&& (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
-#ifdef DWARF_DEBUGGING_INFO
|| write_symbols == DWARF_DEBUG
-#endif
- )
- )
+ || write_symbols == DWARF2_DEBUG))
{
/* Beginning of a symbol-block. Assign it a sequence number
and push the number onto the stack PENDING_BLOCKS. */
@@ -1376,20 +1491,21 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", next_block_index);
#endif
#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG && block_depth > 1)
+ if (write_symbols == DWARF_DEBUG)
dwarfout_begin_block (next_block_index);
#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_begin_block (next_block_index);
+#endif
next_block_index++;
}
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END
&& (debug_info_level == DINFO_LEVEL_NORMAL
|| debug_info_level == DINFO_LEVEL_VERBOSE
-#ifdef DWARF_DEBUGGING_INFO
|| write_symbols == DWARF_DEBUG
-#endif
- )
- )
+ || write_symbols == DWARF2_DEBUG))
{
/* End of a symbol-block. Pop its sequence number off
PENDING_BLOCKS and output debugging info based on that. */
@@ -1412,9 +1528,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
pending_blocks[block_depth]);
#endif
#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG && block_depth >= 1)
+ if (write_symbols == DWARF_DEBUG && block_depth >= 0)
dwarfout_end_block (pending_blocks[block_depth]);
#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG && block_depth >= 0)
+ dwarf2out_end_block (pending_blocks[block_depth]);
+#endif
}
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL
&& (debug_info_level == DINFO_LEVEL_NORMAL
@@ -1424,6 +1544,10 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (write_symbols == DWARF_DEBUG)
dwarfout_label (insn);
#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_label (insn);
+#endif
}
else if (NOTE_LINE_NUMBER (insn) > 0)
/* This note is a line-number. */
@@ -1480,6 +1604,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (NEXT_INSN (insn))
ASM_OUTPUT_ALIGN_CODE (file);
#endif
+#if defined (DWARF2_UNWIND_INFO) && !defined (ACCUMULATE_OUTGOING_ARGS)
+ /* If we push arguments, we need to check all insns for stack
+ adjustments. */
+ if (dwarf2out_do_frame ())
+ dwarf2out_frame_debug (insn);
+#endif
break;
case CODE_LABEL:
@@ -1487,6 +1617,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (prescan > 0)
break;
new_block = 1;
+
+#ifdef FINAL_PRESCAN_LABEL
+ FINAL_PRESCAN_INSN (insn, NULL_PTR, 0);
+#endif
+
#ifdef SDB_DEBUGGING_INFO
if (write_symbols == SDB_DEBUG && LABEL_NAME (insn))
sdbout_label (insn);
@@ -1495,6 +1630,10 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (write_symbols == DWARF_DEBUG && LABEL_NAME (insn))
dwarfout_label (insn);
#endif
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG && LABEL_NAME (insn))
+ dwarf2out_label (insn);
+#endif
if (app_on)
{
fprintf (file, ASM_APP_OFF);
@@ -1537,7 +1676,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
default:
{
- register rtx body = PATTERN (insn);
+ register rtx body = PATTERN (insn), set;
int insn_code_number;
char *template;
rtx note;
@@ -1739,6 +1878,8 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
body = PATTERN (insn);
#ifdef HAVE_cc0
+ set = single_set(insn);
+
/* Check for redundant test and compare instructions
(when the condition codes are already set up as desired).
This is done only when optimizing; if not optimizing,
@@ -1747,35 +1888,41 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
and the next statement should reexamine the variable
to compute the condition codes. */
- if (optimize
- && GET_CODE (body) == SET
- && GET_CODE (SET_DEST (body)) == CC0
- && insn != last_ignored_compare)
+ if (optimize)
{
- if (GET_CODE (SET_SRC (body)) == SUBREG)
- SET_SRC (body) = alter_subreg (SET_SRC (body));
- else if (GET_CODE (SET_SRC (body)) == COMPARE)
- {
- if (GET_CODE (XEXP (SET_SRC (body), 0)) == SUBREG)
- XEXP (SET_SRC (body), 0)
- = alter_subreg (XEXP (SET_SRC (body), 0));
- if (GET_CODE (XEXP (SET_SRC (body), 1)) == SUBREG)
- XEXP (SET_SRC (body), 1)
- = alter_subreg (XEXP (SET_SRC (body), 1));
- }
- if ((cc_status.value1 != 0
- && rtx_equal_p (SET_SRC (body), cc_status.value1))
- || (cc_status.value2 != 0
- && rtx_equal_p (SET_SRC (body), cc_status.value2)))
+#if 0
+ rtx set = single_set(insn);
+#endif
+
+ if (set
+ && GET_CODE (SET_DEST (set)) == CC0
+ && insn != last_ignored_compare)
{
- /* Don't delete insn if it has an addressing side-effect. */
- if (! FIND_REG_INC_NOTE (insn, 0)
- /* or if anything in it is volatile. */
- && ! volatile_refs_p (PATTERN (insn)))
+ if (GET_CODE (SET_SRC (set)) == SUBREG)
+ SET_SRC (set) = alter_subreg (SET_SRC (set));
+ else if (GET_CODE (SET_SRC (set)) == COMPARE)
{
- /* We don't really delete the insn; just ignore it. */
- last_ignored_compare = insn;
- break;
+ if (GET_CODE (XEXP (SET_SRC (set), 0)) == SUBREG)
+ XEXP (SET_SRC (set), 0)
+ = alter_subreg (XEXP (SET_SRC (set), 0));
+ if (GET_CODE (XEXP (SET_SRC (set), 1)) == SUBREG)
+ XEXP (SET_SRC (set), 1)
+ = alter_subreg (XEXP (SET_SRC (set), 1));
+ }
+ if ((cc_status.value1 != 0
+ && rtx_equal_p (SET_SRC (set), cc_status.value1))
+ || (cc_status.value2 != 0
+ && rtx_equal_p (SET_SRC (set), cc_status.value2)))
+ {
+ /* Don't delete insn if it has an addressing side-effect. */
+ if (! FIND_REG_INC_NOTE (insn, 0)
+ /* or if anything in it is volatile. */
+ && ! volatile_refs_p (PATTERN (insn)))
+ {
+ /* We don't really delete the insn; just ignore it. */
+ last_ignored_compare = insn;
+ break;
+ }
}
}
}
@@ -1856,12 +2003,29 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
}
/* Make same adjustments to instructions that examine the
- condition codes without jumping (if this machine has them). */
+ condition codes without jumping and instructions that
+ handle conditional moves (if this machine has either one). */
if (cc_status.flags != 0
- && GET_CODE (body) == SET)
+ && set != 0)
{
- switch (GET_CODE (SET_SRC (body)))
+ rtx cond_rtx, then_rtx, else_rtx;
+
+ if (GET_CODE (insn) != JUMP_INSN
+ && GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
+ {
+ cond_rtx = XEXP (SET_SRC (set), 0);
+ then_rtx = XEXP (SET_SRC (set), 1);
+ else_rtx = XEXP (SET_SRC (set), 2);
+ }
+ else
+ {
+ cond_rtx = SET_SRC (set);
+ then_rtx = const_true_rtx;
+ else_rtx = const0_rtx;
+ }
+
+ switch (GET_CODE (cond_rtx))
{
case GTU:
case GT:
@@ -1875,18 +2039,29 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
case NE:
{
register int result;
- if (XEXP (SET_SRC (body), 0) != cc0_rtx)
+ if (XEXP (cond_rtx, 0) != cc0_rtx)
break;
- result = alter_cond (SET_SRC (body));
+ result = alter_cond (cond_rtx);
if (result == 1)
- validate_change (insn, &SET_SRC (body), const_true_rtx, 0);
+ validate_change (insn, &SET_SRC (set), then_rtx, 0);
else if (result == -1)
- validate_change (insn, &SET_SRC (body), const0_rtx, 0);
+ validate_change (insn, &SET_SRC (set), else_rtx, 0);
else if (result == 2)
INSN_CODE (insn) = -1;
+ if (SET_DEST (set) == SET_SRC (set))
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
}
+ break;
+
+ default:
+ break;
}
}
+
#endif
/* Do machine-specific peephole optimizations if desired. */
@@ -2001,6 +2176,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (new == insn && PATTERN (new) == body)
abort ();
+#ifdef HAVE_ATTR_length
+ /* This instruction should have been split in shorten_branches,
+ to ensure that we would have valid length info for the
+ splitees. */
+ abort ();
+#endif
+
new_block = 0;
return new;
}
@@ -2012,6 +2194,22 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
output_asm_insn (template, recog_operand);
+#if defined (DWARF2_UNWIND_INFO)
+#if !defined (ACCUMULATE_OUTGOING_ARGS)
+ /* If we push arguments, we need to check all insns for stack
+ adjustments. */
+ if (dwarf2out_do_frame ())
+ dwarf2out_frame_debug (insn);
+#else
+#if defined (HAVE_prologue)
+ /* If this insn is part of the prologue, emit DWARF v2
+ call frame info. */
+ if (RTX_FRAME_RELATED_P (insn) && dwarf2out_do_frame ())
+ dwarf2out_frame_debug (insn);
+#endif
+#endif
+#endif
+
#if 0
/* It's not at all clear why we did this and doing so interferes
with tests we'd like to do to use REG_WAS_0 notes, so let's try
@@ -2085,6 +2283,11 @@ output_source_line (file, insn)
if (write_symbols == DWARF_DEBUG)
dwarfout_line (filename, NOTE_LINE_NUMBER (insn));
#endif
+
+#ifdef DWARF2_DEBUGGING_INFO
+ if (write_symbols == DWARF2_DEBUG)
+ dwarf2out_line (filename, NOTE_LINE_NUMBER (insn));
+#endif
}
}
@@ -2139,6 +2342,9 @@ walk_alter_subreg (x)
case SUBREG:
return alter_subreg (x);
+
+ default:
+ break;
}
return x;
@@ -2197,6 +2403,9 @@ alter_cond (cond)
PUT_CODE (cond, NE);
value = 2;
break;
+
+ default:
+ break;
}
if (cc_status.flags & CC_NOT_NEGATIVE)
@@ -2223,6 +2432,9 @@ alter_cond (cond)
PUT_CODE (cond, NE);
value = 2;
break;
+
+ default:
+ break;
}
if (cc_status.flags & CC_NO_OVERFLOW)
@@ -2245,19 +2457,15 @@ alter_cond (cond)
case LTU:
/* Jump becomes no-op. */
return -1;
+
+ default:
+ break;
}
if (cc_status.flags & (CC_Z_IN_NOT_N | CC_Z_IN_N))
switch (GET_CODE (cond))
{
- case LE:
- case LEU:
- case GE:
- case GEU:
- case LT:
- case LTU:
- case GT:
- case GTU:
+ default:
abort ();
case NE:
@@ -2295,6 +2503,9 @@ alter_cond (cond)
PUT_CODE (cond, GEU);
value = 2;
break;
+
+ default:
+ break;
}
return value;
@@ -2458,12 +2669,7 @@ output_asm_insn (template, operands)
else if (letter == 'n')
{
if (GET_CODE (operands[c]) == CONST_INT)
- fprintf (asm_out_file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- "%d",
-#else
- "%ld",
-#endif
+ fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC,
- INTVAL (operands[c]));
else
{
@@ -2599,13 +2805,7 @@ output_addr_const (file, x)
break;
case CONST_INT:
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- "%d",
-#else
- "%ld",
-#endif
- INTVAL (x));
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
break;
case CONST:
@@ -2619,37 +2819,12 @@ output_addr_const (file, x)
{
/* We can use %d if the number is one word and positive. */
if (CONST_DOUBLE_HIGH (x))
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == 64
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
- "0x%lx%016lx",
-#else
- "0x%x%016x",
-#endif
-#else
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
- "0x%lx%08lx",
-#else
- "0x%x%08x",
-#endif
-#endif
+ fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
else if (CONST_DOUBLE_LOW (x) < 0)
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- "0x%x",
-#else
- "0x%lx",
-#endif
- CONST_DOUBLE_LOW (x));
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
else
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- "%d",
-#else
- "%ld",
-#endif
- CONST_DOUBLE_LOW (x));
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
}
else
/* We can't handle floating point constants;
@@ -2730,8 +2905,8 @@ asm_fprintf VPROTO((FILE *file, char *p, ...))
VA_START (argptr, p);
#ifndef __STDC__
- file = va_arg (argptr, FILE*);
- p = va_arg (argptr, char*);
+ file = va_arg (argptr, FILE *);
+ p = va_arg (argptr, char *);
#endif
buf[0] = '%';
@@ -2790,8 +2965,14 @@ asm_fprintf VPROTO((FILE *file, char *p, ...))
but we do not check for those cases. It means that the value
is a HOST_WIDE_INT, which may be either `int' or `long'. */
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+ *q++ = 'l';
+#else
*q++ = 'l';
+ *q++ = 'l';
+#endif
#endif
*q++ = *p++;
@@ -2953,7 +3134,7 @@ split_double (value, first, second)
/* Note, this converts the REAL_VALUE_TYPE to the target's
format, splits up the floating point double and outputs
exactly 32 bits of it into each of l[0] and l[1] --
- not necessarily BITS_PER_WORD bits. */
+ not necessarily BITS_PER_WORD bits. */
REAL_VALUE_TO_TARGET_DOUBLE (r, l);
*first = GEN_INT ((HOST_WIDE_INT) l[0]);
@@ -2992,7 +3173,7 @@ leaf_function_p ()
{
rtx insn;
- if (profile_flag || profile_block_flag)
+ if (profile_flag || profile_block_flag || profile_arc_flag)
return 0;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
diff --git a/gnu/usr.bin/gcc/fixinc.ptx b/gnu/usr.bin/gcc/fixinc.ptx
index 031b8f412d0..93a8f2c5d0e 100644
--- a/gnu/usr.bin/gcc/fixinc.ptx
+++ b/gnu/usr.bin/gcc/fixinc.ptx
@@ -1,7 +1,7 @@
#! /bin/sh
# Install modified versions of certain ANSI-incompatible
# native Sequent DYNIX/ptx System V Release 3.2 system include files.
-# Copyright (C) 1994 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
# Contributed by Bill Burton <billb@progress.com>
# Portions adapted from fixinc.svr4 and fixincludes.
#
@@ -125,11 +125,12 @@ if [ \! -z "$file_to_fix" ]; then
if grep stdio $file_to_fix > /dev/null; then
true
else
- sed -e '/#include \<sys\types\.h\>/a\
+ sed -e '/#include <sys\/types\.h>/a\
\
#if defined(__STDC__) || defined(__cplusplus)\
#include <stdio.h>\
-#endif /* __STDC__ */' \
+#endif /* __STDC__ */
+' \
$file_to_fix > ${LIB}/${file}.sed
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
echo Fixed $file_to_fix
@@ -183,10 +184,69 @@ if [ \! -z "$file_to_fix" ]; then
\
#if defined (__GNUC__) || defined (__GNUG__)\
#include <sys/byteorder.h>\
-#else /* not __GNUC__ */\
+#else /* not __GNUC__ */
' \
-e '/#endif[ ]*\/\* NETSWAP \*\//i\
-#endif /* not __GNUC__ */' \
+#endif /* not __GNUC__ */
+' \
+ $file_to_fix > ${LIB}/${file}.sed
+ rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
+ echo Fixed $file_to_fix
+ fi
+fi
+
+# /usr/include/sys/mc_param.h has an embedded asm for the cpuid instruction
+# on the P5. This is not used by anything else so we ifdef it out.
+file=sys/mc_param.h
+if [ -r ${LIB}/$file ]; then
+ file_to_fix=${LIB}/$file
+else
+ if [ -r ${INPUT}/$file ]; then
+ file_to_fix=${INPUT}/$file
+ else
+ file_to_fix=""
+ fi
+fi
+if [ \! -z "$file_to_fix" ]; then
+ echo Checking $file_to_fix
+ if grep __GNUC__ $file_to_fix > /dev/null; then
+ true
+ else
+ sed -e '/__asm/,/}/{
+/__asm/i\
+#if !defined (__GNUC__) && !defined (__GNUG__)
+/}/a\
+#endif
+}' \
+ $file_to_fix > ${LIB}/${file}.sed
+ rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
+ echo Fixed $file_to_fix
+ fi
+fi
+
+# /usr/include/sys/mc_param.h has an embedded asm for the cpuid instruction
+# on the P5. This is not used by anything else so we ifdef it out.
+file=sys/mc_param.h
+if [ -r ${LIB}/$file ]; then
+ file_to_fix=${LIB}/$file
+else
+ if [ -r ${INPUT}/$file ]; then
+ file_to_fix=${INPUT}/$file
+ else
+ file_to_fix=""
+ fi
+fi
+if [ \! -z "$file_to_fix" ]; then
+ echo Checking $file_to_fix
+ if grep __GNUC__ $file_to_fix > /dev/null; then
+ true
+ else
+ sed -e '/__asm/,/}/{
+/__asm/i\
+#if !defined (__GNUC__) && !defined (__GNUG__)
+/}/a\
+#endif
+}' \
$file_to_fix > ${LIB}/${file}.sed
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
echo Fixed $file_to_fix
diff --git a/gnu/usr.bin/gcc/fixinc.sco b/gnu/usr.bin/gcc/fixinc.sco
index b3301e19cba..c0ca7826d7f 100644
--- a/gnu/usr.bin/gcc/fixinc.sco
+++ b/gnu/usr.bin/gcc/fixinc.sco
@@ -6,6 +6,8 @@
# Based on fixinc.svr4 script by Ron Guilmette (rfg@ncd.com) (SCO
# modifications by Ian Lance Taylor (ian@airs.com)).
#
+# Copyright (C) 1995, 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
@@ -169,6 +171,9 @@ while [ $# != 0 ]; do
shift; shift
done
+# We shouldn't stay in the directory we just copied.
+cd ${INPUT}
+
# Fix first broken decl of getcwd present on some svr4 systems.
file=stdlib.h
@@ -290,6 +295,80 @@ if [ -r ${LIB}/$file ]; then
fi
fi
+# This function is borrowed from fixinclude.svr4
+# The OpenServer math.h defines struct exception, which conflicts with
+# the class exception defined in the C++ file std/stdexcept.h. We
+# redefine it to __math_exception. This is not a great fix, but I
+# haven't been able to think of anything better.
+#
+# OpenServer's math.h declares abs as inline int abs... Unfortunately,
+# we blow over that one (with C++ linkage) and stick a new one in stdlib.h
+# with C linkage. So we eat the one out of math.h.
+file=math.h
+base=`basename $file`
+if [ -r ${LIB}/$file ]; then
+ file_to_fix=${LIB}/$file
+else
+ if [ -r ${INPUT}/$file ]; then
+ file_to_fix=${INPUT}/$file
+ else
+ file_to_fix=""
+ fi
+fi
+if [ \! -z "$file_to_fix" ]; then
+ echo Checking $file_to_fix
+ sed -e '/struct exception/i\
+#ifdef __cplusplus\
+#define exception __math_exception\
+#endif'\
+ -e '/struct exception/a\
+#ifdef __cplusplus\
+#undef exception\
+#endif' \
+ -e 's@inline int abs(int [a-z][a-z]*) {.*}@extern "C" int abs(int);@' \
+ $file_to_fix > /tmp/$base
+ if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
+ true
+ else
+ echo Fixed $file_to_fix
+ rm -f ${LIB}/$file
+ cp /tmp/$base ${LIB}/$file
+ chmod a+r ${LIB}/$file
+ fi
+ rm -f /tmp/$base
+fi
+
+#
+# Also, the static functions lstat() and fchmod() in <sys/stat.h>
+# cause G++ grief since they're not wrapped in "if __cplusplus".
+# Fix that up now.
+#
+file=sys/stat.h
+if [ -r $file ] && [ ! -r ${LIB}/$file ]; then
+ cp $file ${LIB}/$file >/dev/null 2>&1 || echo "Can't copy $file"
+ chmod +w ${LIB}/$file 2>/dev/null
+ chmod a+r ${LIB}/$file 2>/dev/null
+fi
+
+if [ -r ${LIB}/$file ]; then
+ echo Fixing $file, static definitions not C++-aware.
+ sed -e '/^static int[ ]*/i\
+#if __cplusplus\
+extern "C"\
+{\
+#endif /* __cplusplus */ \
+' \
+-e '/^}$/a\
+#if __cplusplus\
+}\
+#endif /* __cplusplus */ \
+' ${LIB}/$file > ${LIB}/${file}.sed
+ rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
+ if cmp $file ${LIB}/$file >/dev/null 2>&1; then
+ rm -f ${LIB}/$file
+ fi
+fi
+
echo 'Removing unneeded directories:'
cd $LIB
files=`find . -type d -print | sort -r`
diff --git a/gnu/usr.bin/gcc/fixinc.svr4 b/gnu/usr.bin/gcc/fixinc.svr4
index 582c6fbd2f3..46e07ce0ac9 100644
--- a/gnu/usr.bin/gcc/fixinc.svr4
+++ b/gnu/usr.bin/gcc/fixinc.svr4
@@ -1,9 +1,8 @@
#! /bin/sh
-#
-# fixinc.svr4 -- Install modified versions of certain ANSI-incompatible
-# native System V Release 4 system include files.
-#
-# Written by Ron Guilmette (rfg@ncd.com).
+# Install modified versions of certain ANSI-incompatible
+# native System V Release 4 system include files.
+# Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
+# Contributed by Ron Guilmette (rfg@monkeys.com).
#
# This file is part of GNU CC.
#
@@ -74,7 +73,7 @@ fi
echo 'Making directories:'
cd ${INPUT}
if $LINKS; then
- files=`ls -LR | sed -n s/:$//p`
+ files=`find . -follow -type d -print 2>/dev/null | sed '/^.$/d'`
else
files=`find . -type d -print | sed '/^.$/d'`
fi
@@ -99,6 +98,7 @@ if $LINKS; then
# In case $dest is relative, get to $file's dir first.
cd ${INPUT}
cd `echo ./$file | sed -n 's&[^/]*$&&p'`
+ rwd=`pwd`
# Check that the target directory exists.
# Redirections changed to avoid bug in sh on Ultrix.
(cd $dest) > /dev/null 2>&1
@@ -108,7 +108,11 @@ if $LINKS; then
x=`pwd`
# If link leads back into ${INPUT},
# make a similar link here.
- if expr $x : "${INPUT}/.*" > /dev/null; then
+ if expr "$dest" : '[^/][^/]*' >/dev/null && [ ! -h $dest ]; then
+ echo $file '->' $dest': Making link'
+ rm -fr ${LIB}/$file > /dev/null 2>&1
+ ln -s $dest ${LIB}/$file > /dev/null 2>&1
+ elif expr $x : "${INPUT}/.*" > /dev/null; then
# Y gets the actual target dir name, relative to ${INPUT}.
y=`echo $x | sed -n "s&${INPUT}/&&p"`
# DOTS is the relative path from ${LIB}/$file's dir back to ${LIB}.
@@ -117,6 +121,15 @@ if $LINKS; then
echo $file '->' $dots$y ': Making link'
rm -fr ${LIB}/$file > /dev/null 2>&1
ln -s $dots$y ${LIB}/$file > /dev/null 2>&1
+ elif expr $x : "${rwd}/.*" > /dev/null; then
+ # Y gets the actual target dir name, relative to the directory where the link is.
+ y=`echo $x | sed -n "s&${rwd}/&&p"`
+ # DOTS is the relative path from ${LIB}/$file's dir back to ${LIB}.
+ dots=`echo "$file" |
+ sed -e 's@^./@@' -e 's@/./@/@g' -e 's@[^/][^/]*@..@g' -e 's@..$@@'`
+ echo $file '->' $dots$y ': Making link'
+ rm -fr ${LIB}/$file > /dev/null 2>&1
+ ln -s $dots$y ${LIB}/$file > /dev/null 2>&1
else
# If the link is to outside ${INPUT},
# treat this directory as if it actually contained the files.
@@ -188,7 +201,9 @@ while [ $# != 0 ]; do
s/__STDC__[ ][ ]*==[ ][ ]*0/!defined (__STRICT_ANSI__)/g
s/__STDC__[ ][ ]*==[ ][ ]*1/defined (__STRICT_ANSI__)/g
s/__STDC__[ ][ ]*!=[ ][ ]*0/defined (__STRICT_ANSI__)/g
+ s/__STDC__[ ][ ]*!=[ ][ ]*1/!defined (__STRICT_ANSI__)/g
s/__STDC__ - 0 == 0/!defined (__STRICT_ANSI__)/g
+ s/__STDC__ - 0 == 1/defined (__STRICT_ANSI__)/g
/^typedef[ ][ ]*[unsigned ]*long[ ][ ]*[u_]*longlong_t;/s/long/long long/
' $2/$file > $2/$file.sed
mv $2/$file.sed $2/$file
@@ -475,14 +490,16 @@ else
static\
#else\
extern\
-#endif'\
+#endif
+'\
-e 's/extern \(int ftw(const.*\)$/\1/' \
-e '/^extern int nftw/i\
#if defined(_STYPES)\
static\
#else\
extern\
-#endif'\
+#endif
+'\
-e 's/extern \(int nftw.*\)$/\1/' \
-e '/^extern int ftw(),/c\
#if !defined(_STYPES)\
@@ -1028,9 +1045,11 @@ fi
# true
# else
# sed -e '/#ifdef INKERNEL/i\
-# #ifdef _KERNEL' \
+# #ifdef _KERNEL
+# ' \
# -e '/#endif[ ]*\/\* INKERNEL \*\//a\
-# #endif /* _KERNEL */' \
+# #endif /* _KERNEL */
+# ' \
# $file_to_fix > ${LIB}/${file}.sed
# rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
# echo Fixed $file_to_fix
@@ -1056,10 +1075,12 @@ if [ \! -z "$file_to_fix" ]; then
true
else
sed -e '/# ifdef __STDC__/i\
-# if !defined (__GNUC__) && !defined (__GNUG__)' \
+# if !defined (__GNUC__) && !defined (__GNUG__)
+' \
-e '/# include <sys\/byteorder.h>/s/ / /'\
-e '/# include <sys\/byteorder.h>/i\
-# endif /* !defined (__GNUC__) && !defined (__GNUG__) */'\
+# endif /* !defined (__GNUC__) && !defined (__GNUG__) */
+'\
$file_to_fix > ${LIB}/${file}.sed
rm -f ${LIB}/$file; mv ${LIB}/${file}.sed ${LIB}/$file
echo Fixed $file_to_fix
@@ -1335,29 +1356,41 @@ fi
if [ \! -z "$file_to_fix" ]; then
echo Checking $file_to_fix
sed -e '/[ ]FLT_MIN[ ]/i\
-#ifndef FLT_MIN'\
+#ifndef FLT_MIN
+'\
-e '/[ ]FLT_MIN[ ]/a\
-#endif'\
+#endif
+'\
-e '/[ ]FLT_MAX[ ]/i\
-#ifndef FLT_MAX'\
+#ifndef FLT_MAX
+'\
-e '/[ ]FLT_MAX[ ]/a\
-#endif'\
+#endif
+'\
-e '/[ ]FLT_DIG[ ]/i\
-#ifndef FLT_DIG'\
+#ifndef FLT_DIG
+'\
-e '/[ ]FLT_DIG[ ]/a\
-#endif'\
+#endif
+'\
-e '/[ ]DBL_MIN[ ]/i\
-#ifndef DBL_MIN'\
+#ifndef DBL_MIN
+'\
-e '/[ ]DBL_MIN[ ]/a\
-#endif'\
+#endif
+'\
-e '/[ ]DBL_MAX[ ]/i\
-#ifndef DBL_MAX'\
+#ifndef DBL_MAX
+'\
-e '/[ ]DBL_MAX[ ]/a\
-#endif'\
+#endif
+'\
-e '/[ ]DBL_DIG[ ]/i\
-#ifndef DBL_DIG'\
+#ifndef DBL_DIG
+'\
-e '/[ ]DBL_DIG[ ]/a\
-#endif' $file_to_fix > /tmp/$base
+#endif
+' $file_to_fix > /tmp/$base
if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
true
else
@@ -1408,9 +1441,11 @@ fi
if [ \! -z "$file_to_fix" ]; then
echo Checking $file_to_fix
sed -e '/define[ ]HUGE_VAL[ ]/i\
-#ifndef HUGE_VAL'\
+#ifndef HUGE_VAL
+'\
-e '/define[ ]HUGE_VAL[ ]/a\
-#endif' $file_to_fix > /tmp/$base
+#endif
+' $file_to_fix > /tmp/$base
if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
true
else
@@ -1439,9 +1474,11 @@ for file in math.h floatingpoint.h; do
if [ \! -z "$file_to_fix" ]; then
echo Checking $file_to_fix
sed -e '/^#define[ ]*__P/i\
-#ifndef __P'\
+#ifndef __P
+'\
-e '/^#define[ ]*__P/a\
-#endif' $file_to_fix > /tmp/$base
+#endif
+' $file_to_fix > /tmp/$base
if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
true
else
@@ -1454,6 +1491,42 @@ for file in math.h floatingpoint.h; do
fi
done
+# The Solaris math.h defines struct exception, which conflicts with
+# the class exception defined in the C++ file std/stdexcept.h. We
+# redefine it to __math_exception. This is not a great fix, but I
+# haven't been able to think of anything better.
+file=math.h
+base=`basename $file`
+if [ -r ${LIB}/$file ]; then
+ file_to_fix=${LIB}/$file
+else
+ if [ -r ${INPUT}/$file ]; then
+ file_to_fix=${INPUT}/$file
+ else
+ file_to_fix=""
+ fi
+fi
+if [ \! -z "$file_to_fix" ]; then
+ echo Checking $file_to_fix
+ sed -e '/struct exception/i\
+#ifdef __cplusplus\
+#define exception __math_exception\
+#endif'\
+ -e '/struct exception/a\
+#ifdef __cplusplus\
+#undef exception\
+#endif' $file_to_fix > /tmp/$base
+ if cmp $file_to_fix /tmp/$base >/dev/null 2>&1; then \
+ true
+ else
+ echo Fixed $file_to_fix
+ rm -f ${LIB}/$file
+ cp /tmp/$base ${LIB}/$file
+ chmod a+r ${LIB}/$file
+ fi
+ rm -f /tmp/$base
+fi
+
echo 'Removing unneeded directories:'
cd $LIB
files=`find . -type d -print | sort -r`
@@ -1468,7 +1541,7 @@ if $LINKS; then
for file in $files; do
dest=`ls -ld $file | sed -n 's/.*-> //p'`
if expr "$dest" : '[^/].*' > /dev/null; then
- target=${LIB}/`echo file | sed "s|[^/]*\$|$dest|"`
+ target=${LIB}/`echo $file | sed "s|[^/]*\$|$dest|"`
if [ -f $target ]; then
ln -s $dest ${LIB}/$file >/dev/null 2>&1
fi
diff --git a/gnu/usr.bin/gcc/fixproto b/gnu/usr.bin/gcc/fixproto
index 79c8dfc3aff..1e4c0fc905a 100644
--- a/gnu/usr.bin/gcc/fixproto
+++ b/gnu/usr.bin/gcc/fixproto
@@ -65,7 +65,7 @@ if [ `echo $1 | wc -w` = 0 ] ; then
exit 1
fi
-std_files="ctype.h dirent.h errno.h curses.h fcntl.h grp.h locale.h math.h pwd.h setjmp.h signal.h stdio.h stdlib.h string.h sys/stat.h sys/times.h sys/resource.h sys/utsname.h sys/wait.h tar.h termios.h time.h unistd.h"
+std_files="ctype.h dirent.h errno.h curses.h fcntl.h grp.h locale.h math.h pwd.h setjmp.h signal.h stdio.h stdlib.h string.h sys/socket.h sys/stat.h sys/times.h sys/resource.h sys/utsname.h sys/wait.h tar.h termios.h time.h unistd.h utime.h"
rel_target_dir=$1
# All files in $src_dir_all (normally same as $rel_target_dir) are
@@ -120,6 +120,7 @@ required_stdlib_h="abort abs atexit atof atoi atol bsearch calloc exit free gete
required_unistd_h="_exit access alarm chdir chown close ctermid cuserid dup dup2 execl execle execlp execv execve execvp fork fpathconf getcwd getegid geteuid getgid getlogin getopt getpgrp getpid getppid getuid isatty link lseek pathconf pause pipe read rmdir setgid setpgid setsid setuid sleep sysconf tcgetpgrp tcsetpgrp ttyname unlink write"
done_dirs=""
+subdirs_made=""
echo "" >fixproto.list
for code in ALL STD ; do
@@ -142,7 +143,7 @@ for code in ALL STD ; do
# for C++, so skip those.
subdirs="$subdirs "`cd $rel_source_dir/$d; find . -type d -print | \
sed -e '/^\.$/d' -e "s|^\./|${d}/|" -e 's|^\./||' \
- -e '/CC$/d' -e '/\+\+/d'`
+ -e '/CC$/d' -e '/[+][+]/d'`
links=
links=`cd $rel_source_dir; find $d/. -type l -print | \
sed -e "s|$d/./|$d/|" -e 's|^\./||'`
@@ -174,7 +175,9 @@ for code in ALL STD ; do
abs_target_subdir=${abs_target_dir}/${rel_source_subdir}
if [ \! -d $abs_target_subdir ] ; then
- mkdir $abs_target_subdir
+ if mkdir $abs_target_subdir ; then
+ subdirs_made="$abs_target_subdir $subdirs_made"
+ fi
fi
# Append "/"; remove initial "./". Hence "." -> "" and "sys" -> "sys/".
rel_source_prefix=`echo $rel_source_subdir | sed -e 's|$|/|' -e 's|^./||'`
@@ -199,7 +202,9 @@ for code in ALL STD ; do
# Create the dir where this file will go when fixed.
xxdir=`echo ./$file | sed -e 's|/[^/]*$||'`
if [ \! -d $abs_target_subdir/$xxdir ] ; then
- mkdir $abs_target_subdir/$xxdir
+ if mkdir $abs_target_subdir/$xxdir ; then
+ subdirs_made="$abs_target_subdir/$xxdir $subdirs_made"
+ fi
fi
# Just in case we have edited out a symbolic link
if [ -f $src_dir_std/$file -a -f $src_dir_std/$xxfile ] ; then
@@ -270,4 +275,8 @@ EOF
rm tmp.h
fi
done
+
+# Remove any directories that we made that are still empty.
+rmdir $subdirs_made 2>/dev/null
+
exit 0
diff --git a/gnu/usr.bin/gcc/floatlib.c b/gnu/usr.bin/gcc/floatlib.c
index 2e20d70f36c..55e1d4f6512 100644
--- a/gnu/usr.bin/gcc/floatlib.c
+++ b/gnu/usr.bin/gcc/floatlib.c
@@ -54,6 +54,7 @@ If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu.
*/
/* the following deal with IEEE single-precision numbers */
+#define D_PHANTOM_BIT 0x00100000
#define EXCESS 126
#define SIGNBIT 0x80000000
#define HIDDEN (1 << 23)
@@ -93,7 +94,38 @@ union float_long
long l;
};
+ struct _ieee {
+#ifdef SWAP
+ unsigned mantissa2 : 32;
+ unsigned mantissa1 : 20;
+ unsigned exponent : 11;
+ unsigned sign : 1;
+#else
+ unsigned exponent : 11;
+ unsigned sign : 1;
+ unsigned mantissa2 : 32;
+ unsigned mantissa1 : 20;
+#endif
+ };
+
+ union _doubleu {
+ double d;
+ struct _ieee ieee;
+#ifdef SWAP
+ struct {
+ unsigned long lower;
+ long upper;
+ } l;
+#else
+ struct {
+ long upper;
+ unsigned long lower;
+ } l;
+#endif
+ };
+
/* add two floats */
+
float
__addsf3 (float a1, float a2)
{
@@ -183,6 +215,7 @@ __addsf3 (float a1, float a2)
}
/* subtract two floats */
+
float
__subsf3 (float a1, float a2)
{
@@ -203,6 +236,7 @@ __subsf3 (float a1, float a2)
}
/* compare two floats */
+
long
__cmpsf2 (float a1, float a2)
{
@@ -224,6 +258,7 @@ __cmpsf2 (float a1, float a2)
}
/* multiply two floats */
+
float
__mulsf3 (float a1, float a2)
{
@@ -273,6 +308,7 @@ __mulsf3 (float a1, float a2)
}
/* divide two floats */
+
float
__divsf3 (float a1, float a2)
{
@@ -339,6 +375,7 @@ __divsf3 (float a1, float a2)
}
/* convert int to double */
+
double
__floatsidf (register long a1)
{
@@ -379,6 +416,7 @@ __floatsidf (register long a1)
}
/* negate a float */
+
float
__negsf2 (float a1)
{
@@ -393,6 +431,7 @@ __negsf2 (float a1)
}
/* negate a double */
+
double
__negdf2 (double a1)
{
@@ -408,6 +447,7 @@ __negdf2 (double a1)
}
/* convert float to double */
+
double
__extendsfdf2 (float a1)
{
@@ -433,6 +473,7 @@ __extendsfdf2 (float a1)
}
/* convert double to float */
+
float
__truncdfsf2 (double a1)
{
@@ -470,6 +511,7 @@ __truncdfsf2 (double a1)
}
/* compare two doubles */
+
long
__cmpdf2 (double a1, double a2)
{
@@ -495,6 +537,7 @@ __cmpdf2 (double a1, double a2)
}
/* convert double to int */
+
long
__fixdfsi (double a1)
{
@@ -523,6 +566,7 @@ __fixdfsi (double a1)
}
/* convert double to unsigned int */
+
unsigned
long __fixunsdfsi (double a1)
{
@@ -553,6 +597,7 @@ long __fixunsdfsi (double a1)
/* For now, the hard double-precision routines simply
punt and do it in single */
/* addtwo doubles */
+
double
__adddf3 (double a1, double a2)
{
@@ -560,6 +605,7 @@ __adddf3 (double a1, double a2)
}
/* subtract two doubles */
+
double
__subdf3 (double a1, double a2)
{
@@ -567,15 +613,226 @@ __subdf3 (double a1, double a2)
}
/* multiply two doubles */
+
double
__muldf3 (double a1, double a2)
{
return ((float) a1 * (float) a2);
}
+/*
+ *
+ * Name: Barrett Richardson
+ * E-mail: barrett@iglou.com
+ * When: Thu Dec 15 10:31:11 EST 1994
+ *
+ * callable function:
+ *
+ * double __divdf3(double a1, double a2);
+ *
+ * Does software divide of a1 / a2.
+ *
+ * Based largely on __divsf3() in floatlib.c in the gcc
+ * distribution.
+ *
+ * Purpose: To be used in conjunction with the -msoft-float
+ * option of gcc. You should be able to tack it to the
+ * end of floatlib.c included in the gcc distribution,
+ * and delete the __divdf3() already there which just
+ * calls the single precision function (or may just
+ * use the floating point processor with some configurations).
+ *
+ * You may use this code for whatever your heart desires.
+ */
+
+
+
+
+/*
+ * Compare the the mantissas of two doubles.
+ * Each mantissa is in two longs.
+ *
+ * return 1 if x1's mantissa is greater than x2's
+ * -1 if x1's mantissa is less than x2's
+ * 0 if the two mantissa's are equal.
+ *
+ * The Mantissas won't fit into a 4 byte word, so they are
+ * broken up into two parts.
+ *
+ * This function is used internally by __divdf3()
+ */
+
+int
+__dcmp (long x1m1, long x1m2, long x2m1, long x2m2)
+{
+ if (x1m1 > x2m1)
+ return 1;
+
+ if (x1m1 < x2m1)
+ return -1;
+
+ /* If the first word in the two mantissas were equal check the second word */
+
+ if (x1m2 > x2m2)
+ return 1;
+
+ if (x1m2 < x2m2)
+ return -1;
+
+ return 0;
+}
+
+
/* divide two doubles */
+
double
__divdf3 (double a1, double a2)
{
- return ((float) a1 / (float) a2);
+
+ int sign,
+ exponent,
+ bit_bucket;
+
+ register unsigned long mantissa1,
+ mantissa2,
+ x1m1,
+ x1m2,
+ x2m1,
+ x2m2,
+ mask;
+
+ union _doubleu x1,
+ x2,
+ result;
+
+
+ x1.d = a1;
+ x2.d = a2;
+
+ exponent = x1.ieee.exponent - x2.ieee.exponent + EXCESSD;
+
+ sign = x1.ieee.sign ^ x2.ieee.sign;
+
+ x2.ieee.sign = 0; /* don't want the sign bit to affect any zero */
+ /* comparisons when checking for zero divide */
+
+ if (!x2.l.lower && !x2.l.upper) { /* check for zero divide */
+ result.l.lower = 0x0;
+ if (sign)
+ result.l.upper = 0xFFF00000; /* negative infinity */
+ else
+ result.l.upper = 0x7FF00000; /* positive infinity */
+ return result.d;
+ }
+
+ if (!x1.l.upper && !x1.l.lower) /* check for 0.0 numerator */
+ return (0.0);
+
+ x1m1 = x1.ieee.mantissa1 | D_PHANTOM_BIT; /* turn on phantom bit */
+ x1m2 = x1.ieee.mantissa2;
+
+ x2m1 = x2.ieee.mantissa1 | D_PHANTOM_BIT; /* turn on phantom bit */
+ x2m2 = x2.ieee.mantissa2;
+
+ if (__dcmp(x1m1,x1m2,x2m1,x2m2) < 0) {
+
+ /* if x1's mantissa is less than x2's shift it left one and decrement */
+ /* the exponent to accommodate the change in the mantissa */
+
+ x1m1 <<= 1; /* */
+ bit_bucket = x1m2 >> 31; /* Shift mantissa left one */
+ x1m1 |= bit_bucket; /* */
+ x1m2 <<= 1; /* */
+
+ exponent--;
+ }
+
+
+ mantissa1 = 0;
+ mantissa2 = 0;
+
+
+ /* Get the first part of the results mantissa using successive */
+ /* subtraction. */
+
+ mask = 0x00200000;
+ while (mask) {
+
+ if (__dcmp(x1m1,x1m2,x2m1,x2m2) >= 0) {
+
+ /* subtract x2's mantissa from x1's */
+
+ mantissa1 |= mask; /* turn on a bit in the result */
+
+ if (x2m2 > x1m2)
+ x1m1--;
+ x1m2 -= x2m2;
+ x1m1 -= x2m1;
+ }
+
+ x1m1 <<= 1; /* */
+ bit_bucket = x1m2 >> 31; /* Shift mantissa left one */
+ x1m1 |= bit_bucket; /* */
+ x1m2 <<= 1; /* */
+
+ mask >>= 1;
+ }
+
+ /* Get the second part of the results mantissa using successive */
+ /* subtraction. */
+
+ mask = 0x80000000;
+ while (mask) {
+
+ if (__dcmp(x1m1,x1m2,x2m1,x2m2) >= 0) {
+
+ /* subtract x2's mantissa from x1's */
+
+ mantissa2 |= mask; /* turn on a bit in the result */
+
+ if (x2m2 > x1m2)
+ x1m1--;
+ x1m2 -= x2m2;
+ x1m1 -= x2m1;
+ }
+ x1m1 <<= 1; /* */
+ bit_bucket = x1m2 >> 31; /* Shift mantissa left one */
+ x1m1 |= bit_bucket; /* */
+ x1m2 <<= 1; /* */
+
+ mask >>= 1;
+ }
+
+ /* round up by adding 1 to mantissa */
+
+ if (mantissa2 == 0xFFFFFFFF) { /* check for over flow */
+
+ /* spill if overflow */
+
+ mantissa2 = 0;
+ mantissa1++;
+ }
+ else
+ mantissa2++;
+
+ exponent++; /* increment exponent (mantissa must be shifted right */
+ /* also) */
+
+ /* shift mantissa right one and assume a phantom bit (which really gives */
+ /* 53 bits of precision in the mantissa) */
+
+ mantissa2 >>= 1;
+ bit_bucket = mantissa1 & 1;
+ mantissa2 |= (bit_bucket << 31);
+ mantissa1 >>= 1;
+
+ /* put all the info into the result */
+
+ result.ieee.exponent = exponent;
+ result.ieee.sign = sign;
+ result.ieee.mantissa1 = mantissa1;
+ result.ieee.mantissa2 = mantissa2;
+
+
+ return result.d;
}
diff --git a/gnu/usr.bin/gcc/flow.c b/gnu/usr.bin/gcc/flow.c
index 1e4ff88175c..b9c52afc965 100644
--- a/gnu/usr.bin/gcc/flow.c
+++ b/gnu/usr.bin/gcc/flow.c
@@ -1,5 +1,5 @@
/* Data flow analysis for GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -108,8 +108,8 @@ Boston, MA 02111-1307, USA. */
register usage: reg_n_refs, reg_n_deaths, reg_n_sets, reg_live_length,
reg_n_calls_crosses and reg_basic_block. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "basic-block.h"
#include "insn-config.h"
@@ -117,11 +117,19 @@ Boston, MA 02111-1307, USA. */
#include "hard-reg-set.h"
#include "flags.h"
#include "output.h"
+#include "except.h"
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
+/* The contents of the current function definition are allocated
+ in this obstack, and all are freed at the end of the function.
+ For top-level functions, this is temporary_obstack.
+ Separate obstacks are made for nested functions. */
+
+extern struct obstack *function_obstack;
+
/* List of labels that must never be deleted. */
extern rtx forced_labels;
@@ -154,7 +162,8 @@ int n_basic_blocks;
int max_regno;
-/* Maximum number of SCRATCH rtx's used in any basic block of this function. */
+/* Maximum number of SCRATCH rtx's used in any basic block of this
+ function. */
int max_scratch;
@@ -162,56 +171,9 @@ int max_scratch;
static int num_scratch;
-/* 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.
- REG_BLOCK_UNKNOWN (-1) means it hasn't been seen yet so we don't know.
- This information remains valid for the rest of the compilation
- of the current function; it is used to control register allocation. */
-
-int *reg_basic_block;
-
-/* Indexed by n, gives number of times (REG n) is used or set, each
- weighted by its loop-depth.
- This information remains valid for the rest of the compilation
- of the current function; it is used to control register allocation. */
-
-int *reg_n_refs;
-
-/* Indexed by N; says whether a pseudo register N was ever used
- within a SUBREG that changes the size of the reg. Some machines prohibit
- such objects to be in certain (usually floating-point) registers. */
-
-char *reg_changes_size;
-
-/* Indexed by N, gives number of places register N dies.
- This information remains valid for the rest of the compilation
- of the current function; it is used to control register allocation. */
-
-short *reg_n_deaths;
+/* Indexed by n, giving various register information */
-/* Indexed by N, gives 1 if that reg is live across any CALL_INSNs.
- This information remains valid for the rest of the compilation
- of the current function; it is used to control register allocation. */
-
-int *reg_n_calls_crossed;
-
-/* Total number of instructions at which (REG n) is live.
- The larger this is, the less priority (REG n) gets for
- allocation in a real register.
- This information remains valid for the rest of the compilation
- of the current function; it is used to control register allocation.
-
- local-alloc.c may alter this number to change the priority.
-
- Negative values are special.
- -1 is used to mark a pseudo reg which has a constant or memory equivalent
- and is used infrequently enough that it should not get a hard register.
- -2 is used to mark a pseudo reg for a parameter, when a frame pointer
- is not required. global.c makes an allocno for this but does
- not try to assign a hard register to it. */
-
-int *reg_live_length;
+reg_info *reg_n_info;
/* Element N is the next insn that uses (hard or pseudo) register number N
within the current basic block; or zero, if there is no such insn.
@@ -287,11 +249,11 @@ static HARD_REG_SET elim_reg_set;
/* Forward declarations */
static void find_basic_blocks PROTO((rtx, rtx));
-static int uses_reg_or_mem PROTO((rtx));
static void mark_label_ref PROTO((rtx, rtx, int));
static void life_analysis PROTO((rtx, int));
void allocate_for_life_analysis PROTO((void));
-static void init_regset_vector PROTO((regset *, regset, int, int));
+void init_regset_vector PROTO((regset *, int, struct obstack *));
+void free_regset_vector PROTO((regset *, int));
static void propagate_block PROTO((regset, rtx, rtx, int,
regset, int));
static rtx flow_delete_insn PROTO((rtx));
@@ -327,7 +289,7 @@ flow_analysis (f, nregs, file)
#endif
/* Record which registers will be eliminated. We use this in
- mark_used_regs. */
+ mark_used_regs. */
CLEAR_HARD_REG_SET (elim_reg_set);
@@ -358,6 +320,10 @@ flow_analysis (f, nregs, file)
&& nonlocal_label_list != 0)
|| prev_code == BARRIER)))
i++;
+
+ if (code == CALL_INSN && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+ code = INSN;
+
if (code != NOTE)
prev_code = code;
}
@@ -410,6 +376,7 @@ find_basic_blocks (f, nonlocal_label_list)
/* List of label_refs to all labels whose addresses are taken
and used as data. */
rtx label_value_list;
+ int label_value_list_marked_live;
rtx x, note;
enum rtx_code prev_code, code;
int depth, pass;
@@ -418,6 +385,7 @@ find_basic_blocks (f, nonlocal_label_list)
restart:
label_value_list = 0;
+ label_value_list_marked_live = 0;
block_live_static = block_live;
bzero (block_live, n_basic_blocks);
bzero (block_marked, n_basic_blocks);
@@ -448,7 +416,8 @@ find_basic_blocks (f, nonlocal_label_list)
|| (GET_RTX_CLASS (code) == 'i'
&& (prev_code == JUMP_INSN
|| (prev_code == CALL_INSN
- && nonlocal_label_list != 0)
+ && nonlocal_label_list != 0
+ && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
|| prev_code == BARRIER)))
{
basic_block_head[++i] = insn;
@@ -493,17 +462,13 @@ find_basic_blocks (f, nonlocal_label_list)
abort ();
n_basic_blocks = i + 1;
- /* Don't delete the labels (in this function)
- that are referenced by non-jump instructions. */
-
- for (x = label_value_list; x; x = XEXP (x, 1))
- if (! LABEL_REF_NONLOCAL_P (x))
- block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
-
for (x = forced_labels; x; x = XEXP (x, 1))
if (! LABEL_REF_NONLOCAL_P (x))
block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
+ for (x = exception_handler_labels; x; x = XEXP (x, 1))
+ block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
+
/* Record which basic blocks control can drop in to. */
for (i = 0; i < n_basic_blocks; i++)
@@ -527,57 +492,41 @@ find_basic_blocks (f, nonlocal_label_list)
/* Find all indirect jump insns and mark them as possibly jumping to all
the labels whose addresses are explicitly used. This is because,
when there are computed gotos, we can't tell which labels they jump
- to, of all the possibilities.
-
- Tablejumps and casesi insns are OK and we can recognize them by
- a (use (label_ref)). */
+ to, of all the possibilities. */
for (insn = f; insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == JUMP_INSN)
+ if (computed_jump_p (insn))
{
- rtx pat = PATTERN (insn);
- int computed_jump = 0;
-
- if (GET_CODE (pat) == PARALLEL)
- {
- int len = XVECLEN (pat, 0);
- int has_use_labelref = 0;
-
- for (i = len - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (pat, 0, i)) == USE
- && (GET_CODE (XEXP (XVECEXP (pat, 0, i), 0))
- == LABEL_REF))
- has_use_labelref = 1;
-
- if (! has_use_labelref)
- for (i = len - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (pat, 0, i)) == SET
- && SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
- && uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
- computed_jump = 1;
- }
- else if (GET_CODE (pat) == SET
- && SET_DEST (pat) == pc_rtx
- && uses_reg_or_mem (SET_SRC (pat)))
- computed_jump = 1;
-
- if (computed_jump)
+ if (label_value_list_marked_live == 0)
{
+ label_value_list_marked_live = 1;
+
+ /* This could be made smarter by only considering
+ these live, if the computed goto is live. */
+
+ /* Don't delete the labels (in this function) that
+ are referenced by non-jump instructions. */
+
for (x = label_value_list; x; x = XEXP (x, 1))
- mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
- insn, 0);
+ if (! LABEL_REF_NONLOCAL_P (x))
+ block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
+ }
- for (x = forced_labels; x; x = XEXP (x, 1))
- mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
+ for (x = label_value_list; x; x = XEXP (x, 1))
+ mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
+ insn, 0);
+
+ for (x = forced_labels; x; x = XEXP (x, 1))
+ mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
insn, 0);
- }
}
/* Find all call insns and mark them as possibly jumping
to all the nonlocal goto handler labels. */
for (insn = f; insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == CALL_INSN)
+ if (GET_CODE (insn) == CALL_INSN
+ && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
{
for (x = nonlocal_label_list; x; x = XEXP (x, 1))
mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
@@ -594,6 +543,13 @@ find_basic_blocks (f, nonlocal_label_list)
gotos. */
}
+ /* All blocks associated with labels in label_value_list are
+ trivially considered as marked live, if the list is empty.
+ We do this to speed up the below code. */
+
+ if (label_value_list == 0)
+ label_value_list_marked_live = 1;
+
/* Pass over all blocks, marking each block that is reachable
and has not yet been marked.
Keep doing this until, in one pass, no blocks have been marked.
@@ -613,6 +569,28 @@ find_basic_blocks (f, nonlocal_label_list)
insn = basic_block_end[i];
if (GET_CODE (insn) == JUMP_INSN)
mark_label_ref (PATTERN (insn), insn, 0);
+
+ if (label_value_list_marked_live == 0)
+ /* Now that we know that this block is live, mark as
+ live, all the blocks that we might be able to get
+ to as live. */
+
+ for (insn = basic_block_head[i];
+ insn != NEXT_INSN (basic_block_end[i]);
+ insn = NEXT_INSN (insn))
+ {
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ {
+ for (note = REG_NOTES (insn);
+ note;
+ note = XEXP (note, 1))
+ if (REG_NOTE_KIND (note) == REG_LABEL)
+ {
+ x = XEXP (note, 0);
+ block_live[BLOCK_NUM (x)] = 1;
+ }
+ }
+ }
}
}
@@ -759,38 +737,6 @@ find_basic_blocks (f, nonlocal_label_list)
/* Subroutines of find_basic_blocks. */
-/* Return 1 if X contain a REG or MEM that is not in the constant pool. */
-
-static int
-uses_reg_or_mem (x)
- rtx x;
-{
- enum rtx_code code = GET_CODE (x);
- int i, j;
- char *fmt;
-
- if (code == REG
- || (code == MEM
- && ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))))
- return 1;
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e'
- && uses_reg_or_mem (XEXP (x, i)))
- return 1;
-
- if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (x, i); j++)
- if (uses_reg_or_mem (XVECEXP (x, i, j)))
- return 1;
- }
-
- return 0;
-}
-
/* Check expression X for label references;
if one is found, add INSN to the label's chain of references.
@@ -878,7 +824,6 @@ life_analysis (f, nregs)
rtx f;
int nregs;
{
- register regset tem;
int first_pass;
int changed;
/* For each basic block, a bitmask of regs
@@ -924,28 +869,20 @@ life_analysis (f, nregs)
if there isn't enough space.
Don't use oballoc since we may need to allocate other things during
this function on the temporary obstack. */
- tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_live_at_end, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_live_at_end, n_basic_blocks, &flow_obstack);
basic_block_new_live_at_end
= (regset *) alloca (n_basic_blocks * sizeof (regset));
- tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_new_live_at_end, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_new_live_at_end, n_basic_blocks,
+ &flow_obstack);
basic_block_significant
= (regset *) alloca (n_basic_blocks * sizeof (regset));
- tem = (regset) obstack_alloc (&flow_obstack, n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_significant, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_significant, n_basic_blocks, &flow_obstack);
/* Record which insns refer to any volatile memory
or for any reason can't be deleted just because they are dead stores.
- Also, delete any insns that copy a register to itself. */
+ Also, delete any insns that copy a register to itself. */
for (insn = f; insn; insn = NEXT_INSN (insn))
{
@@ -958,8 +895,25 @@ life_analysis (f, nregs)
if (GET_CODE (PATTERN (insn)) == SET
&& GET_CODE (SET_DEST (PATTERN (insn))) == REG
&& GET_CODE (SET_SRC (PATTERN (insn))) == REG
- && REGNO (SET_DEST (PATTERN (insn))) ==
- REGNO (SET_SRC (PATTERN (insn)))
+ && (REGNO (SET_DEST (PATTERN (insn)))
+ == REGNO (SET_SRC (PATTERN (insn))))
+ /* Insns carrying these notes are useful later on. */
+ && ! find_reg_note (insn, REG_EQUAL, NULL_RTX))
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
+ /* Delete (in effect) any obvious no-op moves. */
+ else if (GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_DEST (PATTERN (insn))) == SUBREG
+ && GET_CODE (SUBREG_REG (SET_DEST (PATTERN (insn)))) == REG
+ && GET_CODE (SET_SRC (PATTERN (insn))) == SUBREG
+ && GET_CODE (SUBREG_REG (SET_SRC (PATTERN (insn)))) == REG
+ && (REGNO (SUBREG_REG (SET_DEST (PATTERN (insn))))
+ == REGNO (SUBREG_REG (SET_SRC (PATTERN (insn)))))
+ && SUBREG_WORD (SET_DEST (PATTERN (insn))) ==
+ SUBREG_WORD (SET_SRC (PATTERN (insn)))
/* Insns carrying these notes are useful later on. */
&& ! find_reg_note (insn, REG_EQUAL, NULL_RTX))
{
@@ -1025,12 +979,10 @@ life_analysis (f, nregs)
{
/* If exiting needs the right stack value,
consider the stack pointer live at the end of the function. */
- basic_block_live_at_end[n_basic_blocks - 1]
- [STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+ STACK_POINTER_REGNUM);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+ STACK_POINTER_REGNUM);
}
/* Mark the frame pointer is needed at the end of the function. If
@@ -1039,38 +991,33 @@ life_analysis (f, nregs)
if (n_basic_blocks > 0)
{
- basic_block_live_at_end[n_basic_blocks - 1]
- [FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (FRAME_POINTER_REGNUM % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+ FRAME_POINTER_REGNUM);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+ FRAME_POINTER_REGNUM);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If they are different, also mark the hard frame pointer as live */
- basic_block_live_at_end[n_basic_blocks - 1]
- [HARD_FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (HARD_FRAME_POINTER_REGNUM
- % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [HARD_FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (HARD_FRAME_POINTER_REGNUM
- % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1],
+ HARD_FRAME_POINTER_REGNUM);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1],
+ HARD_FRAME_POINTER_REGNUM);
#endif
}
- /* Mark all global registers as being live at the end of the function
- since they may be referenced by our caller. */
+ /* Mark all global registers and all registers used by the epilogue
+ as being live at the end of the function since they may be
+ referenced by our caller. */
if (n_basic_blocks > 0)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i])
+ if (global_regs[i]
+#ifdef EPILOGUE_USES
+ || EPILOGUE_USES (i)
+#endif
+ )
{
- basic_block_live_at_end[n_basic_blocks - 1]
- [i / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
- basic_block_new_live_at_end[n_basic_blocks - 1]
- [i / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (basic_block_live_at_end[n_basic_blocks - 1], i);
+ SET_REGNO_REG_SET (basic_block_new_live_at_end[n_basic_blocks - 1], i);
}
/* Propagate life info through the basic blocks
@@ -1105,21 +1052,18 @@ life_analysis (f, nregs)
reg that is live at the end now but was not live there before
is one of the significant regs of this basic block). */
- for (j = 0; j < regset_size; j++)
- {
- register REGSET_ELT_TYPE x
- = (basic_block_new_live_at_end[i][j]
- & ~basic_block_live_at_end[i][j]);
- if (x)
- consider = 1;
- if (x & basic_block_significant[i][j])
- {
- must_rescan = 1;
- consider = 1;
- break;
- }
- }
-
+ EXECUTE_IF_AND_COMPL_IN_REG_SET
+ (basic_block_new_live_at_end[i],
+ basic_block_live_at_end[i], 0, j,
+ {
+ consider = 1;
+ if (REGNO_REG_SET_P (basic_block_significant[i], j))
+ {
+ must_rescan = 1;
+ goto done;
+ }
+ });
+ done:
if (! consider)
continue;
}
@@ -1133,23 +1077,22 @@ life_analysis (f, nregs)
/* No complete rescan needed;
just record those variables newly known live at end
as live at start as well. */
- for (j = 0; j < regset_size; j++)
- {
- register REGSET_ELT_TYPE x
- = (basic_block_new_live_at_end[i][j]
- & ~basic_block_live_at_end[i][j]);
- basic_block_live_at_start[i][j] |= x;
- basic_block_live_at_end[i][j] |= x;
- }
+ IOR_AND_COMPL_REG_SET (basic_block_live_at_start[i],
+ basic_block_new_live_at_end[i],
+ basic_block_live_at_end[i]);
+
+ IOR_AND_COMPL_REG_SET (basic_block_live_at_end[i],
+ basic_block_new_live_at_end[i],
+ basic_block_live_at_end[i]);
}
else
{
/* Update the basic_block_live_at_start
by propagation backwards through the block. */
- bcopy ((char *) basic_block_new_live_at_end[i],
- (char *) basic_block_live_at_end[i], regset_bytes);
- bcopy ((char *) basic_block_live_at_end[i],
- (char *) basic_block_live_at_start[i], regset_bytes);
+ COPY_REG_SET (basic_block_live_at_end[i],
+ basic_block_new_live_at_end[i]);
+ COPY_REG_SET (basic_block_live_at_start[i],
+ basic_block_live_at_end[i]);
propagate_block (basic_block_live_at_start[i],
basic_block_head[i], basic_block_end[i], 0,
first_pass ? basic_block_significant[i]
@@ -1164,12 +1107,8 @@ life_analysis (f, nregs)
that falls through into this one (if any). */
head = basic_block_head[i];
if (basic_block_drops_in[i])
- {
- register int j;
- for (j = 0; j < regset_size; j++)
- basic_block_new_live_at_end[i-1][j]
- |= basic_block_live_at_start[i][j];
- }
+ IOR_REG_SET (basic_block_new_live_at_end[i-1],
+ basic_block_live_at_start[i]);
/* Update the basic_block_new_live_at_end's of
all the blocks that jump to this one. */
@@ -1179,10 +1118,8 @@ life_analysis (f, nregs)
jump = LABEL_NEXTREF (jump))
{
register int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
- register int j;
- for (j = 0; j < regset_size; j++)
- basic_block_new_live_at_end[from_block][j]
- |= basic_block_live_at_start[i][j];
+ IOR_REG_SET (basic_block_new_live_at_end[from_block],
+ basic_block_live_at_start[i]);
}
}
#ifdef USE_C_ALLOCA
@@ -1198,10 +1135,11 @@ life_analysis (f, nregs)
one basic block. */
if (n_basic_blocks > 0)
- for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (basic_block_live_at_start[0][i / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)))
- reg_basic_block[i] = REG_BLOCK_GLOBAL;
+ EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[0],
+ FIRST_PSEUDO_REGISTER, i,
+ {
+ REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
+ });
/* Now the life information is accurate.
Make one more pass over each basic block
@@ -1232,14 +1170,16 @@ life_analysis (f, nregs)
But we don't need to do this for the user's variables, since
ANSI says only volatile variables need this. */
#ifdef LONGJMP_RESTORE_FROM_STACK
- for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
- if (regs_live_at_setjmp[i / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS))
- && regno_reg_rtx[i] != 0 && ! REG_USERVAR_P (regno_reg_rtx[i]))
- {
- reg_live_length[i] = -1;
- reg_basic_block[i] = -1;
- }
+ EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
+ FIRST_PSEUDO_REGISTER, i,
+ {
+ if (regno_reg_rtx[i] != 0
+ && ! REG_USERVAR_P (regno_reg_rtx[i]))
+ {
+ REG_LIVE_LENGTH (i) = -1;
+ REG_BASIC_BLOCK (i) = -1;
+ }
+ });
#endif
#endif
@@ -1252,14 +1192,23 @@ life_analysis (f, nregs)
If the pseudo goes in a hard reg, some other value may occupy
that hard reg where this pseudo is dead, thus clobbering the pseudo.
Conclusion: such a pseudo must not go in a hard reg. */
- for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
- if ((regs_live_at_setjmp[i / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS)))
- && regno_reg_rtx[i] != 0)
- {
- reg_live_length[i] = -1;
- reg_basic_block[i] = -1;
- }
+ EXECUTE_IF_SET_IN_REG_SET (regs_live_at_setjmp,
+ FIRST_PSEUDO_REGISTER, i,
+ {
+ if (regno_reg_rtx[i] != 0)
+ {
+ REG_LIVE_LENGTH (i) = -1;
+ REG_BASIC_BLOCK (i) = -1;
+ }
+ });
+
+
+ free_regset_vector (basic_block_live_at_end, n_basic_blocks);
+ free_regset_vector (basic_block_new_live_at_end, n_basic_blocks);
+ free_regset_vector (basic_block_significant, n_basic_blocks);
+ basic_block_live_at_end = (regset *)0;
+ basic_block_new_live_at_end = (regset *)0;
+ basic_block_significant = (regset *)0;
obstack_free (&flow_obstack, NULL_PTR);
}
@@ -1273,66 +1222,60 @@ void
allocate_for_life_analysis ()
{
register int i;
- register regset tem;
-
- regset_size = ((max_regno + REGSET_ELT_BITS - 1) / REGSET_ELT_BITS);
- regset_bytes = regset_size * sizeof (*(regset)0);
-
- reg_n_refs = (int *) oballoc (max_regno * sizeof (int));
- bzero ((char *) reg_n_refs, max_regno * sizeof (int));
- reg_n_sets = (short *) oballoc (max_regno * sizeof (short));
- bzero ((char *) reg_n_sets, max_regno * sizeof (short));
+ /* Recalculate the register space, in case it has grown. Old style
+ vector oriented regsets would set regset_{size,bytes} here also. */
+ allocate_reg_info (max_regno, FALSE, FALSE);
- reg_n_deaths = (short *) oballoc (max_regno * sizeof (short));
- bzero ((char *) reg_n_deaths, max_regno * sizeof (short));
-
- reg_changes_size = (char *) oballoc (max_regno * sizeof (char));
- bzero (reg_changes_size, max_regno * sizeof (char));;
-
- reg_live_length = (int *) oballoc (max_regno * sizeof (int));
- bzero ((char *) reg_live_length, max_regno * sizeof (int));
-
- reg_n_calls_crossed = (int *) oballoc (max_regno * sizeof (int));
- bzero ((char *) reg_n_calls_crossed, max_regno * sizeof (int));
-
- reg_basic_block = (int *) oballoc (max_regno * sizeof (int));
+ /* Because both reg_scan and flow_analysis want to set up the REG_N_SETS
+ information, explicitly reset it here. The allocation should have
+ already happened on the previous reg_scan pass. Make sure in case
+ some more registers were allocated. */
for (i = 0; i < max_regno; i++)
- reg_basic_block[i] = REG_BLOCK_UNKNOWN;
+ REG_N_SETS (i) = 0;
basic_block_live_at_start
= (regset *) oballoc (n_basic_blocks * sizeof (regset));
- tem = (regset) oballoc (n_basic_blocks * regset_bytes);
- bzero ((char *) tem, n_basic_blocks * regset_bytes);
- init_regset_vector (basic_block_live_at_start, tem,
- n_basic_blocks, regset_bytes);
+ init_regset_vector (basic_block_live_at_start, n_basic_blocks,
+ function_obstack);
- regs_live_at_setjmp = (regset) oballoc (regset_bytes);
- bzero ((char *) regs_live_at_setjmp, regset_bytes);
+ regs_live_at_setjmp = OBSTACK_ALLOC_REG_SET (function_obstack);
+ CLEAR_REG_SET (regs_live_at_setjmp);
}
-/* Make each element of VECTOR point at a regset,
- taking the space for all those regsets from SPACE.
- SPACE is of type regset, but it is really as long as NELTS regsets.
- BYTES_PER_ELT is the number of bytes in one regset. */
+/* Make each element of VECTOR point at a regset. The vector has
+ NELTS elements, and space is allocated from the ALLOC_OBSTACK
+ obstack. */
-static void
-init_regset_vector (vector, space, nelts, bytes_per_elt)
+void
+init_regset_vector (vector, nelts, alloc_obstack)
regset *vector;
- regset space;
int nelts;
- int bytes_per_elt;
+ struct obstack *alloc_obstack;
{
register int i;
- register regset p = space;
for (i = 0; i < nelts; i++)
{
- vector[i] = p;
- p += bytes_per_elt / sizeof (*p);
+ vector[i] = OBSTACK_ALLOC_REG_SET (alloc_obstack);
+ CLEAR_REG_SET (vector[i]);
}
}
+/* Release any additional space allocated for each element of VECTOR point
+ other than the regset header itself. The vector has NELTS elements. */
+
+void
+free_regset_vector (vector, nelts)
+ regset *vector;
+ int nelts;
+{
+ register int i;
+
+ for (i = 0; i < nelts; i++)
+ FREE_REG_SET (vector[i]);
+}
+
/* Compute the registers live at the beginning of a basic block
from those live at the end.
@@ -1369,11 +1312,8 @@ propagate_block (old, first, last, final, significant, bnum)
/* The following variables are used only if FINAL is nonzero. */
/* This vector gets one element for each reg that has been live
at any point in the basic block that has been scanned so far.
- SOMETIMES_MAX says how many elements are in use so far.
- In each element, OFFSET is the byte-number within a regset
- for the register described by the element, and BIT is a mask
- for that register's bit within the byte. */
- register struct sometimes { short offset; short bit; } *regs_sometimes_live;
+ SOMETIMES_MAX says how many elements are in use so far. */
+ register int *regs_sometimes_live;
int sometimes_max = 0;
/* This regset has 1 for each reg that we have seen live so far.
It and REGS_SOMETIMES_LIVE are updated together. */
@@ -1384,8 +1324,8 @@ propagate_block (old, first, last, final, significant, bnum)
current basic block, and adjust as we pass ends and starts of loops. */
loop_depth = basic_block_loop_depth[bnum];
- dead = (regset) alloca (regset_bytes);
- live = (regset) alloca (regset_bytes);
+ dead = ALLOCA_REG_SET ();
+ live = ALLOCA_REG_SET ();
cc0_live = 0;
last_mem_set = 0;
@@ -1405,32 +1345,22 @@ propagate_block (old, first, last, final, significant, bnum)
if (final)
{
- register int i, offset;
- REGSET_ELT_TYPE bit;
+ register int i;
num_scratch = 0;
- maxlive = (regset) alloca (regset_bytes);
- bcopy ((char *) old, (char *) maxlive, regset_bytes);
- regs_sometimes_live
- = (struct sometimes *) alloca (max_regno * sizeof (struct sometimes));
+ maxlive = ALLOCA_REG_SET ();
+ COPY_REG_SET (maxlive, old);
+ regs_sometimes_live = (int *) alloca (max_regno * sizeof (int));
/* Process the regs live at the end of the block.
Enter them in MAXLIVE and REGS_SOMETIMES_LIVE.
- Also mark them as not local to any one basic block. */
-
- for (offset = 0, i = 0; offset < regset_size; offset++)
- for (bit = 1; bit; bit <<= 1, i++)
- {
- if (i == max_regno)
- break;
- if (old[offset] & bit)
- {
- reg_basic_block[i] = REG_BLOCK_GLOBAL;
- regs_sometimes_live[sometimes_max].offset = offset;
- regs_sometimes_live[sometimes_max].bit = i % REGSET_ELT_BITS;
- sometimes_max++;
- }
- }
+ Also mark them as not local to any one basic block. */
+ EXECUTE_IF_SET_IN_REG_SET (old, 0, i,
+ {
+ REG_BASIC_BLOCK (i) = REG_BLOCK_GLOBAL;
+ regs_sometimes_live[sometimes_max] = i;
+ sometimes_max++;
+ });
}
/* Scan the block an insn at a time from end to beginning. */
@@ -1457,11 +1387,7 @@ propagate_block (old, first, last, final, significant, bnum)
warn if any non-volatile datum is live. */
if (final && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
- {
- int i;
- for (i = 0; i < regset_size; i++)
- regs_live_at_setjmp[i] |= old[i];
- }
+ IOR_REG_SET (regs_live_at_setjmp, old);
}
/* Update the life-status of regs for this insn.
@@ -1517,19 +1443,17 @@ propagate_block (old, first, last, final, significant, bnum)
goto flushed;
}
- for (i = 0; i < regset_size; i++)
- {
- dead[i] = 0; /* Faster than bzero here */
- live[i] = 0; /* since regset_size is usually small */
- }
+ CLEAR_REG_SET (dead);
+ CLEAR_REG_SET (live);
/* See if this is an increment or decrement that can be
merged into a following memory address. */
#ifdef AUTO_INC_DEC
{
- register rtx x = PATTERN (insn);
+ register rtx x = single_set (insn);
+
/* Does this instruction increment or decrement a register? */
- if (final && GET_CODE (x) == SET
+ if (final && x != 0
&& GET_CODE (SET_DEST (x)) == REG
&& (GET_CODE (SET_SRC (x)) == PLUS
|| GET_CODE (SET_SRC (x)) == MINUS)
@@ -1604,19 +1528,17 @@ propagate_block (old, first, last, final, significant, bnum)
final, insn);
/* Each call clobbers all call-clobbered regs that are not
- global. Note that the function-value reg is a
+ global or fixed. Note that the function-value reg is a
call-clobbered reg, and mark_set_regs has already had
a chance to handle it. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (call_used_regs[i] && ! global_regs[i])
- dead[i / REGSET_ELT_BITS]
- |= ((REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS));
+ if (call_used_regs[i] && ! global_regs[i]
+ && ! fixed_regs[i])
+ SET_REGNO_REG_SET (dead, i);
/* The stack ptr is used (honorarily) by a CALL insn. */
- live[STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= ((REGSET_ELT_TYPE) 1
- << (STACK_POINTER_REGNUM % REGSET_ELT_BITS));
+ SET_REGNO_REG_SET (live, STACK_POINTER_REGNUM);
/* Calls may also reference any of the global registers,
so they are made live. */
@@ -1631,11 +1553,8 @@ propagate_block (old, first, last, final, significant, bnum)
}
/* Update OLD for the registers used or set. */
- for (i = 0; i < regset_size; i++)
- {
- old[i] &= ~dead[i];
- old[i] |= live[i];
- }
+ AND_COMPL_REG_SET (old, dead);
+ IOR_REG_SET (old, live);
if (GET_CODE (insn) == CALL_INSN && final)
{
@@ -1643,11 +1562,11 @@ propagate_block (old, first, last, final, significant, bnum)
must not go in a register clobbered by calls.
Find all regs now live and record this for them. */
- register struct sometimes *p = regs_sometimes_live;
+ register int *p = regs_sometimes_live;
for (i = 0; i < sometimes_max; i++, p++)
- if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit))
- reg_n_calls_crossed[p->offset * REGSET_ELT_BITS + p->bit]+= 1;
+ if (REGNO_REG_SET_P (old, *p))
+ REG_N_CALLS_CROSSED (*p)++;
}
}
@@ -1657,33 +1576,23 @@ propagate_block (old, first, last, final, significant, bnum)
if (final)
{
- for (i = 0; i < regset_size; i++)
+ register int regno;
+ register int *p;
+
+ EXECUTE_IF_AND_COMPL_IN_REG_SET
+ (live, maxlive, 0, regno,
+ {
+ regs_sometimes_live[sometimes_max++] = regno;
+ SET_REGNO_REG_SET (maxlive, regno);
+ });
+
+ p = regs_sometimes_live;
+ for (i = 0; i < sometimes_max; i++)
{
- register REGSET_ELT_TYPE diff = live[i] & ~maxlive[i];
-
- if (diff)
- {
- register int regno;
- maxlive[i] |= diff;
- for (regno = 0; diff && regno < REGSET_ELT_BITS; regno++)
- if (diff & ((REGSET_ELT_TYPE) 1 << regno))
- {
- regs_sometimes_live[sometimes_max].offset = i;
- regs_sometimes_live[sometimes_max].bit = regno;
- diff &= ~ ((REGSET_ELT_TYPE) 1 << regno);
- sometimes_max++;
- }
- }
+ regno = *p++;
+ if (REGNO_REG_SET_P (old, regno))
+ REG_LIVE_LENGTH (regno)++;
}
-
- {
- register struct sometimes *p = regs_sometimes_live;
- for (i = 0; i < sometimes_max; i++, p++)
- {
- if (old[p->offset] & ((REGSET_ELT_TYPE) 1 << p->bit))
- reg_live_length[p->offset * REGSET_ELT_BITS + p->bit]++;
- }
- }
}
}
flushed: ;
@@ -1691,6 +1600,11 @@ propagate_block (old, first, last, final, significant, bnum)
break;
}
+ FREE_REG_SET (dead);
+ FREE_REG_SET (live);
+ if (final)
+ FREE_REG_SET (maxlive);
+
if (num_scratch > max_scratch)
max_scratch = num_scratch;
}
@@ -1736,9 +1650,6 @@ insn_dead_p (x, needed, call_ok)
if (GET_CODE (r) == REG)
{
register int regno = REGNO (r);
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
/* Don't delete insns to set global regs. */
if ((regno < FIRST_PSEUDO_REGISTER && global_regs[regno])
@@ -1750,10 +1661,10 @@ insn_dead_p (x, needed, call_ok)
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
/* Make sure insns to set arg pointer are never deleted
(if the arg pointer isn't fixed, there will be a USE for
- it, so we can treat it normally). */
+ it, so we can treat it normally). */
|| (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
- || (needed[offset] & bit) != 0)
+ || REGNO_REG_SET_P (needed, regno))
return 0;
/* If this is a hard register, verify that subsequent words are
@@ -1763,9 +1674,7 @@ insn_dead_p (x, needed, call_ok)
int n = HARD_REGNO_NREGS (regno, GET_MODE (r));
while (--n > 0)
- if ((needed[(regno + n) / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1
- << ((regno + n) % REGSET_ELT_BITS))) != 0)
+ if (REGNO_REG_SET_P (needed, regno+n))
return 0;
}
@@ -1862,18 +1771,19 @@ libcall_dead_p (x, needed, note, insn)
/* Return 1 if register REGNO was used before it was set.
In other words, if it is live at function entry.
- Don't count global register variables, though. */
+ Don't count global register variables or variables in registers
+ that can be used for function arg passing, though. */
int
regno_uninitialized (regno)
int regno;
{
if (n_basic_blocks == 0
- || (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
+ || (regno < FIRST_PSEUDO_REGISTER
+ && (global_regs[regno] || FUNCTION_ARG_REGNO_P (regno))))
return 0;
- return (basic_block_live_at_start[0][regno / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS)));
+ return REGNO_REG_SET_P (basic_block_live_at_start[0], regno);
}
/* 1 if register REGNO was alive at a place where `setjmp' was called
@@ -1887,11 +1797,9 @@ regno_clobbered_at_setjmp (regno)
if (n_basic_blocks == 0)
return 0;
- return ((reg_n_sets[regno] > 1
- || (basic_block_live_at_start[0][regno / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS))))
- && (regs_live_at_setjmp[regno / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS))));
+ return ((REG_N_SETS (regno) > 1
+ || REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
+ && REGNO_REG_SET_P (regs_live_at_setjmp, regno));
}
/* Process the registers that are set within X.
@@ -1984,18 +1892,15 @@ mark_set_1 (needed, dead, x, insn, significant)
&& ! (regno < FIRST_PSEUDO_REGISTER && global_regs[regno]))
/* && regno != STACK_POINTER_REGNUM) -- let's try without this. */
{
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- REGSET_ELT_TYPE all_needed = (needed[offset] & bit);
- REGSET_ELT_TYPE some_needed = (needed[offset] & bit);
+ int some_needed = REGNO_REG_SET_P (needed, regno);
+ int some_not_needed = ! some_needed;
/* Mark it as a significant register for this basic block. */
if (significant)
- significant[offset] |= bit;
+ SET_REGNO_REG_SET (significant, regno);
/* Mark it as as dead before this insn. */
- dead[offset] |= bit;
+ SET_REGNO_REG_SET (dead, regno);
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
@@ -2011,17 +1916,14 @@ mark_set_1 (needed, dead, x, insn, significant)
n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (--n > 0)
{
+ int regno_n = regno + n;
+ int needed_regno = REGNO_REG_SET_P (needed, regno_n);
if (significant)
- significant[(regno + n) / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
- dead[(regno + n) / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
- some_needed
- |= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
- all_needed
- &= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
+ SET_REGNO_REG_SET (significant, regno_n);
+
+ SET_REGNO_REG_SET (dead, regno_n);
+ some_needed |= needed_regno;
+ some_not_needed |= ! needed_regno;
}
}
/* Additional data to record if this is the final pass. */
@@ -2044,7 +1946,7 @@ mark_set_1 (needed, dead, x, insn, significant)
reg_next_use[i] = 0;
regs_ever_live[i] = 1;
- reg_n_sets[i]++;
+ REG_N_SETS (i)++;
}
}
else
@@ -2055,25 +1957,25 @@ mark_set_1 (needed, dead, x, insn, significant)
/* Keep track of which basic blocks each reg appears in. */
- if (reg_basic_block[regno] == REG_BLOCK_UNKNOWN)
- reg_basic_block[regno] = blocknum;
- else if (reg_basic_block[regno] != blocknum)
- reg_basic_block[regno] = REG_BLOCK_GLOBAL;
+ if (REG_BASIC_BLOCK (regno) == REG_BLOCK_UNKNOWN)
+ REG_BASIC_BLOCK (regno) = blocknum;
+ else if (REG_BASIC_BLOCK (regno) != blocknum)
+ REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL;
/* Count (weighted) references, stores, etc. This counts a
register twice if it is modified, but that is correct. */
- reg_n_sets[regno]++;
+ REG_N_SETS (regno)++;
- reg_n_refs[regno] += loop_depth;
+ REG_N_REFS (regno) += loop_depth;
/* The insns where a reg is live are normally counted
elsewhere, but we want the count to include the insn
where the reg is set, and the normal counting mechanism
would not count it. */
- reg_live_length[regno]++;
+ REG_LIVE_LENGTH (regno)++;
}
- if (all_needed)
+ if (! some_not_needed)
{
/* Make a logical link from the next following insn
that uses this register, back to this insn.
@@ -2098,7 +2000,7 @@ mark_set_1 (needed, dead, x, insn, significant)
Indicate this by marking the reg being set as dying here. */
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_UNUSED, reg, REG_NOTES (insn));
- reg_n_deaths[REGNO (reg)]++;
+ REG_N_DEATHS (REGNO (reg))++;
}
else
{
@@ -2112,9 +2014,7 @@ mark_set_1 (needed, dead, x, insn, significant)
for (i = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1;
i >= 0; i--)
- if ((needed[(regno + i) / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1
- << ((regno + i) % REGSET_ELT_BITS))) == 0)
+ if (!REGNO_REG_SET_P (needed, regno + i))
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_UNUSED,
gen_rtx (REG, reg_raw_mode[regno + i],
@@ -2212,7 +2112,11 @@ find_auto_inc (needed, x, insn)
else if (GET_CODE (q) == REG
/* PREV_INSN used here to check the semi-open interval
[insn,incr). */
- && ! reg_used_between_p (q, PREV_INSN (insn), incr))
+ && ! reg_used_between_p (q, PREV_INSN (insn), incr)
+ /* We must also check for sets of q as q may be
+ a call clobbered hard register and there may
+ be a call between PREV_INSN (insn) and incr. */
+ && ! reg_set_between_p (q, PREV_INSN (insn), incr))
{
/* We have *p followed sometime later by q = p+size.
Both p and q must be live afterward,
@@ -2273,14 +2177,13 @@ find_auto_inc (needed, x, insn)
it previously wasn't live here. If we don't mark
it as needed, we'll put a REG_DEAD note for it
on this insn, which is incorrect. */
- needed[regno / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (needed, regno);
/* If there are any calls between INSN and INCR, show
that REGNO now crosses them. */
for (temp = insn; temp != incr; temp = NEXT_INSN (temp))
if (GET_CODE (temp) == CALL_INSN)
- reg_n_calls_crossed[regno]++;
+ REG_N_CALLS_CROSSED (regno)++;
}
else
return;
@@ -2312,11 +2215,11 @@ find_auto_inc (needed, x, insn)
/* Count an extra reference to the reg. When a reg is
incremented, spilling it is worse, so we want to make
that less likely. */
- reg_n_refs[regno] += loop_depth;
+ REG_N_REFS (regno) += loop_depth;
/* Count the increment as a setting of the register,
even though it isn't a SET in rtl. */
- reg_n_sets[regno]++;
+ REG_N_SETS (regno)++;
}
}
}
@@ -2374,9 +2277,13 @@ mark_used_regs (needed, live, x, final, insn)
return;
case MEM:
- /* Invalidate the data for the last MEM stored. We could do this only
- if the addresses conflict, but this doesn't seem worthwhile. */
- last_mem_set = 0;
+ /* Invalidate the data for the last MEM stored, but only if MEM is
+ something that can be stored into. */
+ if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)))
+ ; /* needn't clear last_mem_set */
+ else
+ last_mem_set = 0;
#ifdef AUTO_INC_DEC
if (final)
@@ -2389,7 +2296,7 @@ mark_used_regs (needed, live, x, final, insn)
&& REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (GET_MODE (x))
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
- reg_changes_size[REGNO (SUBREG_REG (x))] = 1;
+ REG_CHANGES_SIZE (REGNO (SUBREG_REG (x))) = 1;
/* While we're here, optimize this case. */
x = SUBREG_REG (x);
@@ -2401,7 +2308,7 @@ mark_used_regs (needed, live, x, final, insn)
return;
}
- /* ... fall through ... */
+ /* ... fall through ... */
case REG:
/* See a register other than being set
@@ -2409,13 +2316,11 @@ mark_used_regs (needed, live, x, final, insn)
regno = REGNO (x);
{
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- REGSET_ELT_TYPE all_needed = needed[offset] & bit;
- REGSET_ELT_TYPE some_needed = needed[offset] & bit;
+ int some_needed = REGNO_REG_SET_P (needed, regno);
+ int some_not_needed = ! some_needed;
+
+ SET_REGNO_REG_SET (live, regno);
- live[offset] |= bit;
/* A hard reg in a wide mode may really be multiple registers.
If so, mark all of them just like the first. */
if (regno < FIRST_PSEUDO_REGISTER)
@@ -2456,14 +2361,12 @@ mark_used_regs (needed, live, x, final, insn)
n = HARD_REGNO_NREGS (regno, GET_MODE (x));
while (--n > 0)
{
- live[(regno + n) / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS);
- some_needed
- |= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
- all_needed
- &= (needed[(regno + n) / REGSET_ELT_BITS]
- & (REGSET_ELT_TYPE) 1 << ((regno + n) % REGSET_ELT_BITS));
+ int regno_n = regno + n;
+ int needed_regno = REGNO_REG_SET_P (needed, regno_n);
+
+ SET_REGNO_REG_SET (live, regno_n);
+ some_needed |= needed_regno;
+ some_not_needed |= ! needed_regno;
}
}
if (final)
@@ -2491,14 +2394,14 @@ mark_used_regs (needed, live, x, final, insn)
register int blocknum = BLOCK_NUM (insn);
- if (reg_basic_block[regno] == REG_BLOCK_UNKNOWN)
- reg_basic_block[regno] = blocknum;
- else if (reg_basic_block[regno] != blocknum)
- reg_basic_block[regno] = REG_BLOCK_GLOBAL;
+ if (REG_BASIC_BLOCK (regno) == REG_BLOCK_UNKNOWN)
+ REG_BASIC_BLOCK (regno) = blocknum;
+ else if (REG_BASIC_BLOCK (regno) != blocknum)
+ REG_BASIC_BLOCK (regno) = REG_BLOCK_GLOBAL;
/* Count (weighted) number of uses of each reg. */
- reg_n_refs[regno] += loop_depth;
+ REG_N_REFS (regno) += loop_depth;
}
/* Record and count the insns in which a reg dies.
@@ -2507,7 +2410,7 @@ mark_used_regs (needed, live, x, final, insn)
we do not make a REG_DEAD note; likewise if we already
made such a note. */
- if (! all_needed
+ if (some_not_needed
&& ! dead_or_set_p (insn, x)
#if 0
&& (regno >= FIRST_PSEUDO_REGISTER || ! fixed_regs[regno])
@@ -2530,7 +2433,7 @@ mark_used_regs (needed, live, x, final, insn)
{
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (insn));
- reg_n_deaths[regno]++;
+ REG_N_DEATHS (regno)++;
}
else
{
@@ -2541,9 +2444,7 @@ mark_used_regs (needed, live, x, final, insn)
for (i = HARD_REGNO_NREGS (regno, GET_MODE (x)) - 1;
i >= 0; i--)
- if ((needed[(regno + i) / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1
- << ((regno + i) % REGSET_ELT_BITS))) == 0
+ if (!REGNO_REG_SET_P (needed, regno + i)
&& ! dead_or_set_regno_p (insn, regno + i))
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_DEAD,
@@ -2591,7 +2492,7 @@ mark_used_regs (needed, live, x, final, insn)
&& REGNO (SUBREG_REG (testreg)) >= FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (GET_MODE (testreg))
!= GET_MODE_SIZE (GET_MODE (SUBREG_REG (testreg)))))
- reg_changes_size[REGNO (SUBREG_REG (testreg))] = 1;
+ REG_CHANGES_SIZE (REGNO (SUBREG_REG (testreg))) = 1;
/* Modifying a single register in an alternate mode
does not use any of the old value. But these other
@@ -2631,19 +2532,24 @@ mark_used_regs (needed, live, x, final, insn)
case RETURN:
/* If exiting needs the right stack value, consider this insn as
using the stack pointer. In any event, consider it as using
- all global registers. */
+ all global registers and all registers used by return. */
#ifdef EXIT_IGNORE_STACK
if (! EXIT_IGNORE_STACK
|| (! FRAME_POINTER_REQUIRED && flag_omit_frame_pointer))
#endif
- live[STACK_POINTER_REGNUM / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (STACK_POINTER_REGNUM % REGSET_ELT_BITS);
+ SET_REGNO_REG_SET (live, STACK_POINTER_REGNUM);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i])
- live[i / REGSET_ELT_BITS]
- |= (REGSET_ELT_TYPE) 1 << (i % REGSET_ELT_BITS);
+ if (global_regs[i]
+#ifdef EPILOGUE_USES
+ || EPILOGUE_USES (i)
+#endif
+ )
+ SET_REGNO_REG_SET (live, i);
+ break;
+
+ default:
break;
}
@@ -2683,7 +2589,7 @@ try_pre_increment_1 (insn)
{
/* Find the next use of this reg. If in same basic block,
make it do pre-increment or pre-decrement if appropriate. */
- rtx x = PATTERN (insn);
+ rtx x = single_set (insn);
HOST_WIDE_INT amount = ((GET_CODE (SET_SRC (x)) == PLUS ? 1 : -1)
* INTVAL (XEXP (SET_SRC (x), 1)));
int regno = REGNO (SET_DEST (x));
@@ -2691,10 +2597,9 @@ try_pre_increment_1 (insn)
if (y != 0
&& BLOCK_NUM (y) == BLOCK_NUM (insn)
/* Don't do this if the reg dies, or gets set in y; a standard addressing
- mode would be better. */
+ mode would be better. */
&& ! dead_or_set_p (y, SET_DEST (x))
- && try_pre_increment (y, SET_DEST (PATTERN (insn)),
- amount))
+ && try_pre_increment (y, SET_DEST (x), amount))
{
/* We have found a suitable auto-increment
and already changed insn Y to do it.
@@ -2708,8 +2613,8 @@ try_pre_increment_1 (insn)
less likely. */
if (regno >= FIRST_PSEUDO_REGISTER)
{
- reg_n_refs[regno] += loop_depth;
- reg_n_sets[regno]++;
+ REG_N_REFS (regno) += loop_depth;
+ REG_N_SETS (regno)++;
}
return 1;
}
@@ -2882,19 +2787,19 @@ dump_flow_info (file)
fprintf (file, "%d registers.\n", max_regno);
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (reg_n_refs[i])
+ if (REG_N_REFS (i))
{
enum reg_class class, altclass;
fprintf (file, "\nRegister %d used %d times across %d insns",
- i, reg_n_refs[i], reg_live_length[i]);
- if (reg_basic_block[i] >= 0)
- fprintf (file, " in block %d", reg_basic_block[i]);
- if (reg_n_deaths[i] != 1)
- fprintf (file, "; dies in %d places", reg_n_deaths[i]);
- if (reg_n_calls_crossed[i] == 1)
+ i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
+ if (REG_BASIC_BLOCK (i) >= 0)
+ fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
+ if (REG_N_DEATHS (i) != 1)
+ fprintf (file, "; dies in %d places", REG_N_DEATHS (i));
+ if (REG_N_CALLS_CROSSED (i) == 1)
fprintf (file, "; crosses 1 call");
- else if (reg_n_calls_crossed[i])
- fprintf (file, "; crosses %d calls", reg_n_calls_crossed[i]);
+ else if (REG_N_CALLS_CROSSED (i))
+ fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
if (PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
class = reg_preferred_class (i);
@@ -2943,14 +2848,112 @@ dump_flow_info (file)
}
fprintf (file, "\nRegisters live at start:");
for (regno = 0; regno < max_regno; regno++)
- {
- register int offset = regno / REGSET_ELT_BITS;
- register REGSET_ELT_TYPE bit
- = (REGSET_ELT_TYPE) 1 << (regno % REGSET_ELT_BITS);
- if (basic_block_live_at_start[i][offset] & bit)
- fprintf (file, " %d", regno);
- }
+ if (REGNO_REG_SET_P (basic_block_live_at_start[i], regno))
+ fprintf (file, " %d", regno);
fprintf (file, "\n");
}
fprintf (file, "\n");
}
+
+
+/* Like print_rtl, but also print out live information for the start of each
+ basic block. */
+
+void
+print_rtl_with_bb (outf, rtx_first)
+ FILE *outf;
+ rtx rtx_first;
+{
+ register rtx tmp_rtx;
+
+ if (rtx_first == 0)
+ fprintf (outf, "(nil)\n");
+
+ else
+ {
+ int i, bb;
+ enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
+ int max_uid = get_max_uid ();
+ int *start = (int *) alloca (max_uid * sizeof (int));
+ int *end = (int *) alloca (max_uid * sizeof (int));
+ char *in_bb_p = (char *) alloca (max_uid * sizeof (enum bb_state));
+
+ for (i = 0; i < max_uid; i++)
+ {
+ start[i] = end[i] = -1;
+ in_bb_p[i] = NOT_IN_BB;
+ }
+
+ for (i = n_basic_blocks-1; i >= 0; i--)
+ {
+ rtx x;
+ start[INSN_UID (basic_block_head[i])] = i;
+ end[INSN_UID (basic_block_end[i])] = i;
+ for (x = basic_block_head[i]; x != NULL_RTX; x = NEXT_INSN (x))
+ {
+ in_bb_p[ INSN_UID(x)]
+ = (in_bb_p[ INSN_UID(x)] == NOT_IN_BB)
+ ? IN_ONE_BB : IN_MULTIPLE_BB;
+ if (x == basic_block_end[i])
+ break;
+ }
+ }
+
+ for (tmp_rtx = rtx_first; NULL != tmp_rtx; tmp_rtx = NEXT_INSN (tmp_rtx))
+ {
+ if ((bb = start[INSN_UID (tmp_rtx)]) >= 0)
+ {
+ int pos = 18;
+
+ if (PREV_INSN (tmp_rtx) != 0
+ && end[INSN_UID (PREV_INSN (tmp_rtx))] >= 0)
+ fprintf (outf, " start");
+ else
+ fprintf (outf, ";; Start");
+
+ fprintf (outf, " of basic block %d.\n;; Registers live:", bb);
+
+ EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[bb], 0, i,
+ {
+ if (pos > 65)
+ {
+ fprintf (outf, "\n;;\t");
+ pos = 10;
+ }
+
+ fprintf (outf, " %d", i);
+ pos += (i >= 100 ? 4 : 3);
+ if (i < FIRST_PSEUDO_REGISTER)
+ {
+ fprintf (outf, " [%s]",
+ reg_names[i]);
+ pos += (strlen (reg_names[i])
+ + 3);
+ }
+ });
+ putc ('\n', outf);
+ putc ('\n', outf);
+ }
+
+ if (in_bb_p[ INSN_UID(tmp_rtx)] == NOT_IN_BB
+ && GET_CODE (tmp_rtx) != NOTE
+ && GET_CODE (tmp_rtx) != BARRIER)
+ fprintf (outf, ";; Insn is not within a basic block\n");
+ else if (in_bb_p[ INSN_UID(tmp_rtx)] == IN_MULTIPLE_BB)
+ fprintf (outf, ";; Insn is in multiple basic blocks\n");
+
+ print_rtl_single (outf, tmp_rtx);
+ putc ('\n', outf);
+
+ if ((bb = end[INSN_UID (tmp_rtx)]) >= 0)
+ {
+ fprintf (outf, "\n;; End of basic block %d", bb);
+ if (NEXT_INSN (tmp_rtx) != 0
+ && start[INSN_UID (NEXT_INSN (tmp_rtx))] >= 0)
+ fprintf (outf, ";");
+ else
+ fprintf (outf, ".\n");
+ }
+ }
+ }
+}
diff --git a/gnu/usr.bin/gcc/function.c b/gnu/usr.bin/gcc/function.c
index e45eec64e06..05332fe1dae 100644
--- a/gnu/usr.bin/gcc/function.c
+++ b/gnu/usr.bin/gcc/function.c
@@ -1,5 +1,5 @@
/* Expands front end tree to back end RTL for GNU C-Compiler
- Copyright (C) 1987, 88, 89, 91-94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 91-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -39,12 +39,11 @@ Boston, MA 02111-1307, USA. */
then scans all the RTL instructions so far generated to correct them. */
#include "config.h"
-
#include <stdio.h>
-
#include "rtl.h"
#include "tree.h"
#include "flags.h"
+#include "except.h"
#include "function.h"
#include "insn-flags.h"
#include "expr.h"
@@ -57,11 +56,16 @@ Boston, MA 02111-1307, USA. */
#include "basic-block.h"
#include "obstack.h"
#include "bytecode.h"
+#include "bc-emit.h"
+
+#ifndef TRAMPOLINE_ALIGNMENT
+#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
+#endif
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
- must define both, or neither. */
+ must define both, or neither. */
#ifndef NAME__MAIN
#define NAME__MAIN "__main"
#define SYMBOL__MAIN __main
@@ -128,6 +132,11 @@ int current_function_has_nonlocal_goto;
int current_function_contains_functions;
+/* Nonzero if the current function is a thunk (a lightweight function that
+ just adjusts one of its arguments and forwards to another function), so
+ we should try to cut corners where we can. */
+int current_function_is_thunk;
+
/* Nonzero if function being compiled can call alloca,
either as a subroutine or builtin. */
@@ -154,7 +163,7 @@ int current_function_args_size;
int current_function_pretend_args_size;
/* # of bytes of outgoing arguments. If ACCUMULATE_OUTGOING_ARGS is
- defined, the needed space is pushed by the prologue. */
+ defined, the needed space is pushed by the prologue. */
int current_function_outgoing_args_size;
@@ -182,10 +191,10 @@ CUMULATIVE_ARGS current_function_args_info;
char *current_function_name;
-/* If non-zero, an RTL expression for that location at which the current
- function returns its result. Always equal to
- DECL_RTL (DECL_RESULT (current_function_decl)), but provided
- independently of the tree structures. */
+/* If non-zero, an RTL expression for the location at which the current
+ function returns its result. If the current function returns its
+ result in a register, current_function_return_rtx will always be
+ the hard register containing the result. */
rtx current_function_return_rtx;
@@ -263,7 +272,7 @@ rtx arg_pointer_save_area;
/* Offset to end of allocated area of stack frame.
If stack grows down, this is the address of the last stack slot allocated.
If stack grows up, this is the address for the next slot. */
-int frame_offset;
+HOST_WIDE_INT frame_offset;
/* List (chain of TREE_LISTs) of static chains for containing functions.
Each link has a FUNCTION_DECL in the TREE_PURPOSE and a reg rtx
@@ -291,21 +300,15 @@ static int invalid_stack_slot;
/* Last insn of those whose job was to put parms into their nominal homes. */
static rtx last_parm_insn;
-/* 1 + last pseudo register number used for loading a copy
- of a parameter of this function. */
-static int max_parm_reg;
+/* 1 + last pseudo register number possibly used for loading a copy
+ of a parameter of this function. */
+int max_parm_reg;
/* Vector indexed by REGNO, containing location on stack in which
to put the parm which is nominally in pseudo register REGNO,
- if we discover that that parm must go in the stack. */
-static rtx *parm_reg_stack_loc;
-
-#if 0 /* Turned off because 0 seems to work just as well. */
-/* Cleanup lists are required for binding levels regardless of whether
- that binding level has cleanups or not. This node serves as the
- cleanup list whenever an empty list is required. */
-static tree empty_cleanup_list;
-#endif
+ if we discover that that parm must go in the stack. The highest
+ element in this vector is one less than MAX_PARM_REG, above. */
+rtx *parm_reg_stack_loc;
/* Nonzero once virtual register instantiation has been done.
assign_stack_local uses frame_pointer_rtx when this is nonzero. */
@@ -314,8 +317,8 @@ static int virtuals_instantiated;
/* These variables hold pointers to functions to
save and restore machine-specific data,
in push_function_context and pop_function_context. */
-void (*save_machine_status) ();
-void (*restore_machine_status) ();
+void (*save_machine_status) PROTO((struct function *));
+void (*restore_machine_status) PROTO((struct function *));
/* Nonzero if we need to distinguish between the return value of this function
and the return value of a function called by this function. This helps
@@ -323,10 +326,6 @@ void (*restore_machine_status) ();
extern int rtx_equal_function_value_matters;
extern tree sequence_rtl_expr;
-extern tree bc_runtime_type_code ();
-extern rtx bc_build_calldesc ();
-extern char *bc_emit_trampoline ();
-extern char *bc_end_function ();
/* In order to evaluate some expressions, such as function calls returning
structures in memory, we need to temporarily allocate stack locations.
@@ -350,7 +349,7 @@ struct temp_slot
{
/* Points to next temporary slot. */
struct temp_slot *next;
- /* The rtx to used to reference the slot. */
+ /* The rtx to used to reference the slot. */
rtx slot;
/* The rtx used to represent the address if not the address of the
slot above. May be an EXPR_LIST if multiple addresses exist. */
@@ -425,7 +424,7 @@ struct fixup_replacement
static struct temp_slot *find_temp_slot_from_address PROTO((rtx));
static void put_reg_into_stack PROTO((struct function *, rtx, tree,
enum machine_mode, enum machine_mode,
- int));
+ int, int));
static void fixup_var_refs PROTO((rtx, enum machine_mode, int));
static struct fixup_replacement
*find_fixup_replacement PROTO((struct fixup_replacement **, rtx));
@@ -451,6 +450,8 @@ static tree blocks_nreverse PROTO((tree));
static int all_blocks PROTO((tree, tree *));
static int *record_insns PROTO((rtx));
static int contains PROTO((rtx, int *));
+static void put_addressof_into_stack PROTO((rtx));
+static void purge_addressof_1 PROTO((rtx *, rtx, int));
/* Pointer to chain of `struct function' for containing functions. */
struct function *outer_function_chain;
@@ -488,6 +489,7 @@ push_function_context_to (context)
p->pops_args = current_function_pops_args;
p->returns_struct = current_function_returns_struct;
p->returns_pcc_struct = current_function_returns_pcc_struct;
+ p->returns_pointer = current_function_returns_pointer;
p->needs_context = current_function_needs_context;
p->calls_setjmp = current_function_calls_setjmp;
p->calls_longjmp = current_function_calls_longjmp;
@@ -495,6 +497,7 @@ push_function_context_to (context)
p->has_nonlocal_label = current_function_has_nonlocal_label;
p->has_nonlocal_goto = current_function_has_nonlocal_goto;
p->contains_functions = current_function_contains_functions;
+ p->is_thunk = current_function_is_thunk;
p->args_size = current_function_args_size;
p->pretend_args_size = current_function_pretend_args_size;
p->arg_offset_rtx = current_function_arg_offset_rtx;
@@ -528,6 +531,7 @@ push_function_context_to (context)
p->temp_slot_level = temp_slot_level;
p->fixup_var_refs_queue = 0;
p->epilogue_delay_list = current_function_epilogue_delay_list;
+ p->args_info = current_function_args_info;
save_tree_status (p, context);
save_storage_status (p);
@@ -535,7 +539,7 @@ push_function_context_to (context)
init_emit ();
save_expr_status (p);
save_stmt_status (p);
- save_varasm_status (p);
+ save_varasm_status (p, context);
if (save_machine_status)
(*save_machine_status) (p);
@@ -566,12 +570,14 @@ pop_function_context_from (context)
current_function_pops_args = p->pops_args;
current_function_returns_struct = p->returns_struct;
current_function_returns_pcc_struct = p->returns_pcc_struct;
+ current_function_returns_pointer = p->returns_pointer;
current_function_needs_context = p->needs_context;
current_function_calls_setjmp = p->calls_setjmp;
current_function_calls_longjmp = p->calls_longjmp;
current_function_calls_alloca = p->calls_alloca;
current_function_has_nonlocal_label = p->has_nonlocal_label;
current_function_has_nonlocal_goto = p->has_nonlocal_goto;
+ current_function_is_thunk = p->is_thunk;
current_function_args_size = p->args_size;
current_function_pretend_args_size = p->pretend_args_size;
current_function_arg_offset_rtx = p->arg_offset_rtx;
@@ -605,8 +611,9 @@ pop_function_context_from (context)
temp_slot_level = p->temp_slot_level;
current_function_epilogue_delay_list = p->epilogue_delay_list;
reg_renumber = 0;
+ current_function_args_info = p->args_info;
- restore_tree_status (p);
+ restore_tree_status (p, context);
restore_storage_status (p);
restore_expr_status (p);
restore_emit_status (p);
@@ -642,7 +649,7 @@ void pop_function_context ()
This size counts from zero. It is not rounded to STACK_BOUNDARY;
the caller may have to do that. */
-int
+HOST_WIDE_INT
get_frame_size ()
{
#ifdef FRAME_GROWS_DOWNWARD
@@ -916,9 +923,58 @@ assign_stack_temp (mode, size, keep)
p->level = temp_slot_level;
p->keep = keep;
}
+
+ /* We may be reusing an old slot, so clear any MEM flags that may have been
+ set from before. */
+ RTX_UNCHANGING_P (p->slot) = 0;
+ MEM_IN_STRUCT_P (p->slot) = 0;
return p->slot;
}
+
+/* Assign a temporary of given TYPE.
+ KEEP is as for assign_stack_temp.
+ MEMORY_REQUIRED is 1 if the result must be addressable stack memory;
+ it is 0 if a register is OK.
+ DONT_PROMOTE is 1 if we should not promote values in register
+ to wider modes. */
+
+rtx
+assign_temp (type, keep, memory_required, dont_promote)
+ tree type;
+ int keep;
+ int memory_required;
+ int dont_promote;
+{
+ enum machine_mode mode = TYPE_MODE (type);
+ int unsignedp = TREE_UNSIGNED (type);
+
+ if (mode == BLKmode || memory_required)
+ {
+ int size = int_size_in_bytes (type);
+ rtx tmp;
+
+ /* Unfortunately, we don't yet know how to allocate variable-sized
+ temporaries. However, sometimes we have a fixed upper limit on
+ the size (which is stored in TYPE_ARRAY_MAX_SIZE) and can use that
+ instead. This is the case for Chill variable-sized strings. */
+ if (size == -1 && TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_ARRAY_MAX_SIZE (type) != NULL_TREE
+ && TREE_CODE (TYPE_ARRAY_MAX_SIZE (type)) == INTEGER_CST)
+ size = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type));
+
+ tmp = assign_stack_temp (mode, size, keep);
+ MEM_IN_STRUCT_P (tmp) = AGGREGATE_TYPE_P (type);
+ return tmp;
+ }
+
+#ifndef PROMOTE_FOR_CALL_ONLY
+ if (! dont_promote)
+ mode = promote_mode (type, mode, &unsignedp, 0);
+#endif
+ return gen_reg_rtx (mode);
+}
+
/* Combine temporary stack slots which are adjacent on the stack.
This allows for better use of already allocated stack space. This is only
@@ -994,7 +1050,12 @@ find_temp_slot_from_address (x)
if (! p->in_use)
continue;
else if (XEXP (p->slot, 0) == x
- || p->address == x)
+ || p->address == x
+ || (GET_CODE (x) == PLUS
+ && XEXP (x, 0) == virtual_stack_vars_rtx
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) >= p->base_offset
+ && INTVAL (XEXP (x, 1)) < p->base_offset + p->full_size))
return p;
else if (p->address != 0 && GET_CODE (p->address) == EXPR_LIST)
@@ -1051,10 +1112,11 @@ mark_temp_addr_taken (x)
p->addr_taken = 1;
}
-/* If X could be a reference to a temporary slot, mark that slot as belonging
- to the to one level higher. If X matched one of our slots, just mark that
- one. Otherwise, we can't easily predict which it is, so upgrade all of
- them. Kept slots need not be touched.
+/* If X could be a reference to a temporary slot, mark that slot as
+ belonging to the to one level higher than the current level. If X
+ matched one of our slots, just mark that one. Otherwise, we can't
+ easily predict which it is, so upgrade all of them. Kept slots
+ need not be touched.
This is called when an ({...}) construct occurs and a statement
returns a value in memory. */
@@ -1105,12 +1167,15 @@ preserve_temp_slots (x)
level in case we used its address. */
struct temp_slot *q;
- for (q = temp_slots; q; q = q->next)
- if (q != p && q->addr_taken && q->level == p->level)
- q->level--;
+ if (p->level == temp_slot_level)
+ {
+ for (q = temp_slots; q; q = q->next)
+ if (q != p && q->addr_taken && q->level == p->level)
+ q->level--;
- p->level--;
- p->addr_taken = 0;
+ p->level--;
+ p->addr_taken = 0;
+ }
return;
}
@@ -1183,6 +1248,21 @@ free_temps_for_rtl_expr (t)
combine_temp_slots ();
}
+/* Mark all temporaries ever allocated in this function as not suitable
+ for reuse until the current level is exited. */
+
+void
+mark_all_temps_used ()
+{
+ struct temp_slot *p;
+
+ for (p = temp_slots; p; p = p->next)
+ {
+ p->in_use = p->keep = 1;
+ p->level = MIN (p->level, temp_slot_level);
+ }
+}
+
/* Push deeper into the nesting level for stack temporaries. */
void
@@ -1207,6 +1287,17 @@ pop_temp_slots ()
temp_slot_level--;
}
+
+/* Initialize temporary slots. */
+
+void
+init_temp_slots ()
+{
+ /* We have not allocated any temporaries yet. */
+ temp_slots = 0;
+ temp_slot_level = 0;
+ target_temp_slot_level = 0;
+}
/* Retroactively move an auto variable from a register to a stack slot.
This is done when an address-reference to the variable is seen. */
@@ -1219,6 +1310,7 @@ put_var_into_stack (decl)
enum machine_mode promoted_mode, decl_mode;
struct function *function = 0;
tree context;
+ int can_use_addressof;
if (output_bytecode)
return;
@@ -1242,7 +1334,7 @@ put_var_into_stack (decl)
/* If this variable comes from an outer function,
find that function's saved context. */
- if (context != current_function_decl)
+ if (context != current_function_decl && context != inline_function_decl)
for (function = outer_function_chain; function; function = function->next)
if (function->decl == context)
break;
@@ -1258,11 +1350,35 @@ put_var_into_stack (decl)
decl_mode = promoted_mode = GET_MODE (reg);
}
+ can_use_addressof
+ = (function == 0
+ /* FIXME make it work for promoted modes too */
+ && decl_mode == promoted_mode
+#ifdef NON_SAVING_SETJMP
+ && ! (NON_SAVING_SETJMP && current_function_calls_setjmp)
+#endif
+ );
+
+ /* If we can't use ADDRESSOF, make sure we see through one we already
+ generated. */
+ if (! can_use_addressof && GET_CODE (reg) == MEM
+ && GET_CODE (XEXP (reg, 0)) == ADDRESSOF)
+ reg = XEXP (XEXP (reg, 0), 0);
+
/* Now we should have a value that resides in one or more pseudo regs. */
if (GET_CODE (reg) == REG)
- put_reg_into_stack (function, reg, TREE_TYPE (decl),
- promoted_mode, decl_mode, TREE_SIDE_EFFECTS (decl));
+ {
+ /* If this variable lives in the current function and we don't need
+ to put things in the stack for the sake of setjmp, try to keep it
+ in a register until we know we actually need the address. */
+ if (can_use_addressof)
+ gen_mem_addressof (reg, decl);
+ else
+ put_reg_into_stack (function, reg, TREE_TYPE (decl),
+ promoted_mode, decl_mode,
+ TREE_SIDE_EFFECTS (decl), 0);
+ }
else if (GET_CODE (reg) == CONCAT)
{
/* A CONCAT contains two pseudos; put them both in the stack.
@@ -1272,14 +1388,14 @@ put_var_into_stack (decl)
#ifdef FRAME_GROWS_DOWNWARD
/* Since part 0 should have a lower address, do it second. */
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
- part_mode, TREE_SIDE_EFFECTS (decl));
+ part_mode, TREE_SIDE_EFFECTS (decl), 0);
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
- part_mode, TREE_SIDE_EFFECTS (decl));
+ part_mode, TREE_SIDE_EFFECTS (decl), 0);
#else
put_reg_into_stack (function, XEXP (reg, 0), part_type, part_mode,
- part_mode, TREE_SIDE_EFFECTS (decl));
+ part_mode, TREE_SIDE_EFFECTS (decl), 0);
put_reg_into_stack (function, XEXP (reg, 1), part_type, part_mode,
- part_mode, TREE_SIDE_EFFECTS (decl));
+ part_mode, TREE_SIDE_EFFECTS (decl), 0);
#endif
/* Change the CONCAT into a combined MEM for both parts. */
@@ -1293,6 +1409,16 @@ put_var_into_stack (decl)
if (GET_CODE (XEXP (reg, 0)) == PLUS)
XEXP (reg, 0) = copy_rtx (XEXP (reg, 0));
}
+ else
+ return;
+
+ if (flag_check_memory_usage)
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ XEXP (reg, 0), ptr_mode,
+ GEN_INT (GET_MODE_SIZE (GET_MODE (reg))),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
}
/* Subroutine of put_var_into_stack. This puts a single pseudo reg REG
@@ -1302,27 +1428,33 @@ put_var_into_stack (decl)
VOLATILE_P is nonzero if this is for a "volatile" decl. */
static void
-put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p)
+put_reg_into_stack (function, reg, type, promoted_mode, decl_mode, volatile_p,
+ original_regno)
struct function *function;
rtx reg;
tree type;
enum machine_mode promoted_mode, decl_mode;
int volatile_p;
+ int original_regno;
{
rtx new = 0;
+ int regno = original_regno;
+
+ if (regno == 0)
+ regno = REGNO (reg);
if (function)
{
- if (REGNO (reg) < function->max_parm_reg)
- new = function->parm_reg_stack_loc[REGNO (reg)];
+ if (regno < function->max_parm_reg)
+ new = function->parm_reg_stack_loc[regno];
if (new == 0)
new = assign_outer_stack_local (decl_mode, GET_MODE_SIZE (decl_mode),
0, function);
}
else
{
- if (REGNO (reg) < max_parm_reg)
- new = parm_reg_stack_loc[REGNO (reg)];
+ if (regno < max_parm_reg)
+ new = parm_reg_stack_loc[regno];
if (new == 0)
new = assign_stack_local (decl_mode, GET_MODE_SIZE (decl_mode), 0);
}
@@ -1404,7 +1536,7 @@ fixup_var_refs (var, promoted_mode, unsignedp)
/* REPLACEMENTS is a pointer to a list of the struct fixup_replacement and X is
some part of an insn. Return a struct fixup_replacement whose OLD
- value is equal to X. Allocate a new structure if no such entry exists. */
+ value is equal to X. Allocate a new structure if no such entry exists. */
static struct fixup_replacement *
find_fixup_replacement (replacements, x)
@@ -1494,42 +1626,43 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
struct fixup_replacement *replacements = 0;
rtx next_insn = NEXT_INSN (insn);
-#ifdef SMALL_REGISTER_CLASSES
- /* If the insn that copies the results of a CALL_INSN
- into a pseudo now references VAR, we have to use an
- intermediate pseudo since we want the life of the
- return value register to be only a single insn.
-
- If we don't use an intermediate pseudo, such things as
- address computations to make the address of VAR valid
- if it is not can be placed between the CALL_INSN and INSN.
-
- To make sure this doesn't happen, we record the destination
- of the CALL_INSN and see if the next insn uses both that
- and VAR. */
-
- if (call_dest != 0 && GET_CODE (insn) == INSN
- && reg_mentioned_p (var, PATTERN (insn))
- && reg_mentioned_p (call_dest, PATTERN (insn)))
+ if (SMALL_REGISTER_CLASSES)
{
- rtx temp = gen_reg_rtx (GET_MODE (call_dest));
+ /* If the insn that copies the results of a CALL_INSN
+ into a pseudo now references VAR, we have to use an
+ intermediate pseudo since we want the life of the
+ return value register to be only a single insn.
+
+ If we don't use an intermediate pseudo, such things as
+ address computations to make the address of VAR valid
+ if it is not can be placed between the CALL_INSN and INSN.
+
+ To make sure this doesn't happen, we record the destination
+ of the CALL_INSN and see if the next insn uses both that
+ and VAR. */
+
+ if (call_dest != 0 && GET_CODE (insn) == INSN
+ && reg_mentioned_p (var, PATTERN (insn))
+ && reg_mentioned_p (call_dest, PATTERN (insn)))
+ {
+ rtx temp = gen_reg_rtx (GET_MODE (call_dest));
- emit_insn_before (gen_move_insn (temp, call_dest), insn);
+ emit_insn_before (gen_move_insn (temp, call_dest), insn);
- PATTERN (insn) = replace_rtx (PATTERN (insn),
- call_dest, temp);
- }
+ PATTERN (insn) = replace_rtx (PATTERN (insn),
+ call_dest, temp);
+ }
- if (GET_CODE (insn) == CALL_INSN
- && GET_CODE (PATTERN (insn)) == SET)
- call_dest = SET_DEST (PATTERN (insn));
- else if (GET_CODE (insn) == CALL_INSN
- && GET_CODE (PATTERN (insn)) == PARALLEL
- && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
- call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
- else
- call_dest = 0;
-#endif
+ if (GET_CODE (insn) == CALL_INSN
+ && GET_CODE (PATTERN (insn)) == SET)
+ call_dest = SET_DEST (PATTERN (insn));
+ else if (GET_CODE (insn) == CALL_INSN
+ && GET_CODE (PATTERN (insn)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
+ call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
+ else
+ call_dest = 0;
+ }
/* See if we have to do anything to INSN now that VAR is in
memory. If it needs to be loaded into a pseudo, use a single
@@ -1632,6 +1765,27 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
switch (code)
{
+ case ADDRESSOF:
+ if (XEXP (x, 0) == var)
+ {
+ /* Prevent sharing of rtl that might lose. */
+ rtx sub = copy_rtx (XEXP (var, 0));
+
+ start_sequence ();
+
+ if (! validate_change (insn, loc, sub, 0))
+ {
+ rtx y = force_operand (sub, NULL_RTX);
+
+ if (! validate_change (insn, loc, y, 0))
+ *loc = copy_to_reg (y);
+ }
+
+ emit_insn_before (gen_sequence (), insn);
+ end_sequence ();
+ }
+ return;
+
case MEM:
if (var == x)
{
@@ -1699,8 +1853,20 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
tem = XEXP (x, 0);
if (GET_CODE (tem) == SUBREG)
- tem = fixup_memory_subreg (tem, insn, 1);
- tem = fixup_stack_1 (tem, insn);
+ {
+ if (GET_MODE_BITSIZE (GET_MODE (tem))
+ > GET_MODE_BITSIZE (GET_MODE (var)))
+ {
+ replacement = find_fixup_replacement (replacements, var);
+ if (replacement->new == 0)
+ replacement->new = gen_reg_rtx (GET_MODE (var));
+ SUBREG_REG (tem) = replacement->new;
+ }
+ else
+ tem = fixup_memory_subreg (tem, insn, 0);
+ }
+ else
+ tem = fixup_stack_1 (tem, insn);
/* Unless we want to load from memory, get TEM into the proper mode
for an extract from memory. This can only be done if the
@@ -1829,8 +1995,24 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
|| GET_CODE (SET_SRC (x)) == ZERO_EXTRACT)
optimize_bit_field (x, insn, NULL_PTR);
+ /* For a paradoxical SUBREG inside a ZERO_EXTRACT, load the object
+ into a register and then store it back out. */
+ if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
+ && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG
+ && SUBREG_REG (XEXP (SET_DEST (x), 0)) == var
+ && (GET_MODE_SIZE (GET_MODE (XEXP (SET_DEST (x), 0)))
+ > GET_MODE_SIZE (GET_MODE (var))))
+ {
+ replacement = find_fixup_replacement (replacements, var);
+ if (replacement->new == 0)
+ replacement->new = gen_reg_rtx (GET_MODE (var));
+
+ SUBREG_REG (XEXP (SET_DEST (x), 0)) = replacement->new;
+ emit_insn_after (gen_move_insn (var, replacement->new), insn);
+ }
+
/* If SET_DEST is now a paradoxical SUBREG, put the result of this
- insn into a pseudo and store the low part of the pseudo into VAR. */
+ insn into a pseudo and store the low part of the pseudo into VAR. */
if (GET_CODE (SET_DEST (x)) == SUBREG
&& SUBREG_REG (SET_DEST (x)) == var
&& (GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
@@ -1884,7 +2066,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
This was legitimate when the MEM was a REG. */
if (GET_CODE (tem) == SUBREG
&& SUBREG_REG (tem) == var)
- tem = fixup_memory_subreg (tem, insn, 1);
+ tem = fixup_memory_subreg (tem, insn, 0);
else
tem = fixup_stack_1 (tem, insn);
@@ -1968,7 +2150,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
&& (GET_CODE (SET_DEST (x)) == REG
|| (GET_CODE (SET_DEST (x)) == SUBREG
&& GET_CODE (SUBREG_REG (SET_DEST (x))) == REG))
- && x == single_set (PATTERN (insn)))
+ && GET_MODE (var) == promoted_mode
+ && x == single_set (insn))
{
rtx pat;
@@ -2013,7 +2196,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
&& (GET_CODE (SET_SRC (x)) == REG
|| (GET_CODE (SET_SRC (x)) == SUBREG
&& GET_CODE (SUBREG_REG (SET_SRC (x))) == REG))
- && x == single_set (PATTERN (insn)))
+ && GET_MODE (var) == promoted_mode
+ && x == single_set (insn))
{
rtx pat;
@@ -2076,6 +2260,9 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
SET_DEST (x) = temp;
}
}
+
+ default:
+ break;
}
/* Nothing special about this RTX; fix its operands. */
@@ -2100,7 +2287,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements)
If any insns must be emitted to compute NEWADDR, put them before INSN.
UNCRITICAL nonzero means accept paradoxical subregs.
- This is used for subregs found inside of ZERO_EXTRACTs and in REG_NOTES. */
+ This is used for subregs found inside REG_NOTES. */
static rtx
fixup_memory_subreg (x, insn, uncritical)
@@ -2201,6 +2388,12 @@ fixup_stack_1 (x, insn)
&& GET_CODE (XEXP (ad, 0)) == REG
&& ((REGNO (XEXP (ad, 0)) >= FIRST_VIRTUAL_REGISTER
&& REGNO (XEXP (ad, 0)) <= LAST_VIRTUAL_REGISTER)
+ || REGNO (XEXP (ad, 0)) == FRAME_POINTER_REGNUM
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+ || REGNO (XEXP (ad, 0)) == HARD_FRAME_POINTER_REGNUM
+#endif
+ || REGNO (XEXP (ad, 0)) == STACK_POINTER_REGNUM
+ || REGNO (XEXP (ad, 0)) == ARG_POINTER_REGNUM
|| XEXP (ad, 0) == current_function_internal_arg_pointer)
&& GET_CODE (XEXP (ad, 1)) == CONST_INT)
{
@@ -2441,6 +2634,163 @@ static int out_arg_offset;
#endif
#endif
+/* Build up a (MEM (ADDRESSOF (REG))) rtx for a register REG that just had
+ its address taken. DECL is the decl for the object stored in the
+ register, for later use if we do need to force REG into the stack.
+ REG is overwritten by the MEM like in put_reg_into_stack. */
+
+rtx
+gen_mem_addressof (reg, decl)
+ rtx reg;
+ tree decl;
+{
+ tree type = TREE_TYPE (decl);
+
+ rtx r = gen_rtx (ADDRESSOF, Pmode, gen_reg_rtx (GET_MODE (reg)));
+ ADDRESSOF_REGNO (r) = REGNO (reg);
+ SET_ADDRESSOF_DECL (r, decl);
+
+ XEXP (reg, 0) = r;
+ PUT_CODE (reg, MEM);
+ PUT_MODE (reg, DECL_MODE (decl));
+ MEM_VOLATILE_P (reg) = TREE_SIDE_EFFECTS (decl);
+ MEM_IN_STRUCT_P (reg) = AGGREGATE_TYPE_P (type);
+
+ fixup_var_refs (reg, GET_MODE (reg), TREE_UNSIGNED (type));
+ return reg;
+}
+
+/* If DECL has an RTL that is an ADDRESSOF rtx, put it into the stack. */
+
+void
+flush_addressof (decl)
+ tree decl;
+{
+ if ((TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == VAR_DECL)
+ && DECL_RTL (decl) != 0
+ && GET_CODE (DECL_RTL (decl)) == MEM
+ && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF
+ && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == REG)
+ put_addressof_into_stack (XEXP (DECL_RTL (decl), 0));
+}
+
+/* Force the register pointed to by R, an ADDRESSOF rtx, into the stack. */
+
+static void
+put_addressof_into_stack (r)
+ rtx r;
+{
+ tree decl = ADDRESSOF_DECL (r);
+ rtx reg = XEXP (r, 0);
+
+ if (GET_CODE (reg) != REG)
+ abort ();
+
+ put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg),
+ DECL_MODE (decl), TREE_SIDE_EFFECTS (decl),
+ ADDRESSOF_REGNO (r));
+}
+
+/* Helper function for purge_addressof. See if the rtx expression at *LOC
+ in INSN needs to be changed. If FORCE, always put any ADDRESSOFs into
+ the stack. */
+
+static void
+purge_addressof_1 (loc, insn, force)
+ rtx *loc;
+ rtx insn;
+ int force;
+{
+ rtx x;
+ RTX_CODE code;
+ int i, j;
+ char *fmt;
+
+ /* Re-start here to avoid recursion in common cases. */
+ restart:
+
+ x = *loc;
+ if (x == 0)
+ return;
+
+ code = GET_CODE (x);
+
+ if (code == ADDRESSOF && GET_CODE (XEXP (x, 0)) == MEM)
+ {
+ rtx insns;
+ /* We must create a copy of the rtx because it was created by
+ overwriting a REG rtx which is always shared. */
+ rtx sub = copy_rtx (XEXP (XEXP (x, 0), 0));
+
+ if (validate_change (insn, loc, sub, 0))
+ return;
+
+ start_sequence ();
+ if (! validate_change (insn, loc,
+ force_operand (sub, NULL_RTX),
+ 0))
+ abort ();
+
+ insns = get_insns ();
+ end_sequence ();
+ emit_insns_before (insns, insn);
+ return;
+ }
+ else if (code == MEM && GET_CODE (XEXP (x, 0)) == ADDRESSOF && ! force)
+ {
+ rtx sub = XEXP (XEXP (x, 0), 0);
+ if (GET_CODE (sub) == MEM)
+ sub = gen_rtx (MEM, GET_MODE (x), copy_rtx (XEXP (sub, 0)));
+ if (GET_CODE (sub) == REG && GET_MODE (x) != GET_MODE (sub))
+ {
+ if (! BYTES_BIG_ENDIAN && ! WORDS_BIG_ENDIAN)
+ {
+ rtx sub2 = gen_rtx (SUBREG, GET_MODE (x), sub, 0);
+ if (validate_change (insn, loc, sub2, 0))
+ goto restart;
+ }
+ }
+ else if (validate_change (insn, loc, sub, 0))
+ goto restart;
+ /* else give up and put it into the stack */
+ }
+ else if (code == ADDRESSOF)
+ {
+ put_addressof_into_stack (x);
+ return;
+ }
+
+ /* Scan all subexpressions. */
+ fmt = GET_RTX_FORMAT (code);
+ for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
+ {
+ if (*fmt == 'e')
+ purge_addressof_1 (&XEXP (x, i), insn, force);
+ else if (*fmt == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ purge_addressof_1 (&XVECEXP (x, i, j), insn, force);
+ }
+}
+
+/* Eliminate all occurrences of ADDRESSOF from INSNS. Elide any remaining
+ (MEM (ADDRESSOF)) patterns, and force any needed registers into the
+ stack. */
+
+void
+purge_addressof (insns)
+ rtx insns;
+{
+ rtx insn;
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
+ || GET_CODE (insn) == CALL_INSN)
+ {
+ purge_addressof_1 (&PATTERN (insn), insn,
+ asm_noperands (PATTERN (insn)) > 0);
+ purge_addressof_1 (&REG_NOTES (insn), NULL_RTX, 0);
+ }
+}
+
/* Pass through the INSNS of function FNDECL and convert virtual register
references to hard register references. */
@@ -2450,6 +2800,7 @@ instantiate_virtual_regs (fndecl, insns)
rtx insns;
{
rtx insn;
+ int i;
/* Compute the offsets to use for this function. */
in_arg_offset = FIRST_PARM_OFFSET (fndecl);
@@ -2476,6 +2827,12 @@ instantiate_virtual_regs (fndecl, insns)
instantiate_virtual_regs_1 (&REG_NOTES (insn), NULL_RTX, 0);
}
+ /* Instantiate the stack slots for the parm registers, for later use in
+ addressof elimination. */
+ for (i = 0; i < max_parm_reg; ++i)
+ if (parm_reg_stack_loc[i])
+ instantiate_virtual_regs_1 (&parm_reg_stack_loc[i], NULL_RTX, 0);
+
/* Now instantiate the remaining register equivalences for debugging info.
These will not be valid addresses. */
instantiate_decls (fndecl, 0);
@@ -2498,7 +2855,7 @@ instantiate_decls (fndecl, valid_only)
{
tree decl;
- if (DECL_INLINE (fndecl) || DECL_DEFER_OUTPUT (fndecl))
+ if (DECL_SAVED_INSNS (fndecl))
/* When compiling an inline function, the obstack used for
rtl allocation is the maybepermanent_obstack. Calling
`resume_temporary_allocation' switches us back to that
@@ -2508,13 +2865,17 @@ instantiate_decls (fndecl, valid_only)
/* Process all parameters of the function. */
for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
{
- instantiate_decl (DECL_RTL (decl), int_size_in_bytes (TREE_TYPE (decl)),
- valid_only);
- instantiate_decl (DECL_INCOMING_RTL (decl),
- int_size_in_bytes (TREE_TYPE (decl)), valid_only);
+ int size = int_size_in_bytes (TREE_TYPE (decl));
+ instantiate_decl (DECL_RTL (decl), size, valid_only);
+
+ /* If the parameter was promoted, then the incoming RTL mode may be
+ larger than the declared type size. We must use the larger of
+ the two sizes. */
+ size = MAX (GET_MODE_SIZE (GET_MODE (DECL_INCOMING_RTL (decl))), size);
+ instantiate_decl (DECL_INCOMING_RTL (decl), size, valid_only);
}
- /* Now process all variables defined in the function or its subblocks. */
+ /* Now process all variables defined in the function or its subblocks. */
instantiate_decls_1 (DECL_INITIAL (fndecl), valid_only);
if (DECL_INLINE (fndecl) || DECL_DEFER_OUTPUT (fndecl))
@@ -2569,6 +2930,7 @@ instantiate_decl (x, size, valid_only)
addr = XEXP (x, 0);
if (CONSTANT_P (addr)
+ || (GET_CODE (addr) == ADDRESSOF && GET_CODE (XEXP (addr, 0)) == REG)
|| (GET_CODE (addr) == REG
&& (REGNO (addr) < FIRST_VIRTUAL_REGISTER
|| REGNO (addr) > LAST_VIRTUAL_REGISTER)))
@@ -2584,28 +2946,28 @@ instantiate_decl (x, size, valid_only)
instantiate_virtual_regs_1 (&addr, NULL_RTX, 0);
- if (! valid_only)
- return;
-
- /* Now verify that the resulting address is valid for every integer or
- floating-point mode up to and including SIZE bytes long. We do this
- since the object might be accessed in any mode and frame addresses
- are shared. */
-
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
- mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
- mode = GET_MODE_WIDER_MODE (mode))
- if (! memory_address_p (mode, addr))
- return;
+ if (valid_only)
+ {
+ /* Now verify that the resulting address is valid for every integer or
+ floating-point mode up to and including SIZE bytes long. We do this
+ since the object might be accessed in any mode and frame addresses
+ are shared. */
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (! memory_address_p (mode, addr))
+ return;
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
- mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
- mode = GET_MODE_WIDER_MODE (mode))
- if (! memory_address_p (mode, addr))
- return;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+ mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (! memory_address_p (mode, addr))
+ return;
+ }
- /* Otherwise, put back the address, now that we have updated it and we
- know it is valid. */
+ /* Put back the address now that we have updated it and we either know
+ it is valid or we don't care whether it is valid. */
XEXP (x, 0) = addr;
}
@@ -2698,7 +3060,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
emit_insns_before (seq, object);
SET_DEST (x) = new;
- if (!validate_change (object, &SET_SRC (x), temp, 0)
+ if (! validate_change (object, &SET_SRC (x), temp, 0)
|| ! extra_insns)
abort ();
@@ -2773,7 +3135,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
in the case of old offset equals new just changing the register
will yield a valid insn. In the interests of a little efficiency,
however, we only call validate change once (we don't queue up the
- changes and then call apply_change_group). */
+ changes and then call apply_change_group). */
old = XEXP (x, 0);
if (offset == 0
@@ -2837,7 +3199,7 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
case MEM:
/* Most cases of MEM that convert to valid addresses have already been
- handled by our scan of regno_reg_rtx. The only special handling we
+ handled by our scan of decls. The only special handling we
need here is to make a copy of the rtx to ensure it isn't being
shared if we have to change it to a pseudo.
@@ -2895,7 +3257,9 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
??? Also note that this can still lose if OBJECT is an insn that
has less restrictions on an address that some other insn.
In that case, we will modify the shared address. This case
- doesn't seem very likely, though. */
+ doesn't seem very likely, though. One case where this could
+ happen is in the case of a USE or CLOBBER reference, but we
+ take care of that below. */
if (instantiate_virtual_regs_1 (&XEXP (x, 0),
object ? object : x, 0))
@@ -2908,8 +3272,6 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
}
/* Fall through to generic unary operation case. */
- case USE:
- case CLOBBER:
case SUBREG:
case STRICT_LOW_PART:
case NEG: case NOT:
@@ -2926,6 +3288,23 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
loc = &XEXP (x, 0);
goto restart;
+ case USE:
+ case CLOBBER:
+ /* If the operand is a MEM, see if the change is a valid MEM. If not,
+ go ahead and make the invalid one, but do it to a copy. For a REG,
+ just make the recursive call, since there's no chance of a problem. */
+
+ if ((GET_CODE (XEXP (x, 0)) == MEM
+ && instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 0), XEXP (x, 0),
+ 0))
+ || (GET_CODE (XEXP (x, 0)) == REG
+ && instantiate_virtual_regs_1 (&XEXP (x, 0), object, 0)))
+ return 1;
+
+ XEXP (x, 0) = copy_rtx (XEXP (x, 0));
+ loc = &XEXP (x, 0);
+ goto restart;
+
case REG:
/* Try to replace with a PLUS. If that doesn't work, compute the sum
in front of this insn and substitute the temporary. */
@@ -2959,6 +3338,23 @@ instantiate_virtual_regs_1 (loc, object, extra_insns)
}
return 1;
+
+ case ADDRESSOF:
+ if (GET_CODE (XEXP (x, 0)) == REG)
+ return 1;
+
+ else if (GET_CODE (XEXP (x, 0)) == MEM)
+ {
+ /* If we have a (addressof (mem ..)), do any instantiation inside
+ since we know we'll be making the inside valid when we finally
+ remove the ADDRESSOF. */
+ instantiate_virtual_regs_1 (&XEXP (XEXP (x, 0), 0), NULL_RTX, 0);
+ return 1;
+ }
+ break;
+
+ default:
+ break;
}
/* Scan all subexpressions. */
@@ -3129,11 +3525,21 @@ aggregate_value_p (exp)
if (RETURN_IN_MEMORY (type))
return 1;
+ /* Types that are TREE_ADDRESSABLE must be constructed in memory,
+ and thus can't be returned in registers. */
+ if (TREE_ADDRESSABLE (type))
+ return 1;
if (flag_pcc_struct_return && AGGREGATE_TYPE_P (type))
return 1;
/* Make sure we have suitable call-clobbered regs to return
the value in; if not, we must return it in memory. */
reg = hard_function_value (type, 0);
+
+ /* If we have something other than a REG (e.g. a PARALLEL), then assume
+ it is OK. */
+ if (GET_CODE (reg) != REG)
+ return 0;
+
regno = REGNO (reg);
nregs = HARD_REGNO_NREGS (regno, TYPE_MODE (type));
for (i = 0; i < nregs; i++)
@@ -3175,12 +3581,8 @@ assign_parms (fndecl, second_time)
/* This is a dummy PARM_DECL that we used for the function result if
the function returns a structure. */
tree function_result_decl = 0;
- int nparmregs = list_length (fnargs) + LAST_VIRTUAL_REGISTER + 1;
int varargs_setup = 0;
rtx conversion_insns = 0;
- /* FUNCTION_ARG may look at this variable. Since this is not
- expanding a call it will always be zero in this function. */
- int current_call_is_indirect = 0;
/* Nonzero if the last arg is named `__builtin_va_alist',
which is used on some machines for old-fashioned non-ANSI varargs.h;
@@ -3195,7 +3597,7 @@ assign_parms (fndecl, second_time)
/* Nonzero if function takes extra anonymous args.
This means the last named arg must be on the stack
- right before the anonymous ones. */
+ right before the anonymous ones. */
int stdarg
= (TYPE_ARG_TYPES (fntype) != 0
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
@@ -3227,7 +3629,7 @@ assign_parms (fndecl, second_time)
&& ! current_function_returns_pcc_struct
&& struct_value_incoming_rtx == 0)
{
- tree type = build_pointer_type (fntype);
+ tree type = build_pointer_type (TREE_TYPE (fntype));
function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
@@ -3236,13 +3638,14 @@ assign_parms (fndecl, second_time)
fnargs = function_result_decl;
}
- parm_reg_stack_loc = (rtx *) oballoc (nparmregs * sizeof (rtx));
- bzero ((char *) parm_reg_stack_loc, nparmregs * sizeof (rtx));
+ max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
+ parm_reg_stack_loc = (rtx *) savealloc (max_parm_reg * sizeof (rtx));
+ bzero ((char *) parm_reg_stack_loc, max_parm_reg * sizeof (rtx));
#ifdef INIT_CUMULATIVE_INCOMING_ARGS
INIT_CUMULATIVE_INCOMING_ARGS (args_so_far, fntype, NULL_RTX);
#else
- INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX);
+ INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0);
#endif
/* We haven't yet found an argument that we must push and pretend the
@@ -3403,8 +3806,10 @@ assign_parms (fndecl, second_time)
internal_arg_pointer, offset_rtx));
/* If this is a memory ref that contains aggregate components,
- mark it as such for cse and loop optimize. */
+ mark it as such for cse and loop optimize. Likewise if it
+ is readonly. */
MEM_IN_STRUCT_P (stack_parm) = aggregate;
+ RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
}
/* If this parameter was passed both in registers and in the stack,
@@ -3434,9 +3839,17 @@ assign_parms (fndecl, second_time)
* (PARM_BOUNDARY / BITS_PER_UNIT));
if (! second_time)
- move_block_from_reg (REGNO (entry_parm),
- validize_mem (stack_parm), nregs,
- int_size_in_bytes (TREE_TYPE (parm)));
+ {
+ /* Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+ if (GET_CODE (entry_parm) == PARALLEL)
+ emit_group_store (validize_mem (stack_parm),
+ entry_parm);
+ else
+ move_block_from_reg (REGNO (entry_parm),
+ validize_mem (stack_parm), nregs,
+ int_size_in_bytes (TREE_TYPE (parm)));
+ }
entry_parm = stack_parm;
}
}
@@ -3483,7 +3896,7 @@ assign_parms (fndecl, second_time)
FUNCTION_ARG_ADVANCE (args_so_far, promoted_mode,
passed_type, ! last_named);
- /* If this is our second time through, we are done with this parm. */
+ /* If this is our second time through, we are done with this parm. */
if (second_time)
continue;
@@ -3527,6 +3940,19 @@ assign_parms (fndecl, second_time)
else
stack_parm = gen_rtx (MEM, nominal_mode,
gen_rtx (PLUS, Pmode,
+ if (flag_check_memory_usage)
+ {
+ push_to_sequence (conversion_insns);
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ XEXP (stack_parm, 0), ptr_mode,
+ GEN_INT (int_size_in_bytes
+ (TREE_TYPE (parm))),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+ conversion_insns = get_insns ();
+ end_sequence ();
+ }
internal_arg_pointer, offset_rtx));
/* If this is a memory ref that contains aggregate components,
@@ -3560,10 +3986,13 @@ assign_parms (fndecl, second_time)
Set DECL_RTL to that place. */
- if (nominal_mode == BLKmode)
+ if (nominal_mode == BLKmode || GET_CODE (entry_parm) == PARALLEL)
{
- /* If a BLKmode arrives in registers, copy it to a stack slot. */
- if (GET_CODE (entry_parm) == REG)
+ /* If a BLKmode arrives in registers, copy it to a stack slot.
+ Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+ if (GET_CODE (entry_parm) == REG
+ || GET_CODE (entry_parm) == PARALLEL)
{
int size_stored
= CEIL_ROUND (int_size_in_bytes (TREE_TYPE (parm)),
@@ -3594,10 +4023,15 @@ assign_parms (fndecl, second_time)
if (TREE_READONLY (parm))
RTX_UNCHANGING_P (stack_parm) = 1;
- move_block_from_reg (REGNO (entry_parm),
- validize_mem (stack_parm),
- size_stored / UNITS_PER_WORD,
- int_size_in_bytes (TREE_TYPE (parm)));
+ /* Handle calls that pass values in multiple non-contiguous
+ locations. The Irix 6 ABI has examples of this. */
+ if (GET_CODE (entry_parm) == PARALLEL)
+ emit_group_store (validize_mem (stack_parm), entry_parm);
+ else
+ move_block_from_reg (REGNO (entry_parm),
+ validize_mem (stack_parm),
+ size_stored / UNITS_PER_WORD,
+ int_size_in_bytes (TREE_TYPE (parm)));
}
DECL_RTL (parm) = stack_parm;
}
@@ -3626,7 +4060,7 @@ assign_parms (fndecl, second_time)
= promote_mode (TREE_TYPE (parm), nominal_mode, &unsignedp, 0);
parmreg = gen_reg_rtx (promoted_nominal_mode);
- REG_USERVAR_P (parmreg) = 1;
+ mark_user_reg (parmreg);
/* If this was an item that we received a pointer to, set DECL_RTL
appropriately. */
@@ -3646,7 +4080,7 @@ assign_parms (fndecl, second_time)
/* ENTRY_PARM has been converted to PROMOTED_MODE, its
mode, by the caller. We now have to convert it to
NOMINAL_MODE, if different. However, PARMREG may be in
- a diffent mode than NOMINAL_MODE if it is being stored
+ a different mode than NOMINAL_MODE if it is being stored
promoted.
If ENTRY_PARM is a hard register, it might be in a register
@@ -3694,7 +4128,7 @@ assign_parms (fndecl, second_time)
/* We can't use nominal_mode, because it will have been set to
Pmode above. We must use the actual mode of the parm. */
parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
- REG_USERVAR_P (parmreg) = 1;
+ mark_user_reg (parmreg);
emit_move_insn (parmreg, DECL_RTL (parm));
DECL_RTL (parm) = parmreg;
/* STACK_PARM is the pointer, not the parm, and PARMREG is
@@ -3736,9 +4170,17 @@ assign_parms (fndecl, second_time)
copy = assign_stack_temp (TYPE_MODE (type),
int_size_in_bytes (type), 1);
MEM_IN_STRUCT_P (copy) = AGGREGATE_TYPE_P (type);
+ RTX_UNCHANGING_P (copy) = TREE_READONLY (parm);
store_expr (parm, copy, 0);
emit_move_insn (parmreg, XEXP (copy, 0));
+ if (flag_check_memory_usage)
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ XEXP (copy, 0), ptr_mode,
+ GEN_INT (int_size_in_bytes (type)),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
conversion_insns = get_insns ();
did_conversion = 1;
end_sequence ();
@@ -3756,17 +4198,20 @@ assign_parms (fndecl, second_time)
else
regno = REGNO (parmreg);
- if (regno >= nparmregs)
+ if (regno >= max_parm_reg)
{
rtx *new;
- int old_nparmregs = nparmregs;
+ int old_max_parm_reg = max_parm_reg;
- nparmregs = regno + 5;
- new = (rtx *) oballoc (nparmregs * sizeof (rtx));
+ /* It's slow to expand this one register at a time,
+ but it's also rare and we need max_parm_reg to be
+ precisely correct. */
+ max_parm_reg = regno + 1;
+ new = (rtx *) savealloc (max_parm_reg * sizeof (rtx));
bcopy ((char *) parm_reg_stack_loc, (char *) new,
- old_nparmregs * sizeof (rtx));
- bzero ((char *) (new + old_nparmregs),
- (nparmregs - old_nparmregs) * sizeof (rtx));
+ old_max_parm_reg * sizeof (rtx));
+ bzero ((char *) (new + old_max_parm_reg),
+ (max_parm_reg - old_max_parm_reg) * sizeof (rtx));
parm_reg_stack_loc = new;
}
@@ -3801,41 +4246,48 @@ assign_parms (fndecl, second_time)
as we make here would screw up life analysis for it. */
if (nominal_mode == passed_mode
&& ! did_conversion
- && GET_CODE (entry_parm) == MEM
- && entry_parm == stack_parm
+ && stack_parm != 0
+ && GET_CODE (stack_parm) == MEM
&& stack_offset.var == 0
&& reg_mentioned_p (virtual_incoming_args_rtx,
- XEXP (entry_parm, 0)))
+ XEXP (stack_parm, 0)))
{
rtx linsn = get_last_insn ();
+ rtx sinsn, set;
/* Mark complex types separately. */
if (GET_CODE (parmreg) == CONCAT)
- {
- REG_NOTES (linsn)
- = gen_rtx (EXPR_LIST, REG_EQUIV,
- parm_reg_stack_loc[regnoi], REG_NOTES (linsn));
-
- /* Now search backward for where we set the real part. */
- for (; linsn != 0
- && ! reg_referenced_p (parm_reg_stack_loc[regnor],
- PATTERN (linsn));
- linsn = prev_nonnote_insn (linsn))
- ;
-
- REG_NOTES (linsn)
- = gen_rtx (EXPR_LIST, REG_EQUIV,
- parm_reg_stack_loc[regnor], REG_NOTES (linsn));
- }
- else
+ /* Scan backwards for the set of the real and
+ imaginary parts. */
+ for (sinsn = linsn; sinsn != 0;
+ sinsn = prev_nonnote_insn (sinsn))
+ {
+ set = single_set (sinsn);
+ if (set != 0
+ && SET_DEST (set) == regno_reg_rtx [regnoi])
+ REG_NOTES (sinsn)
+ = gen_rtx (EXPR_LIST, REG_EQUIV,
+ parm_reg_stack_loc[regnoi],
+ REG_NOTES (sinsn));
+ else if (set != 0
+ && SET_DEST (set) == regno_reg_rtx [regnor])
+ REG_NOTES (sinsn)
+ = gen_rtx (EXPR_LIST, REG_EQUIV,
+ parm_reg_stack_loc[regnor],
+ REG_NOTES (sinsn));
+ }
+ else if ((set = single_set (linsn)) != 0
+ && SET_DEST (set) == parmreg)
REG_NOTES (linsn)
- = gen_rtx (EXPR_LIST, REG_EQUIV,
- entry_parm, REG_NOTES (linsn));
+ = gen_rtx (EXPR_LIST, REG_EQUIV,
+ stack_parm, REG_NOTES (linsn));
}
/* For pointer data type, suggest pointer register. */
if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
- mark_reg_pointer (parmreg);
+ mark_reg_pointer (parmreg,
+ (TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm)))
+ / BITS_PER_UNIT));
}
else
{
@@ -3881,7 +4333,22 @@ assign_parms (fndecl, second_time)
emit_move_insn (validize_mem (stack_parm),
validize_mem (entry_parm));
}
+ if (flag_check_memory_usage
+ && entry_parm != stack_parm
+ && promoted_mode != nominal_mode)
+ {
+ push_to_sequence (conversion_insns);
+ emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
+ XEXP (stack_parm, 0), ptr_mode,
+ GEN_INT (GET_MODE_SIZE (GET_MODE
+ (entry_parm))),
+ TYPE_MODE (sizetype),
+ GEN_INT (MEMORY_USE_RW),
+ TYPE_MODE (integer_type_node));
+ conversion_insns = get_insns ();
+ end_sequence ();
+ }
DECL_RTL (parm) = stack_parm;
}
@@ -3908,7 +4375,6 @@ assign_parms (fndecl, second_time)
now that all parameters have been copied out of hard registers. */
emit_insns (conversion_insns);
- max_parm_reg = max_reg_num ();
last_parm_insn = get_last_insn ();
current_function_args_size = stack_args_size.constant;
@@ -3936,7 +4402,7 @@ assign_parms (fndecl, second_time)
= (stack_args_size.var == 0 ? GEN_INT (-stack_args_size.constant)
: expand_expr (size_binop (MINUS_EXPR, stack_args_size.var,
size_int (-stack_args_size.constant)),
- NULL_RTX, VOIDmode, 0));
+ NULL_RTX, VOIDmode, EXPAND_MEMORY_USE_BAD));
#else
current_function_arg_offset_rtx = ARGS_SIZE_RTX (stack_args_size);
#endif
@@ -4105,8 +4571,8 @@ locate_and_pad_parm (passed_mode, type, in_regs, fndecl,
}
else
{
- arg_size_ptr->constant = (- initial_offset_ptr->constant -
- offset_ptr->constant);
+ arg_size_ptr->constant = (- initial_offset_ptr->constant
+ - offset_ptr->constant);
}
#else /* !ARGS_GROW_DOWNWARD */
pad_to_arg_alignment (initial_offset_ptr, boundary);
@@ -4267,7 +4733,9 @@ setjmp_protect (block)
if ((TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL)
&& DECL_RTL (decl) != 0
- && GET_CODE (DECL_RTL (decl)) == REG
+ && (GET_CODE (DECL_RTL (decl)) == REG
+ || (GET_CODE (DECL_RTL (decl)) == MEM
+ && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF))
/* If this variable came from an inline function, it must be
that it's life doesn't overlap the setjmp. If there was a
setjmp in the function, it would already be in memory. We
@@ -4298,7 +4766,9 @@ setjmp_protect_args ()
if ((TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL)
&& DECL_RTL (decl) != 0
- && GET_CODE (DECL_RTL (decl)) == REG
+ && (GET_CODE (DECL_RTL (decl)) == REG
+ || (GET_CODE (DECL_RTL (decl)) == MEM
+ && GET_CODE (XEXP (DECL_RTL (decl), 0)) == ADDRESSOF))
&& (
/* If longjmp doesn't restore the registers,
don't put anything in them. */
@@ -4320,9 +4790,10 @@ lookup_static_chain (decl)
tree context = decl_function_context (decl);
tree link;
- if (context == 0)
+ if (context == 0
+ || (TREE_CODE (decl) == FUNCTION_DECL && DECL_NO_STATIC_CHAIN (decl)))
return 0;
-
+
/* We treat inline_function_decl as an alias for the current function
because that is the inline function whose vars, types, etc.
are being merged into the current function.
@@ -4363,6 +4834,9 @@ fix_lexical_addr (addr, var)
if (fp == 0)
abort ();
+ if (GET_CODE (addr) == ADDRESSOF && GET_CODE (XEXP (addr, 0)) == MEM)
+ addr = XEXP (XEXP (addr, 0), 0);
+
/* Decode given address as base reg plus displacement. */
if (GET_CODE (addr) == REG)
basereg = addr, displacement = 0;
@@ -4457,7 +4931,8 @@ trampoline_address (function)
/* Find the `struct function' for the function containing FUNCTION. */
fp = 0;
fn_context = decl_function_context (function);
- if (fn_context != current_function_decl)
+ if (fn_context != current_function_decl
+ && fn_context != inline_function_decl)
for (fp = outer_function_chain; fp; fp = fp->next)
if (fp->decl == fn_context)
break;
@@ -4470,7 +4945,8 @@ trampoline_address (function)
/* If rounding needed, allocate extra space
to ensure we have TRAMPOLINE_SIZE bytes left after rounding up. */
#ifdef TRAMPOLINE_ALIGNMENT
-#define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE + TRAMPOLINE_ALIGNMENT - 1)
+#define TRAMPOLINE_REAL_SIZE \
+ (TRAMPOLINE_SIZE + (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT) - 1)
#else
#define TRAMPOLINE_REAL_SIZE (TRAMPOLINE_SIZE)
#endif
@@ -4518,10 +4994,10 @@ round_trampoline_addr (tramp)
/* Round address up to desired boundary. */
rtx temp = gen_reg_rtx (Pmode);
temp = expand_binop (Pmode, add_optab, tramp,
- GEN_INT (TRAMPOLINE_ALIGNMENT - 1),
+ GEN_INT (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT - 1),
temp, 0, OPTAB_LIB_WIDEN);
tramp = expand_binop (Pmode, and_optab, temp,
- GEN_INT (- TRAMPOLINE_ALIGNMENT),
+ GEN_INT (- TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT),
temp, 0, OPTAB_LIB_WIDEN);
#endif
return tramp;
@@ -4532,33 +5008,34 @@ round_trampoline_addr (tramp)
duplicate portions of the RTL code. Call identify_blocks before
changing the RTL, and call reorder_blocks after. */
-/* Put all this function's BLOCK nodes into a vector, and return it.
+/* Put all this function's BLOCK nodes including those that are chained
+ onto the first block into a vector, and return it.
Also store in each NOTE for the beginning or end of a block
the index of that block in the vector.
- The arguments are TOP_BLOCK, the top-level block of the function,
+ The arguments are BLOCK, the chain of top-level blocks of the function,
and INSNS, the insn chain of the function. */
tree *
-identify_blocks (top_block, insns)
- tree top_block;
+identify_blocks (block, insns)
+ tree block;
rtx insns;
{
int n_blocks;
tree *block_vector;
int *block_stack;
int depth = 0;
- int next_block_number = 0;
- int current_block_number = 0;
+ int next_block_number = 1;
+ int current_block_number = 1;
rtx insn;
- if (top_block == 0)
+ if (block == 0)
return 0;
- n_blocks = all_blocks (top_block, 0);
+ n_blocks = all_blocks (block, 0);
block_vector = (tree *) xmalloc (n_blocks * sizeof (tree));
block_stack = (int *) alloca (n_blocks * sizeof (int));
- all_blocks (top_block, block_vector);
+ all_blocks (block, block_vector);
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE)
@@ -4576,6 +5053,9 @@ identify_blocks (top_block, insns)
}
}
+ if (n_blocks != next_block_number)
+ abort ();
+
return block_vector;
}
@@ -4586,19 +5066,20 @@ identify_blocks (top_block, insns)
Returns the current top-level block. */
tree
-reorder_blocks (block_vector, top_block, insns)
+reorder_blocks (block_vector, block, insns)
tree *block_vector;
- tree top_block;
+ tree block;
rtx insns;
{
- tree current_block = top_block;
+ tree current_block = block;
rtx insn;
if (block_vector == 0)
- return top_block;
+ return block;
- /* Prune the old tree away, so that it doesn't get in the way. */
+ /* Prune the old trees away, so that it doesn't get in the way. */
BLOCK_SUBBLOCKS (current_block) = 0;
+ BLOCK_CHAIN (current_block) = 0;
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE)
@@ -4626,6 +5107,8 @@ reorder_blocks (block_vector, top_block, insns)
}
}
+ BLOCK_SUBBLOCKS (current_block)
+ = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
return current_block;
}
@@ -4646,31 +5129,37 @@ blocks_nreverse (t)
return prev;
}
-/* Count the subblocks of BLOCK, and list them all into the vector VECTOR.
- Also clear TREE_ASM_WRITTEN in all blocks. */
+/* Count the subblocks of the list starting with BLOCK, and list them
+ all into the vector VECTOR. Also clear TREE_ASM_WRITTEN in all
+ blocks. */
static int
all_blocks (block, vector)
tree block;
tree *vector;
{
- int n_blocks = 1;
- tree subblocks;
+ int n_blocks = 0;
+
+ while (block)
+ {
+ TREE_ASM_WRITTEN (block) = 0;
- TREE_ASM_WRITTEN (block) = 0;
- /* Record this block. */
- if (vector)
- vector[0] = block;
+ /* Record this block. */
+ if (vector)
+ vector[n_blocks] = block;
- /* Record the subblocks, and their subblocks. */
- for (subblocks = BLOCK_SUBBLOCKS (block);
- subblocks; subblocks = BLOCK_CHAIN (subblocks))
- n_blocks += all_blocks (subblocks, vector ? vector + n_blocks : 0);
+ ++n_blocks;
+
+ /* Record the subblocks, and their subblocks... */
+ n_blocks += all_blocks (BLOCK_SUBBLOCKS (block),
+ vector ? vector + n_blocks : 0);
+ block = BLOCK_CHAIN (block);
+ }
return n_blocks;
}
-/* Build bytecode call descriptor for function SUBR. */
+/* Build bytecode call descriptor for function SUBR. */
rtx
bc_build_calldesc (subr)
@@ -4724,8 +5213,6 @@ init_function_start (subr, filename, line)
char *filename;
int line;
{
- char *junk;
-
if (output_bytecode)
{
this_function_decl = subr;
@@ -4773,12 +5260,13 @@ init_function_start (subr, filename, line)
init_const_rtx_hash_table ();
- current_function_name = (*decl_printable_name) (subr, &junk);
+ current_function_name = (*decl_printable_name) (subr, 2);
/* Nonzero if this is a nested function that uses a static chain. */
current_function_needs_context
- = (decl_function_context (current_function_decl) != 0);
+ = (decl_function_context (current_function_decl) != 0
+ && ! DECL_NO_STATIC_CHAIN (current_function_decl));
/* Set if a call to setjmp is seen. */
current_function_calls_setjmp = 0;
@@ -4790,6 +5278,7 @@ init_function_start (subr, filename, line)
current_function_has_nonlocal_label = 0;
current_function_has_nonlocal_goto = 0;
current_function_contains_functions = 0;
+ current_function_is_thunk = 0;
current_function_returns_pcc_struct = 0;
current_function_returns_struct = 0;
@@ -4813,10 +5302,8 @@ init_function_start (subr, filename, line)
/* No RTL_EXPRs in this function yet. */
rtl_expr_chain = 0;
- /* We have not allocated any temporaries yet. */
- temp_slots = 0;
- temp_slot_level = 0;
- target_temp_slot_level = 0;
+ /* Set up to allocate temporaries. */
+ init_temp_slots ();
/* Within function body, compute a type's size as soon it is laid out. */
immediate_size_expand++;
@@ -4904,7 +5391,7 @@ expand_main_function ()
extern struct obstack permanent_obstack;
/* Expand start of bytecode function. See comment at
- expand_function_start below for details. */
+ expand_function_start below for details. */
void
bc_expand_function_start (subr, parms_have_cleanups)
@@ -4934,26 +5421,26 @@ bc_expand_function_start (subr, parms_have_cleanups)
}
else
{
- /* Variable-sized objects are pointers to their storage. */
+ /* Variable-sized objects are pointers to their storage. */
DECL_RTL (thisarg) = bc_gen_rtx ((char *) 0, argsz, (struct bc_label *) 0);
argsz += POINTER_SIZE;
}
}
- bc_begin_function (bc_xstrdup (IDENTIFIER_POINTER (DECL_NAME (subr))));
+ bc_begin_function (xstrdup (IDENTIFIER_POINTER (DECL_NAME (subr))));
ASM_GENERATE_INTERNAL_LABEL (label, "LX", nlab);
++nlab;
name = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
this_function_callinfo = bc_gen_rtx (name, 0, (struct bc_label *) 0);
- this_function_bytecode =
- bc_emit_trampoline (BYTECODE_LABEL (this_function_callinfo));
+ this_function_bytecode
+ = bc_emit_trampoline (BYTECODE_LABEL (this_function_callinfo));
}
/* Expand end of bytecode function. See details the comment of
- expand_function_end(), below. */
+ expand_function_end(), below. */
void
bc_expand_function_end ()
@@ -4964,7 +5451,7 @@ bc_expand_function_end ()
/* Emit any fixup code. This must be done before the call to
to BC_END_FUNCTION (), since that will cause the bytecode
- segment to be finished off and closed. */
+ segment to be finished off and closed. */
expand_fixups (NULL_RTX);
@@ -5014,11 +5501,10 @@ expand_function_start (subr, parms_have_cleanups)
{
last_ptr = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
-#ifdef SMALL_REGISTER_CLASSES
/* Delay copying static chain if it is not a register to avoid
conflicts with regs used for parameters. */
- if (GET_CODE (static_chain_incoming_rtx) == REG)
-#endif
+ if (! SMALL_REGISTER_CLASSES
+ || GET_CODE (static_chain_incoming_rtx) == REG)
emit_move_insn (last_ptr, static_chain_incoming_rtx);
}
@@ -5127,14 +5613,12 @@ expand_function_start (subr, parms_have_cleanups)
assign_parms (subr, 0);
-#ifdef SMALL_REGISTER_CLASSES
/* Copy the static chain now if it wasn't a register. The delay is to
avoid conflicts with the parameter passing registers. */
- if (current_function_needs_context)
+ if (SMALL_REGISTER_CLASSES && current_function_needs_context)
if (GET_CODE (static_chain_incoming_rtx) != REG)
emit_move_insn (last_ptr, static_chain_incoming_rtx);
-#endif
/* The following was moved from init_function_start.
The move is supposed to make sdb output more accurate. */
@@ -5157,48 +5641,50 @@ expand_function_start (subr, parms_have_cleanups)
use_variable (current_function_internal_arg_pointer);
}
- /* Fetch static chain values for containing functions. */
- tem = decl_function_context (current_function_decl);
- /* If not doing stupid register allocation copy the static chain
- pointer into a pseudo. If we have small register classes, copy the
- value from memory if static_chain_incoming_rtx is a REG. If we do
- stupid register allocation, we use the stack address generated above. */
- if (tem && ! obey_regdecls)
- {
-#ifdef SMALL_REGISTER_CLASSES
- /* If the static chain originally came in a register, put it back
- there, then move it out in the next insn. The reason for
- this peculiar code is to satisfy function integration. */
- if (GET_CODE (static_chain_incoming_rtx) == REG)
- emit_move_insn (static_chain_incoming_rtx, last_ptr);
-#endif
-
- last_ptr = copy_to_reg (static_chain_incoming_rtx);
- }
-
context_display = 0;
- while (tem)
+ if (current_function_needs_context)
{
- tree rtlexp = make_node (RTL_EXPR);
+ /* Fetch static chain values for containing functions. */
+ tem = decl_function_context (current_function_decl);
+ /* If not doing stupid register allocation copy the static chain
+ pointer into a pseudo. If we have small register classes, copy
+ the value from memory if static_chain_incoming_rtx is a REG. If
+ we do stupid register allocation, we use the stack address
+ generated above. */
+ if (tem && ! obey_regdecls)
+ {
+ /* If the static chain originally came in a register, put it back
+ there, then move it out in the next insn. The reason for
+ this peculiar code is to satisfy function integration. */
+ if (SMALL_REGISTER_CLASSES
+ && GET_CODE (static_chain_incoming_rtx) == REG)
+ emit_move_insn (static_chain_incoming_rtx, last_ptr);
+ last_ptr = copy_to_reg (static_chain_incoming_rtx);
+ }
- RTL_EXPR_RTL (rtlexp) = last_ptr;
- context_display = tree_cons (tem, rtlexp, context_display);
- tem = decl_function_context (tem);
- if (tem == 0)
- break;
- /* Chain thru stack frames, assuming pointer to next lexical frame
- is found at the place we always store it. */
+ while (tem)
+ {
+ tree rtlexp = make_node (RTL_EXPR);
+
+ RTL_EXPR_RTL (rtlexp) = last_ptr;
+ context_display = tree_cons (tem, rtlexp, context_display);
+ tem = decl_function_context (tem);
+ if (tem == 0)
+ break;
+ /* Chain thru stack frames, assuming pointer to next lexical frame
+ is found at the place we always store it. */
#ifdef FRAME_GROWS_DOWNWARD
- last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode));
+ last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode));
#endif
- last_ptr = copy_to_reg (gen_rtx (MEM, Pmode,
- memory_address (Pmode, last_ptr)));
-
- /* If we are not optimizing, ensure that we know that this
- piece of context is live over the entire function. */
- if (! optimize)
- save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, last_ptr,
- save_expr_regs);
+ last_ptr = copy_to_reg (gen_rtx (MEM, Pmode,
+ memory_address (Pmode, last_ptr)));
+
+ /* If we are not optimizing, ensure that we know that this
+ piece of context is live over the entire function. */
+ if (! optimize)
+ save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, last_ptr,
+ save_expr_regs);
+ }
}
/* After the display initializations is where the tail-recursion label
@@ -5208,7 +5694,13 @@ expand_function_start (subr, parms_have_cleanups)
/* Evaluate now the sizes of any types declared among the arguments. */
for (tem = nreverse (get_pending_sizes ()); tem; tem = TREE_CHAIN (tem))
- expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode, 0);
+ {
+ expand_expr (TREE_VALUE (tem), const0_rtx, VOIDmode,
+ EXPAND_MEMORY_USE_BAD);
+ /* Flush the queue in case this parameter declaration has
+ side-effects. */
+ emit_queue ();
+ }
/* Make sure there is a line number after the function entry setup code. */
force_next_line_note ();
@@ -5229,7 +5721,9 @@ expand_function_end (filename, line, end_bindings)
register int i;
tree link;
+#ifdef TRAMPOLINE_TEMPLATE
static rtx initial_trampoline;
+#endif
if (output_bytecode)
{
@@ -5262,8 +5756,10 @@ expand_function_end (filename, line, end_bindings)
tree function = TREE_PURPOSE (link);
rtx context = lookup_static_chain (function);
rtx tramp = RTL_EXPR_RTL (TREE_VALUE (link));
+ rtx blktramp;
rtx seq;
+#ifdef TRAMPOLINE_TEMPLATE
/* First make sure this compilation has a template for
initializing trampolines. */
if (initial_trampoline == 0)
@@ -5273,15 +5769,18 @@ expand_function_end (filename, line, end_bindings)
= gen_rtx (MEM, BLKmode, assemble_trampoline_template ());
resume_temporary_allocation ();
}
+#endif
/* Generate insns to initialize the trampoline. */
start_sequence ();
- tramp = change_address (initial_trampoline, BLKmode,
- round_trampoline_addr (XEXP (tramp, 0)));
- emit_block_move (tramp, initial_trampoline, GEN_INT (TRAMPOLINE_SIZE),
- FUNCTION_BOUNDARY / BITS_PER_UNIT);
- INITIALIZE_TRAMPOLINE (XEXP (tramp, 0),
- XEXP (DECL_RTL (function), 0), context);
+ tramp = round_trampoline_addr (XEXP (tramp, 0));
+#ifdef TRAMPOLINE_TEMPLATE
+ blktramp = change_address (initial_trampoline, BLKmode, tramp);
+ emit_block_move (blktramp, initial_trampoline,
+ GEN_INT (TRAMPOLINE_SIZE),
+ TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
+#endif
+ INITIALIZE_TRAMPOLINE (tramp, XEXP (DECL_RTL (function), 0), context);
seq = get_insns ();
end_sequence ();
@@ -5289,6 +5788,26 @@ expand_function_end (filename, line, end_bindings)
emit_insns_before (seq, tail_recursion_reentry);
}
+ /* If we are doing stack checking and this function makes calls,
+ do a stack probe at the start of the function to ensure we have enough
+ space for another stack frame. */
+ if (flag_stack_check && ! STACK_CHECK_BUILTIN)
+ {
+ rtx insn, seq;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ start_sequence ();
+ probe_stack_range (STACK_CHECK_PROTECT,
+ GEN_INT (STACK_CHECK_MAX_FRAME_SIZE));
+ seq = get_insns ();
+ end_sequence ();
+ emit_insns_before (seq, tail_recursion_reentry);
+ break;
+ }
+ }
+
/* Warn about unused parms if extra warnings were specified. */
if (warn_unused && extra_warnings)
{
@@ -5342,6 +5861,14 @@ expand_function_end (filename, line, end_bindings)
without returning a value. */
emit_note (NULL_PTR, NOTE_INSN_FUNCTION_END);
+ /* Must mark the last line number note in the function, so that the test
+ coverage code can avoid counting the last line twice. This just tells
+ the code to ignore the immediately following line note, since there
+ already exists a copy of this note somewhere above. This line number
+ note is still needed for debugging though, so we can't delete it. */
+ if (flag_test_coverage)
+ emit_note (NULL_PTR, NOTE_REPEATED_LINE_NUMBER);
+
/* Output a linenumber for the end of the function.
SDB depends on this. */
emit_line_note_force (filename, line);
@@ -5359,6 +5886,24 @@ expand_function_end (filename, line, end_bindings)
if (end_bindings)
expand_end_bindings (0, 0, 0);
+ /* Now handle any leftover exception regions that may have been
+ created for the parameters. */
+ {
+ rtx last = get_last_insn ();
+ rtx label;
+
+ expand_leftover_cleanups ();
+
+ /* If the above emitted any code, may sure we jump around it. */
+ if (last != get_last_insn ())
+ {
+ label = gen_label_rtx ();
+ last = emit_jump_insn_after (gen_jump (label), last);
+ last = emit_barrier_after (last);
+ emit_label (label);
+ }
+ }
+
/* If we had calls to alloca, and this machine needs
an accurate stack pointer to exit the function,
insert some code to save and restore the stack pointer. */
@@ -5392,9 +5937,19 @@ expand_function_end (filename, line, end_bindings)
current_function_decl);
#endif
REG_FUNCTION_VALUE_P (real_decl_result) = 1;
+ /* If this is a BLKmode structure being returned in registers, then use
+ the mode computed in expand_return. */
+ if (GET_MODE (real_decl_result) == BLKmode)
+ PUT_MODE (real_decl_result,
+ GET_MODE (DECL_RTL (DECL_RESULT (current_function_decl))));
emit_move_insn (real_decl_result,
DECL_RTL (DECL_RESULT (current_function_decl)));
emit_insn (gen_rtx (USE, VOIDmode, real_decl_result));
+
+ /* The delay slot scheduler assumes that current_function_return_rtx
+ holds the hard register containing the return value, not a temporary
+ pseudo. */
+ current_function_return_rtx = real_decl_result;
}
/* If returning a structure, arrange to return the address of the value
diff --git a/gnu/usr.bin/gcc/function.h b/gnu/usr.bin/gcc/function.h
index 24b4be25b05..d1a5b3115b0 100644
--- a/gnu/usr.bin/gcc/function.h
+++ b/gnu/usr.bin/gcc/function.h
@@ -1,5 +1,5 @@
/* Structure for saving state for a nested function.
- Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -70,6 +70,7 @@ struct function
int pops_args;
int returns_struct;
int returns_pcc_struct;
+ int returns_pointer;
int needs_context;
int calls_setjmp;
int calls_longjmp;
@@ -77,6 +78,7 @@ struct function
int has_nonlocal_label;
int has_nonlocal_goto;
int contains_functions;
+ int is_thunk;
rtx nonlocal_goto_handler_slot;
rtx nonlocal_goto_stack_level;
tree nonlocal_labels;
@@ -94,7 +96,7 @@ struct function
rtx save_expr_regs;
rtx stack_slot_list;
rtx parm_birth_insn;
- int frame_offset;
+ HOST_WIDE_INT frame_offset;
rtx tail_recursion_label;
rtx tail_recursion_reentry;
rtx internal_arg_pointer;
@@ -109,6 +111,7 @@ struct function
/* This slot is initialized as 0 and is added to
during the nested function. */
struct var_refs_queue *fixup_var_refs_queue;
+ CUMULATIVE_ARGS args_info;
/* For stmt.c */
struct nesting *block_stack;
@@ -126,10 +129,19 @@ struct function
int emit_lineno;
struct goto_fixup *goto_fixup_chain;
+ /* For exception handling information. */
+ struct eh_stack ehstack;
+ struct eh_queue ehqueue;
+ rtx catch_clauses;
+ struct label_node *false_label_stack;
+ struct label_node *caught_return_label_stack;
+ tree protect_list;
+ rtx dhc;
+ rtx dcc;
+
/* For expr.c. */
int pending_stack_adjust;
int inhibit_defer_pop;
- tree cleanups_this_call;
rtx saveregs_value;
rtx apply_args_value;
rtx forced_labels;
@@ -145,6 +157,7 @@ struct function
int last_linenum;
char *last_filename;
char *regno_pointer_flag;
+ char *regno_pointer_align;
int regno_pointer_flag_length;
rtx *regno_reg_rtx;
@@ -187,6 +200,7 @@ struct function
struct pool_sym **const_rtx_sym_hash_table;
struct pool_constant *first_pool, *last_pool;
int pool_offset;
+ rtx const_double_chain;
};
/* The FUNCTION_DECL for an inline function currently being expanded. */
@@ -213,15 +227,32 @@ extern struct function *outer_function_chain;
the index of that block in the vector. */
extern tree *identify_blocks PROTO((tree, rtx));
+/* Return size needed for stack frame based on slots so far allocated.
+ This size counts from zero. It is not rounded to STACK_BOUNDARY;
+ the caller may have to do that. */
+extern HOST_WIDE_INT get_frame_size PROTO((void));
+
/* These variables hold pointers to functions to
save and restore machine-specific data,
in push_function_context and pop_function_context. */
-extern void (*save_machine_status) ();
-extern void (*restore_machine_status) ();
+extern void (*save_machine_status) PROTO((struct function *));
+extern void (*restore_machine_status) PROTO((struct function *));
-/* Save and restore varasm.c status for a nested function. */
-extern void save_varasm_status PROTO((struct function *));
+/* Save and restore status information for a nested function. */
+extern void save_tree_status PROTO((struct function *, tree));
+extern void restore_tree_status PROTO((struct function *, tree));
+extern void save_varasm_status PROTO((struct function *, tree));
extern void restore_varasm_status PROTO((struct function *));
+extern void save_eh_status PROTO((struct function *));
+extern void restore_eh_status PROTO((struct function *));
+extern void save_stmt_status PROTO((struct function *));
+extern void restore_stmt_status PROTO((struct function *));
+extern void save_expr_status PROTO((struct function *));
+extern void restore_expr_status PROTO((struct function *));
+extern void save_emit_status PROTO((struct function *));
+extern void restore_emit_status PROTO((struct function *));
+extern void save_storage_status PROTO((struct function *));
+extern void restore_storage_status PROTO((struct function *));
#ifdef rtx
#undef rtx
diff --git a/gnu/usr.bin/gcc/gbl-ctors.h b/gnu/usr.bin/gcc/gbl-ctors.h
index 537df5014d5..6393a9045ab 100644
--- a/gnu/usr.bin/gcc/gbl-ctors.h
+++ b/gnu/usr.bin/gcc/gbl-ctors.h
@@ -2,7 +2,7 @@
for getting g++ file-scope static objects constructed. This file
will get included either by libgcc2.c (for systems that don't support
a .init section) or by crtstuff.c (for those that do).
- Copyright (C) 1991, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@segfault.us.com)
This file is part of GNU CC.
@@ -30,8 +30,14 @@ Boston, MA 02111-1307, USA. */
Note that this file should only be compiled with GCC.
*/
+#ifdef NEED_ATEXIT
+#ifndef HAVE_ATEXIT
+#define HAVE_ATEXIT 1 /* Take it from libgcc2.c */
+#endif
+#endif
+
#ifdef HAVE_ATEXIT
-#ifdef WINNT
+#if defined (WINNT) || defined (NEED_ATEXIT)
extern int atexit (void (*) (void));
#else
extern void atexit (void (*) (void));
@@ -39,7 +45,7 @@ extern void atexit (void (*) (void));
#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
#else
#ifdef sun
-extern void on_exit (void*, void*);
+extern int on_exit (void *, void *); /* The man page says it returns int. */
#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
#endif
#endif
diff --git a/gnu/usr.bin/gcc/gcc.1 b/gnu/usr.bin/gcc/gcc.1
index 44accff4013..cd511d4bcb0 100644
--- a/gnu/usr.bin/gcc/gcc.1
+++ b/gnu/usr.bin/gcc/gcc.1
@@ -20,7 +20,7 @@
.if n .sp
.if t .sp 0.4
..
-.Id $Id: gcc.1,v 1.1.1.1 1995/12/20 01:02:34 niklas Exp $
+.Id $Id: gcc.1,v 1.1.1.2 1998/02/14 19:11:12 niklas Exp $
.TH GCC 1 "\*(Dt" "GNU Tools" "GNU Tools"
.SH NAME
gcc, g++ \- GNU project C and C++ Compiler (v2.7)
@@ -157,6 +157,10 @@ in the following sections.
\-fexternal\-templates
\-fno\-asm
\-fno\-builtin
+\-fhosted
+\-fno\-hosted
+\-ffreestanding
+\-fno\-freestanding
\-fno\-strict\-prototype
\-fsigned\-bitfields
\-fsigned\-char
@@ -186,7 +190,10 @@ in the following sections.
\-Wformat
.RI \-Wid\-clash\- len
\-Wimplicit
+\-Wimplicit\-int
+\-Wimplicit\-function\-declaration
\-Winline
+\-Wmain
\-Wmissing\-prototypes
\-Wmissing\-declarations
\-Wnested\-externs
@@ -793,6 +800,20 @@ The `\|\c
\& from
being builtin functions.
.TP
+.B \-fhosted
+Compile for a hosted environment; this implies the `\|\c
+.B \-fbuiltin\c
+\&\|' option, and implies that suspicious declarations of
+.B main\c
+\& should be warned about.
+.TP
+.B \-ffreestanding
+Compile for a freestanding environment; this implies the `\|\c
+.B \-fno-builtin\c
+\&\|' option, and implies that
+.B main\c
+\& has no special requirements.
+.TP
.B \-fno\-strict\-prototype
Treat a function declaration with no arguments, such as `\|\c
.B int foo
@@ -1698,8 +1719,24 @@ An unsigned value is compared against zero with `\|\c
\&\|'.
.PP
.TP
+.B \-Wimplicit-int
+Warn whenever a declaration does not specify a type.
+.TP
+.B \-Wimplicit-function-declaration
+Warn whenever a function is used before being declared.
+.TP
.B \-Wimplicit
-Warn whenever a function or parameter is implicitly declared.
+Same as -Wimplicit-int and -Wimplicit-function-declaration.
+.TP
+.B \-Wmain
+Warn if the
+.B main
+function is declared or defined with a suspicious type.
+Typically, it is a function with external linkage, returning
+.B int\c
+\&, and
+taking zero or two arguments.
+
.TP
.B \-Wreturn\-type
Warn whenever a function is defined with a return-type that defaults
@@ -2125,6 +2162,25 @@ Eventually GNU \c
.B gprof\c
\& should be extended to process this data.
.TP
+.B \-ax
+Generate extra code to read basic block profiling parameters from
+file `bb.in' and write profiling results to file `bb.out'.
+`bb.in' contains a list of functions. Whenever a function on the list
+is entered, profiling is turned on. When the outmost function is left,
+profiling is turned off. If a function name is prefixed with `-'
+the function is excluded from profiling. If a function name is not
+unique it can be disambiguated by writing
+`/path/filename.d:functionname'. `bb.out' will list some available
+filenames.
+Four function names have a special meaning:
+`__bb_jumps__' will cause jump frequencies to be written to `bb.out'.
+`__bb_trace__' will cause the sequence of basic blocks to be piped
+into `gzip' and written to file `bbtrace.gz'.
+`__bb_hidecall__' will cause call instructions to be excluded from
+the trace.
+`__bb_showret__' will cause return instructions to be included in
+the trace.
+.TP
.BI "\-d" "letters"
Says to make debugging dumps during compilation at times specified by
.I letters\c
@@ -3942,7 +3998,7 @@ three-way choice.
.BI "\-fcall\-used\-" "reg"
Treat the register named \c
.I reg\c
-\& as an allocatable register that is
+\& as an allocable register that is
clobbered by function calls. It may be allocated for temporaries or
variables that do not live across a call. Functions compiled this way
will not save and restore the register \c
@@ -3959,7 +4015,7 @@ three-way choice.
.BI "\-fcall\-saved\-" "reg"
Treat the register named \c
.I reg\c
-\& as an allocatable register saved by
+\& as an allocable register saved by
functions. It may be allocated even for temporaries or variables that
live across a call. Functions compiled this way will save and restore
the register \c
diff --git a/gnu/usr.bin/gcc/gcc.cps b/gnu/usr.bin/gcc/gcc.cps
index 0e65d8a6492..f0d186f592f 100644
--- a/gnu/usr.bin/gcc/gcc.cps
+++ b/gnu/usr.bin/gcc/gcc.cps
@@ -1,1898 +1,1964 @@
+, 156}
\initial {!}
-\entry {\samp {!} in constraint}{288}
+\entry {\samp {!} in constraint}{306}
\initial {#}
-\entry {\samp {#} in constraint}{289}
-\entry {\code {#} in template}{280}
-\entry {\code {#pragma}}{434}
-\entry {\code {#pragma implementation}, implied}{173}
-\entry {\code {#pragma}, reason for not using}{147}
+\entry {\samp {#} in constraint}{307}
+\entry {\code {#} in template}{299}
+\entry {\code {#pragma}}{466}
+\entry {\code {#pragma implementation}, implied}{182}
+\entry {\code {#pragma}, reason for not using}{157}
\initial {$}
-\entry {$}{149}
+\entry {$}{158}
\initial {%}
-\entry {\samp {%} in constraint}{289}
-\entry {\samp {%} in template}{279}
+\entry {\samp {%} in constraint}{307}
+\entry {\samp {%} in template}{298}
\initial {&}
-\entry {\samp {&} in constraint}{289}
+\entry {\samp {&} in constraint}{307}
\initial {'}
-\entry {'}{192}
+\entry {'}{203}
\initial {(}
-\entry {(nil)}{232}
+\entry {(nil)}{248}
\initial {*}
-\entry {\samp {*} in constraint}{289}
-\entry {\code {*} in template}{281}
+\entry {\samp {*} in constraint}{308}
+\entry {\code {*} in template}{299}
\initial {-}
-\entry {\code {-lgcc}, use with \code {-nodefaultlibs}}{53}
-\entry {\code {-lgcc}, use with \code {-nostdlib}}{53}
-\entry {\code {-nodefaultlibs} and unresolved references}{53}
-\entry {\code {-nostdlib} and unresolved references}{53}
+\entry {\code {-lgcc}, use with \code {-nodefaultlibs}}{49}
+\entry {\code {-lgcc}, use with \code {-nostdlib}}{49}
+\entry {\code {-nodefaultlibs} and unresolved references}{49}
+\entry {\code {-nostdlib} and unresolved references}{49}
+\initial {.}
+\entry {.sdata/.sdata2 references (PowerPC)}{74}
\initial {/}
-\entry {\samp {/i} in RTL dump}{235}
-\entry {\samp {/s} in RTL dump}{235, 236}
-\entry {\samp {/u} in RTL dump}{235}
-\entry {\samp {/v} in RTL dump}{235}
+\entry {//}{158}
+\entry {\samp {/i} in RTL dump}{251}
+\entry {\samp {/s} in RTL dump}{250, 252}
+\entry {\samp {/u} in RTL dump}{251}
+\entry {\samp {/v} in RTL dump}{250}
\initial {=}
-\entry {\samp {=} in constraint}{289}
+\entry {\samp {=} in constraint}{307}
\initial {?}
-\entry {\samp {?} in constraint}{288}
-\entry {\code {?:} extensions}{133, 134}
-\entry {?: side effect}{135}
+\entry {\samp {?} in constraint}{306}
+\entry {\code {?:} extensions}{142, 143}
+\entry {?: side effect}{143}
\initial {{\_}}
-\entry {\samp {{\_}} in variables in macros}{132}
-\entry {\code {{\_}{\_}bb{\_}init{\_}func}}{381}
-\entry {\code {{\_}{\_}builtin{\_}apply}}{131}
-\entry {\code {{\_}{\_}builtin{\_}apply{\_}args}}{131}
-\entry {\code {{\_}{\_}builtin{\_}args{\_}info}}{383}
-\entry {\code {{\_}{\_}builtin{\_}classify{\_}type}}{383}
-\entry {\code {{\_}{\_}builtin{\_}next{\_}arg}}{383}
-\entry {\code {{\_}{\_}builtin{\_}return}}{131}
-\entry {\code {{\_}{\_}builtin{\_}saveregs}}{382}
-\entry {\code {{\_}{\_}CTOR{\_}LIST{\_}{\_}}}{412}
-\entry {\code {{\_}{\_}DTOR{\_}LIST{\_}{\_}}}{412}
-\entry {\code {{\_}{\_}main}}{122}
+\entry {\samp {{\_}} in variables in macros}{141}
+\entry {\code {{\_}{\_}bb}}{407}
+\entry {\code {{\_}{\_}bb{\_}init{\_}func}}{406}
+\entry {\code {{\_}{\_}bb{\_}init{\_}trace{\_}func}}{407, 408}
+\entry {\code {{\_}{\_}bb{\_}trace{\_}func}}{407, 408}
+\entry {\code {{\_}{\_}bb{\_}trace{\_}ret}}{408}
+\entry {\code {{\_}{\_}builtin{\_}apply}}{140}
+\entry {\code {{\_}{\_}builtin{\_}apply{\_}args}}{140}
+\entry {\code {{\_}{\_}builtin{\_}args{\_}info}}{409}
+\entry {\code {{\_}{\_}builtin{\_}classify{\_}type}}{410}
+\entry {\code {{\_}{\_}builtin{\_}next{\_}arg}}{410}
+\entry {\code {{\_}{\_}builtin{\_}return}}{140}
+\entry {\code {{\_}{\_}builtin{\_}saveregs}}{409}
+\entry {\code {{\_}{\_}CTOR{\_}LIST{\_}{\_}}}{442}
+\entry {\code {{\_}{\_}DTOR{\_}LIST{\_}{\_}}}{442}
+\entry {\code {{\_}{\_}main}}{132}
\initial {{\tt\char43}}
-\entry {\samp {{\tt\char43}} in constraint}{289}
+\entry {\samp {{\tt\char43}} in constraint}{307}
\initial {{\tt\gtr}}
-\entry {\samp {{\tt\gtr}} in constraint}{283}
-\entry {\code {{\tt\gtr}?}}{171}
+\entry {\samp {{\tt\gtr}} in constraint}{301}
+\entry {\code {{\tt\gtr}?}}{181}
\initial {{\tt\indexbackslash }}
-\entry {{\tt\indexbackslash }}{280}
+\entry {{\tt\indexbackslash }}{298}
\initial {{\tt\less}}
-\entry {\samp {{\tt\less}} in constraint}{283}
-\entry {\code {{\tt\less}?}}{171}
+\entry {\samp {{\tt\less}} in constraint}{301}
+\entry {\code {{\tt\less}?}}{181}
\initial {0}
-\entry {\samp {0} in constraint}{284}
+\entry {\samp {0} in constraint}{303}
\initial {A}
-\entry {\code {abort}}{28, 221}
-\entry {\code {abs}}{28, 250}
-\entry {\code {abs} and attributes}{323}
-\entry {\code {abs\var {m}2} instruction pattern}{299}
-\entry {absolute value}{250}
-\entry {access to operands}{232}
-\entry {accessors}{232}
-\entry {\code {ACCUMULATE{\_}OUTGOING{\_}ARGS}}{369}
-\entry {\code {ACCUMULATE{\_}OUTGOING{\_}ARGS} and stack frames}{379}
-\entry {\code {ADDITIONAL{\_}REGISTER{\_}NAMES}}{416}
-\entry {\code {add\var {m}3} instruction pattern}{298}
-\entry {\code {addr{\_}diff{\_}vec}}{259}
-\entry {\code {addr{\_}diff{\_}vec}, length of}{329}
-\entry {\code {addr{\_}vec}}{259}
-\entry {\code {addr{\_}vec}, length of}{329}
-\entry {\code {address}}{279}
-\entry {address constraints}{285}
-\entry {address of a label}{127}
-\entry {\code {ADDRESS{\_}COST}}{396}
-\entry {\code {address{\_}operand}}{285}
-\entry {addressing modes}{391}
-\entry {\code {ADJUST{\_}COST}}{399}
-\entry {\code {ADJUST{\_}INSN{\_}LENGTH}}{329}
-\entry {aggregates as return values}{376}
-\entry {\code {alias} attribute}{147}
-\entry {\code {aligned} attribute}{151, 154}
-\entry {alignment}{150}
-\entry {\code {ALL{\_}REGS}}{357}
-\entry {Alliant}{188}
-\entry {\code {alloca}}{28}
-\entry {\code {alloca} and SunOs}{97}
-\entry {\code {alloca} vs variable-length arrays}{137}
-\entry {\code {alloca}, for SunOs}{118}
-\entry {\code {alloca}, for Unos}{106}
-\entry {\code {allocate{\_}stack} instruction pattern}{306}
-\entry {\code {ALLOCATE{\_}TRAMPOLINE}}{386}
-\entry {alternate keywords}{165}
-\entry {AMD29K options}{63}
-\entry {analysis, data flow}{227}
-\entry {\code {and}}{250}
-\entry {\code {and} and attributes}{323}
-\entry {\code {and}, canonicalization of}{311}
-\entry {\code {and\var {m}3} instruction pattern}{298}
-\entry {ANSI support}{27}
-\entry {apostrophes}{192}
-\entry {\code {APPLY{\_}RESULT{\_}SIZE}}{376}
-\entry {\code {ARG{\_}POINTER{\_}REGNUM}}{366}
-\entry {\code {ARG{\_}POINTER{\_}REGNUM} and virtual registers}{245}
-\entry {\code {arg{\_}pointer{\_}rtx}}{367}
-\entry {\code {ARGS{\_}GROW{\_}DOWNWARD}}{364}
-\entry {argument passing}{223}
-\entry {arguments in frame (88k)}{66}
-\entry {arguments in registers}{371}
-\entry {arguments on stack}{369}
-\entry {arithmetic libraries}{224}
-\entry {arithmetic shift}{250}
-\entry {arithmetic simplifications}{225}
-\entry {arithmetic, in RTL}{248}
-\entry {ARM options}{64}
-\entry {arrays of length zero}{136}
-\entry {arrays of variable length}{137}
-\entry {arrays, non-lvalue}{139}
-\entry {\code {ashift}}{250}
-\entry {\code {ashift} and attributes}{323}
-\entry {\code {ashiftrt}}{250}
-\entry {\code {ashiftrt} and attributes}{323}
-\entry {\code {ashl\var {m}3} instruction pattern}{299}
-\entry {\code {ashr\var {m}3} instruction pattern}{299}
-\entry {\code {asm} expressions}{157}
-\entry {\code {ASM{\_}APP{\_}OFF}}{403}
-\entry {\code {ASM{\_}APP{\_}ON}}{403}
-\entry {\code {ASM{\_}BYTE{\_}OP}}{405}
-\entry {\code {ASM{\_}CLOSE{\_}PAREN}}{406}
-\entry {\code {ASM{\_}COMMENT{\_}START}}{403}
-\entry {\code {ASM{\_}DECLARE{\_}FUNCTION{\_}NAME}}{408}
-\entry {\code {ASM{\_}DECLARE{\_}FUNCTION{\_}SIZE}}{408}
-\entry {\code {ASM{\_}DECLARE{\_}OBJECT{\_}NAME}}{408}
-\entry {\code {ASM{\_}FILE{\_}END}}{403}
-\entry {\code {ASM{\_}FILE{\_}START}}{402}
-\entry {\code {ASM{\_}FINAL{\_}SPEC}}{336}
-\entry {\code {ASM{\_}FINISH{\_}DECLARE{\_}OBJECT}}{408}
-\entry {\code {ASM{\_}FORMAT{\_}PRIVATE{\_}NAME}}{410}
-\entry {\code {asm{\_}fprintf}}{418}
-\entry {\code {ASM{\_}GENERATE{\_}INTERNAL{\_}LABEL}}{410}
-\entry {\code {ASM{\_}GLOBALIZE{\_}LABEL}}{409}
-\entry {\code {ASM{\_}IDENTIFY{\_}GCC}}{403}
-\entry {\code {asm{\_}input}}{259}
-\entry {\code {ASM{\_}NO{\_}SKIP{\_}IN{\_}TEXT}}{420}
-\entry {\code {asm{\_}noperands}}{265}
-\entry {\code {ASM{\_}OPEN{\_}PAREN}}{406}
-\entry {\code {asm{\_}operands}, RTL sharing}{271}
-\entry {\code {asm{\_}operands}, usage}{260}
-\entry {\code {ASM{\_}OUTPUT{\_}ADDR{\_}DIFF{\_}ELT}}{419}
-\entry {\code {ASM{\_}OUTPUT{\_}ADDR{\_}VEC{\_}ELT}}{419}
-\entry {\code {ASM{\_}OUTPUT{\_}ALIGN}}{420}
-\entry {\code {ASM{\_}OUTPUT{\_}ALIGN{\_}CODE}}{420}
-\entry {\code {ASM{\_}OUTPUT{\_}ALIGNED{\_}COMMON}}{407}
-\entry {\code {ASM{\_}OUTPUT{\_}ALIGNED{\_}LOCAL}}{407}
-\entry {\code {ASM{\_}OUTPUT{\_}ASCII}}{405}
-\entry {\code {ASM{\_}OUTPUT{\_}BYTE}}{405}
-\entry {\code {ASM{\_}OUTPUT{\_}CASE{\_}END}}{419}
-\entry {\code {ASM{\_}OUTPUT{\_}CASE{\_}LABEL}}{419}
-\entry {\code {ASM{\_}OUTPUT{\_}CHAR}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}COMMON}}{407}
-\entry {\code {ASM{\_}OUTPUT{\_}CONSTRUCTOR}}{414}
-\entry {\code {ASM{\_}OUTPUT{\_}DEF}}{410}
-\entry {\code {ASM{\_}OUTPUT{\_}DESTRUCTOR}}{415}
-\entry {\code {ASM{\_}OUTPUT{\_}DOUBLE}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}DOUBLE{\_}INT}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}EXTERNAL}}{409}
-\entry {\code {ASM{\_}OUTPUT{\_}EXTERNAL{\_}LIBCALL}}{409}
-\entry {\code {ASM{\_}OUTPUT{\_}FLOAT}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}IDENT}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}INT}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}INTERNAL{\_}LABEL}}{410}
-\entry {\code {ASM{\_}OUTPUT{\_}LABEL}}{408}
-\entry {\code {ASM{\_}OUTPUT{\_}LABELREF}}{409}
-\entry {\code {ASM{\_}OUTPUT{\_}LOCAL}}{407}
-\entry {\code {ASM{\_}OUTPUT{\_}LONG{\_}DOUBLE}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}LOOP{\_}ALIGN}}{420}
-\entry {\code {ASM{\_}OUTPUT{\_}OPCODE}}{416}
-\entry {\code {ASM{\_}OUTPUT{\_}POOL{\_}PROLOGUE}}{405}
-\entry {\code {ASM{\_}OUTPUT{\_}QUADRUPLE{\_}INT}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}REG{\_}POP}}{418}
-\entry {\code {ASM{\_}OUTPUT{\_}REG{\_}PUSH}}{418}
-\entry {\code {ASM{\_}OUTPUT{\_}SECTION{\_}NAME}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}SHARED{\_}COMMON}}{407}
-\entry {\code {ASM{\_}OUTPUT{\_}SHARED{\_}LOCAL}}{408}
-\entry {\code {ASM{\_}OUTPUT{\_}SHORT}}{404}
-\entry {\code {ASM{\_}OUTPUT{\_}SKIP}}{420}
-\entry {\code {ASM{\_}OUTPUT{\_}SOURCE{\_}FILENAME}}{403}
-\entry {\code {ASM{\_}OUTPUT{\_}SOURCE{\_}LINE}}{403}
-\entry {\code {ASM{\_}OUTPUT{\_}SPECIAL{\_}POOL{\_}ENTRY}}{405}
-\entry {\code {ASM{\_}SPEC}}{336}
-\entry {\code {ASM{\_}STABD{\_}OP}}{422}
-\entry {\code {ASM{\_}STABN{\_}OP}}{422}
-\entry {\code {ASM{\_}STABS{\_}OP}}{422}
-\entry {\code {ASM{\_}WEAKEN{\_}LABEL}}{409}
-\entry {\code {assemble{\_}name}}{408}
-\entry {assembler format}{402}
-\entry {assembler instructions}{157}
-\entry {assembler instructions in RTL}{260}
-\entry {assembler names for identifiers}{161}
-\entry {assembler syntax, 88k}{66}
-\entry {\code {ASSEMBLER{\_}DIALECT}}{418}
-\entry {assembly code, invalid}{203}
-\entry {assigning attribute values to insns}{325}
-\entry {asterisk in template}{281}
-\entry {\code {atof}}{427}
-\entry {\code {attr}}{326}
-\entry {\code {attr{\_}flag}}{324}
-\entry {attribute expressions}{322}
-\entry {attribute of types}{153}
-\entry {attribute of variables}{150}
-\entry {attribute specifications}{327}
-\entry {attribute specifications example}{327}
-\entry {attributes, defining}{321}
-\entry {autoincrement addressing, availability}{221}
-\entry {autoincrement/decrement addressing}{283}
-\entry {autoincrement/decrement analysis}{227}
-\entry {automatic \code {inline} for C{\tt\char43}{\tt\char43} member fns}{156}
+\entry {\code {abort}}{18, 235}
+\entry {\code {abs}}{18, 267}
+\entry {\code {abs} and attributes}{342}
+\entry {\code {abs\var {m}2} instruction pattern}{318}
+\entry {absolute value}{267}
+\entry {access to operands}{248}
+\entry {accessors}{248}
+\entry {\code {ACCUMULATE{\_}OUTGOING{\_}ARGS}}{392}
+\entry {\code {ACCUMULATE{\_}OUTGOING{\_}ARGS} and stack frames}{403}
+\entry {\code {ADDITIONAL{\_}REGISTER{\_}NAMES}}{446}
+\entry {\code {add\var {m}3} instruction pattern}{317}
+\entry {\code {addr{\_}diff{\_}vec}}{277}
+\entry {\code {addr{\_}diff{\_}vec}, length of}{347}
+\entry {\code {addr{\_}vec}}{277}
+\entry {\code {addr{\_}vec}, length of}{347}
+\entry {\code {address}}{297}
+\entry {address constraints}{303}
+\entry {address of a label}{137}
+\entry {\code {ADDRESS{\_}COST}}{424}
+\entry {\code {address{\_}operand}}{303}
+\entry {addressing modes}{418}
+\entry {\code {ADJUST{\_}COST}}{427}
+\entry {\code {ADJUST{\_}FIELD{\_}ALIGN}}{365}
+\entry {\code {ADJUST{\_}INSN{\_}LENGTH}}{348}
+\entry {\code {ADJUST{\_}PRIORITY}}{427}
+\entry {aggregates as return values}{399}
+\entry {\code {alias} attribute}{155}
+\entry {\code {aligned} attribute}{159, 163}
+\entry {alignment}{159}
+\entry {\code {ALL{\_}REGS}}{379}
+\entry {Alliant}{199}
+\entry {\code {alloca}}{18}
+\entry {\code {alloca} and SunOS}{104}
+\entry {\code {alloca} vs variable-length arrays}{145}
+\entry {\code {alloca}, for SunOS}{127}
+\entry {\code {alloca}, for Unos}{113}
+\entry {\code {allocate{\_}stack} instruction pattern}{326}
+\entry {\code {ALLOCATE{\_}TRAMPOLINE}}{413}
+\entry {alternate keywords}{174}
+\entry {AMD29K options}{60}
+\entry {analysis, data flow}{242}
+\entry {\code {and}}{267}
+\entry {\code {and} and attributes}{342}
+\entry {\code {and}, canonicalization of}{331}
+\entry {\code {and\var {m}3} instruction pattern}{317}
+\entry {ANSI support}{17}
+\entry {apostrophes}{203}
+\entry {\code {APPLY{\_}RESULT{\_}SIZE}}{399}
+\entry {\code {ARG{\_}POINTER{\_}REGNUM}}{388}
+\entry {\code {ARG{\_}POINTER{\_}REGNUM} and virtual registers}{261}
+\entry {\code {arg{\_}pointer{\_}rtx}}{389}
+\entry {\code {ARGS{\_}GROW{\_}DOWNWARD}}{386}
+\entry {argument passing}{237}
+\entry {arguments in frame (88k)}{64}
+\entry {arguments in registers}{394}
+\entry {arguments on stack}{391}
+\entry {arithmetic libraries}{238}
+\entry {arithmetic shift}{267}
+\entry {arithmetic simplifications}{239}
+\entry {arithmetic, in RTL}{265}
+\entry {ARM options}{61}
+\entry {arrays of length zero}{145}
+\entry {arrays of variable length}{145}
+\entry {arrays, non-lvalue}{147}
+\entry {\code {ashift}}{267}
+\entry {\code {ashift} and attributes}{342}
+\entry {\code {ashiftrt}}{267}
+\entry {\code {ashiftrt} and attributes}{342}
+\entry {\code {ashl\var {m}3} instruction pattern}{317}
+\entry {\code {ashr\var {m}3} instruction pattern}{318}
+\entry {\code {asm} expressions}{167}
+\entry {\code {ASM{\_}APP{\_}OFF}}{432}
+\entry {\code {ASM{\_}APP{\_}ON}}{432}
+\entry {\code {ASM{\_}BYTE{\_}OP}}{434}
+\entry {\code {ASM{\_}CLOSE{\_}PAREN}}{435}
+\entry {\code {ASM{\_}COMMENT{\_}START}}{432}
+\entry {\code {ASM{\_}DECLARE{\_}FUNCTION{\_}NAME}}{438}
+\entry {\code {ASM{\_}DECLARE{\_}FUNCTION{\_}SIZE}}{438}
+\entry {\code {ASM{\_}DECLARE{\_}OBJECT{\_}NAME}}{438}
+\entry {\code {ASM{\_}FILE{\_}END}}{432}
+\entry {\code {ASM{\_}FILE{\_}START}}{431}
+\entry {\code {ASM{\_}FINAL{\_}SPEC}}{354}
+\entry {\code {ASM{\_}FINISH{\_}DECLARE{\_}OBJECT}}{438}
+\entry {\code {ASM{\_}FORMAT{\_}PRIVATE{\_}NAME}}{440}
+\entry {\code {asm{\_}fprintf}}{448}
+\entry {\code {ASM{\_}GENERATE{\_}INTERNAL{\_}LABEL}}{440}
+\entry {\code {ASM{\_}GLOBALIZE{\_}LABEL}}{439}
+\entry {\code {ASM{\_}IDENTIFY{\_}GCC}}{432}
+\entry {\code {asm{\_}input}}{276}
+\entry {\code {ASM{\_}NO{\_}SKIP{\_}IN{\_}TEXT}}{451}
+\entry {\code {asm{\_}noperands}}{283}
+\entry {\code {ASM{\_}OPEN{\_}PAREN}}{435}
+\entry {\code {asm{\_}operands}, RTL sharing}{289}
+\entry {\code {asm{\_}operands}, usage}{278}
+\entry {\code {ASM{\_}OUTPUT{\_}ADDR{\_}DIFF{\_}ELT}}{449}
+\entry {\code {ASM{\_}OUTPUT{\_}ADDR{\_}VEC{\_}ELT}}{449}
+\entry {\code {ASM{\_}OUTPUT{\_}ALIGN}}{451}
+\entry {\code {ASM{\_}OUTPUT{\_}ALIGN{\_}CODE}}{450}
+\entry {\code {ASM{\_}OUTPUT{\_}ALIGNED{\_}BSS}}{437}
+\entry {\code {ASM{\_}OUTPUT{\_}ALIGNED{\_}COMMON}}{436}
+\entry {\code {ASM{\_}OUTPUT{\_}ALIGNED{\_}LOCAL}}{437}
+\entry {\code {ASM{\_}OUTPUT{\_}ASCII}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}BSS}}{436}
+\entry {\code {ASM{\_}OUTPUT{\_}BYTE}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}CASE{\_}END}}{450}
+\entry {\code {ASM{\_}OUTPUT{\_}CASE{\_}LABEL}}{450}
+\entry {\code {ASM{\_}OUTPUT{\_}CHAR}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}COMMON}}{436}
+\entry {\code {ASM{\_}OUTPUT{\_}CONSTRUCTOR}}{444}
+\entry {\code {ASM{\_}OUTPUT{\_}DEF}}{441}
+\entry {\code {ASM{\_}OUTPUT{\_}DESTRUCTOR}}{445}
+\entry {\code {ASM{\_}OUTPUT{\_}DOUBLE}}{433}
+\entry {\code {ASM{\_}OUTPUT{\_}DOUBLE{\_}INT}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}EXTERNAL}}{439}
+\entry {\code {ASM{\_}OUTPUT{\_}EXTERNAL{\_}LIBCALL}}{439}
+\entry {\code {ASM{\_}OUTPUT{\_}FLOAT}}{433}
+\entry {\code {ASM{\_}OUTPUT{\_}IDENT}}{433}
+\entry {\code {ASM{\_}OUTPUT{\_}INT}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}INTERNAL{\_}LABEL}}{440}
+\entry {\code {ASM{\_}OUTPUT{\_}LABEL}}{438}
+\entry {\code {ASM{\_}OUTPUT{\_}LABELREF}}{440}
+\entry {\code {ASM{\_}OUTPUT{\_}LOCAL}}{437}
+\entry {\code {ASM{\_}OUTPUT{\_}LONG{\_}DOUBLE}}{433}
+\entry {\code {ASM{\_}OUTPUT{\_}LOOP{\_}ALIGN}}{450}
+\entry {\code {ASM{\_}OUTPUT{\_}MI{\_}THUNK}}{405}
+\entry {\code {ASM{\_}OUTPUT{\_}OPCODE}}{446}
+\entry {\code {ASM{\_}OUTPUT{\_}POOL{\_}PROLOGUE}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}QUADRUPLE{\_}INT}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}REG{\_}POP}}{449}
+\entry {\code {ASM{\_}OUTPUT{\_}REG{\_}PUSH}}{449}
+\entry {\code {ASM{\_}OUTPUT{\_}SECTION{\_}NAME}}{433}
+\entry {\code {ASM{\_}OUTPUT{\_}SHARED{\_}BSS}}{437}
+\entry {\code {ASM{\_}OUTPUT{\_}SHARED{\_}COMMON}}{436}
+\entry {\code {ASM{\_}OUTPUT{\_}SHARED{\_}LOCAL}}{438}
+\entry {\code {ASM{\_}OUTPUT{\_}SHORT}}{434}
+\entry {\code {ASM{\_}OUTPUT{\_}SKIP}}{451}
+\entry {\code {ASM{\_}OUTPUT{\_}SOURCE{\_}FILENAME}}{432}
+\entry {\code {ASM{\_}OUTPUT{\_}SOURCE{\_}LINE}}{433}
+\entry {\code {ASM{\_}OUTPUT{\_}SPECIAL{\_}POOL{\_}ENTRY}}{435}
+\entry {\code {ASM{\_}SPEC}}{354}
+\entry {\code {ASM{\_}STABD{\_}OP}}{453}
+\entry {\code {ASM{\_}STABN{\_}OP}}{453}
+\entry {\code {ASM{\_}STABS{\_}OP}}{452}
+\entry {\code {ASM{\_}WEAKEN{\_}LABEL}}{439}
+\entry {\code {assemble{\_}name}}{438}
+\entry {assembler format}{431}
+\entry {assembler instructions}{167}
+\entry {assembler instructions in RTL}{278}
+\entry {assembler names for identifiers}{171}
+\entry {assembler syntax, 88k}{65}
+\entry {\code {ASSEMBLER{\_}DIALECT}}{448}
+\entry {assembly code, invalid}{215}
+\entry {assigning attribute values to insns}{344}
+\entry {asterisk in template}{299}
+\entry {\code {atof}}{458}
+\entry {\code {attr}}{345}
+\entry {\code {attr{\_}flag}}{343}
+\entry {attribute expressions}{341}
+\entry {attribute of types}{162}
+\entry {attribute of variables}{159}
+\entry {attribute specifications}{346}
+\entry {attribute specifications example}{346}
+\entry {attributes, defining}{341}
+\entry {autoincrement addressing, availability}{235}
+\entry {autoincrement/decrement addressing}{301}
+\entry {autoincrement/decrement analysis}{242}
+\entry {automatic \code {inline} for C{\tt\char43}{\tt\char43} member fns}{166}
\initial {B}
-\entry {backslash}{280}
-\entry {backtrace for bug reports}{207}
-\entry {\code {barrier}}{263}
-\entry {\code {BASE{\_}REG{\_}CLASS}}{359}
-\entry {basic blocks}{227}
-\entry {\code {bcmp}}{440}
-\entry {\code {b\var {cond}} instruction pattern}{302}
-\entry {\code {bcopy}, implicit usage}{389}
-\entry {\code {BIGGEST{\_}ALIGNMENT}}{344}
-\entry {\code {BIGGEST{\_}FIELD{\_}ALIGNMENT}}{344}
-\entry {Bison parser generator}{94}
-\entry {bit fields}{253}
-\entry {bit shift overflow (88k)}{68}
-\entry {\code {BITFIELD{\_}NBYTES{\_}LIMITED}}{346}
-\entry {\code {BITS{\_}BIG{\_}ENDIAN}}{342}
-\entry {\code {BITS{\_}BIG{\_}ENDIAN}, effect on \code {sign{\_}extract}}{253}
-\entry {\code {BITS{\_}PER{\_}UNIT}}{343}
-\entry {\code {BITS{\_}PER{\_}WORD}}{343}
-\entry {bitwise complement}{250}
-\entry {bitwise exclusive-or}{250}
-\entry {bitwise inclusive-or}{250}
-\entry {bitwise logical-and}{250}
-\entry {\code {BLKmode}}{239}
-\entry {\code {BLKmode}, and function return values}{270}
-\entry {\code {BLOCK{\_}PROFILER}}{382}
-\entry {\code {BLOCK{\_}PROFILER{\_}CODE}}{382}
-\entry {\code {BRANCH{\_}COST}}{397}
-\entry {\code {break{\_}out{\_}memory{\_}refs}}{393}
-\entry {bug criteria}{203}
-\entry {bug report mailing lists}{204}
-\entry {bugs}{203}
-\entry {bugs, known}{179}
-\entry {builtin functions}{28}
-\entry {byte writes (29k)}{63}
-\entry {\code {byte{\_}mode}}{242}
-\entry {\code {BYTES{\_}BIG{\_}ENDIAN}}{342}
-\entry {\code {bzero}}{440}
-\entry {\code {bzero}, implicit usage}{389}
+\entry {backslash}{298}
+\entry {backtrace for bug reports}{219}
+\entry {\code {barrier}}{281}
+\entry {\code {BASE{\_}REG{\_}CLASS}}{380}
+\entry {basic blocks}{242}
+\entry {\code {bcmp}}{472}
+\entry {\code {b\var {cond}} instruction pattern}{321}
+\entry {\code {bcopy}, implicit usage}{416}
+\entry {\code {BIGGEST{\_}ALIGNMENT}}{364}
+\entry {\code {BIGGEST{\_}FIELD{\_}ALIGNMENT}}{364}
+\entry {Bison parser generator}{101}
+\entry {bit fields}{270}
+\entry {bit shift overflow (88k)}{66}
+\entry {\code {BITFIELD{\_}NBYTES{\_}LIMITED}}{367}
+\entry {\code {BITS{\_}BIG{\_}ENDIAN}}{362}
+\entry {\code {BITS{\_}BIG{\_}ENDIAN}, effect on \code {sign{\_}extract}}{270}
+\entry {\code {BITS{\_}PER{\_}UNIT}}{363}
+\entry {\code {BITS{\_}PER{\_}WORD}}{363}
+\entry {bitwise complement}{267}
+\entry {bitwise exclusive-or}{267}
+\entry {bitwise inclusive-or}{267}
+\entry {bitwise logical-and}{267}
+\entry {\code {BLKmode}}{255}
+\entry {\code {BLKmode}, and function return values}{288}
+\entry {\code {BLOCK{\_}PROFILER}}{407}
+\entry {\code {BLOCK{\_}PROFILER{\_}CODE}}{409}
+\entry {\code {BRANCH{\_}COST}}{426}
+\entry {\code {break{\_}out{\_}memory{\_}refs}}{420}
+\entry {\code {BSS{\_}SECTION{\_}ASM{\_}OP}}{428}
+\entry {bug criteria}{215}
+\entry {bug report mailing lists}{216}
+\entry {bugs}{215}
+\entry {bugs, known}{189}
+\entry {builtin functions}{18}
+\entry {byte writes (29k)}{60}
+\entry {\code {byte{\_}mode}}{258}
+\entry {\code {BYTES{\_}BIG{\_}ENDIAN}}{362}
+\entry {\code {bzero}}{472}
+\entry {\code {bzero}, implicit usage}{416}
\initial {C}
-\entry {C compilation options}{19}
-\entry {C intermediate output, nonexistent}{17}
-\entry {C language extensions}{125}
-\entry {C language, traditional}{28}
-\entry {C statements for assembler output}{281}
-\entry {\code {C{\_}INCLUDE{\_}PATH}}{87}
-\entry {\code {c{\tt\char43}{\tt\char43}}}{26}
-\entry {C{\tt\char43}{\tt\char43}}{17}
-\entry {C{\tt\char43}{\tt\char43} compilation options}{19}
-\entry {C{\tt\char43}{\tt\char43} interface and implementation headers}{172}
-\entry {C{\tt\char43}{\tt\char43} language extensions}{169}
-\entry {C{\tt\char43}{\tt\char43} member fns, automatically \code {inline}}{156}
-\entry {C{\tt\char43}{\tt\char43} misunderstandings}{196}
-\entry {C{\tt\char43}{\tt\char43} named return value}{169}
-\entry {C{\tt\char43}{\tt\char43} options, command line}{31}
-\entry {C{\tt\char43}{\tt\char43} pragmas, effect on inlining}{173}
-\entry {C{\tt\char43}{\tt\char43} signatures}{176}
-\entry {C{\tt\char43}{\tt\char43} source file suffixes}{26}
-\entry {C{\tt\char43}{\tt\char43} static data, declaring and defining}{196}
-\entry {C{\tt\char43}{\tt\char43} subtype polymorphism}{176}
-\entry {C{\tt\char43}{\tt\char43} type abstraction}{176}
-\entry {\code {call}}{256}
-\entry {\code {call} instruction pattern}{302}
-\entry {\code {call} usage}{269}
-\entry {call-clobbered register}{351}
-\entry {call-saved register}{351}
-\entry {call-used register}{351}
-\entry {\code {call{\_}insn}}{263}
-\entry {\code {call{\_}insn} and \samp {/u}}{236}
-\entry {\code {CALL{\_}INSN{\_}FUNCTION{\_}USAGE}}{263}
-\entry {\code {call{\_}pop} instruction pattern}{303}
-\entry {\code {CALL{\_}USED{\_}REGISTERS}}{351}
-\entry {\code {call{\_}used{\_}regs}}{352}
-\entry {\code {call{\_}value} instruction pattern}{303}
-\entry {\code {call{\_}value{\_}pop} instruction pattern}{303}
-\entry {\code {CALLER{\_}SAVE{\_}PROFITABLE}}{378}
-\entry {calling conventions}{364}
-\entry {calling functions in RTL}{269}
-\entry {\code {CAN{\_}DEBUG{\_}WITHOUT{\_}FP}}{342}
-\entry {\code {CAN{\_}ELIMINATE}}{368}
-\entry {canonicalization of instructions}{310}
-\entry {\code {CANONICALIZE{\_}COMPARISON}}{395}
-\entry {case labels in initializers}{141}
-\entry {case ranges}{143}
-\entry {case sensitivity and VMS}{219}
-\entry {\code {CASE{\_}DROPS{\_}THROUGH}}{430}
-\entry {\code {CASE{\_}VALUES{\_}THRESHOLD}}{430}
-\entry {\code {CASE{\_}VECTOR{\_}MODE}}{430}
-\entry {\code {CASE{\_}VECTOR{\_}PC{\_}RELATIVE}}{430}
-\entry {\code {casesi} instruction pattern}{304}
-\entry {cast to a union}{143}
-\entry {casts as lvalues}{133}
-\entry {\code {cc{\_}status}}{393}
-\entry {\code {CC{\_}STATUS{\_}MDEP}}{394}
-\entry {\code {CC{\_}STATUS{\_}MDEP{\_}INIT}}{394}
-\entry {\code {cc0}}{247}
-\entry {\code {cc0}, RTL sharing}{271}
-\entry {\code {cc0{\_}rtx}}{247}
-\entry {\code {CC1{\_}SPEC}}{336}
-\entry {\code {CC1PLUS{\_}SPEC}}{336}
-\entry {\code {CCmode}}{239}
-\entry {\code {CDImode}}{240}
-\entry {\code {change{\_}address}}{296}
-\entry {\code {CHAR{\_}TYPE{\_}SIZE}}{348}
-\entry {\code {CHECK{\_}FLOAT{\_}VALUE}}{347}
-\entry {\code {CHImode}}{240}
-\entry {class definitions, register}{357}
-\entry {class preference constraints}{288}
-\entry {\code {CLASS{\_}LIKELY{\_}SPILLED{\_}P}}{362}
-\entry {\code {CLASS{\_}MAX{\_}NREGS}}{362}
-\entry {classes of RTX codes}{233}
-\entry {\code {CLEAR{\_}INSN{\_}CACHE}}{387}
-\entry {\code {clobber}}{256}
-\entry {\code {cmp\var {m}} instruction pattern}{299}
-\entry {\code {cmpstr\var {m}} instruction pattern}{300}
-\entry {code generation conventions}{83}
-\entry {code generation RTL sequences}{315}
-\entry {code motion}{227}
-\entry {\code {code{\_}label}}{263}
-\entry {\code {code{\_}label} and \samp {/i}}{237}
-\entry {\code {CODE{\_}LABEL{\_}NUMBER}}{263}
-\entry {codes, RTL expression}{231}
-\entry {\code {COImode}}{240}
-\entry {\code {COLLECT{\_}EXPORT{\_}LIST}}{440}
-\entry {combiner pass}{246}
-\entry {command options}{19}
-\entry {common subexpression elimination}{227}
-\entry {\code {COMP{\_}TYPE{\_}ATTRIBUTES}}{435}
-\entry {\code {compare}}{248}
-\entry {\code {compare}, canonicalization of}{310}
-\entry {compilation in a separate directory}{111}
-\entry {compiler bugs, reporting}{205}
-\entry {compiler compared to C{\tt\char43}{\tt\char43} preprocessor}{17}
-\entry {compiler options, C{\tt\char43}{\tt\char43}}{31}
-\entry {compiler passes and files}{225}
-\entry {compiler version, specifying}{55}
-\entry {\code {COMPILER{\_}PATH}}{87}
-\entry {complement, bitwise}{250}
-\entry {complex numbers}{135}
-\entry {compound expressions as lvalues}{133}
-\entry {computed gotos}{127}
-\entry {computing the length of an insn}{328}
-\entry {\code {cond}}{252}
-\entry {\code {cond} and attributes}{323}
-\entry {condition code register}{247}
-\entry {condition code status}{393}
-\entry {condition codes}{251}
-\entry {conditional expressions as lvalues}{133}
-\entry {conditional expressions, extensions}{134}
-\entry {\code {CONDITIONAL{\_}REGISTER{\_}USAGE}}{352}
-\entry {conditions, in patterns}{274}
-\entry {configuration file}{437}
-\entry {configurations supported by GNU CC}{97}
-\entry {conflicting types}{195}
-\entry {\code {const} applied to function}{144}
-\entry {\code {const} function attribute}{145}
-\entry {\code {CONST{\_}CALL{\_}P}}{236}
-\entry {\code {CONST{\_}COSTS}}{396}
-\entry {\code {const{\_}double}}{242}
-\entry {\code {const{\_}double}, RTL sharing}{271}
-\entry {\code {CONST{\_}DOUBLE{\_}CHAIN}}{242}
-\entry {\code {CONST{\_}DOUBLE{\_}LOW}}{243}
-\entry {\code {CONST{\_}DOUBLE{\_}MEM}}{242}
-\entry {\code {CONST{\_}DOUBLE{\_}OK{\_}FOR{\_}LETTER{\_}P}}{363}
-\entry {\code {const{\_}int}}{242}
-\entry {\code {const{\_}int} and attribute tests}{323}
-\entry {\code {const{\_}int} and attributes}{322}
-\entry {\code {const{\_}int}, RTL sharing}{271}
-\entry {\code {CONST{\_}OK{\_}FOR{\_}LETTER{\_}P}}{363}
-\entry {\code {const{\_}string}}{243}
-\entry {\code {const{\_}string} and attributes}{323}
-\entry {\code {const{\_}true{\_}rtx}}{242}
-\entry {\code {const0{\_}rtx}}{242}
-\entry {\code {CONST0{\_}RTX}}{243}
-\entry {\code {const1{\_}rtx}}{242}
-\entry {\code {CONST1{\_}RTX}}{243}
-\entry {\code {const2{\_}rtx}}{242}
-\entry {\code {CONST2{\_}RTX}}{243}
-\entry {constant attributes}{330}
-\entry {constant folding}{225}
-\entry {constant folding and floating point}{429}
-\entry {constant propagation}{227}
-\entry {\code {CONSTANT{\_}ADDRESS{\_}P}}{391}
-\entry {\code {CONSTANT{\_}ALIGNMENT}}{345}
-\entry {\code {CONSTANT{\_}P}}{391}
-\entry {\code {CONSTANT{\_}POOL{\_}ADDRESS{\_}P}}{236}
-\entry {constants in constraints}{284}
-\entry {\code {constm1{\_}rtx}}{242}
-\entry {constraint modifier characters}{289}
-\entry {constraint, matching}{284}
-\entry {constraints}{283}
-\entry {constraints, machine specific}{290}
-\entry {constructing calls}{131}
-\entry {constructor expressions}{140}
-\entry {\code {constructor} function attribute}{147}
-\entry {constructors vs \code {goto}}{172}
-\entry {constructors, automatic calls}{122}
-\entry {constructors, output of}{411}
-\entry {contributors}{9}
-\entry {controlling register usage}{352}
-\entry {controlling the compilation driver}{335}
-\entry {conventions, run-time}{223}
-\entry {conversions}{253}
-\entry {Convex options}{62}
-\entry {\code {copy{\_}rtx{\_}if{\_}shared}}{271}
-\entry {core dump}{203}
-\entry {\code {cos}}{28}
-\entry {costs of instructions}{396}
-\entry {\code {COSTS{\_}N{\_}INSNS}}{396}
-\entry {\code {CPLUS{\_}INCLUDE{\_}PATH}}{87}
-\entry {\code {CPP{\_}PREDEFINES}}{340}
-\entry {\code {CPP{\_}SPEC}}{335}
-\entry {\code {CQImode}}{240}
-\entry {cross compilation and floating point}{427}
-\entry {cross compiling}{55}
-\entry {cross-compiler, installation}{112}
-\entry {cross-jumping}{229}
-\entry {\code {CSImode}}{240}
-\entry {\code {CTImode}}{240}
-\entry {\code {CUMULATIVE{\_}ARGS}}{373}
-\entry {\code {current{\_}function{\_}epilogue{\_}delay{\_}list}}{381}
-\entry {\code {current{\_}function{\_}outgoing{\_}args{\_}size}}{369}
-\entry {\code {current{\_}function{\_}pops{\_}args}}{380}
-\entry {\code {current{\_}function{\_}pretend{\_}args{\_}size}}{379}
+\entry {C compilation options}{9}
+\entry {C intermediate output, nonexistent}{7}
+\entry {C language extensions}{135}
+\entry {C language, traditional}{18}
+\entry {C statements for assembler output}{299}
+\entry {\code {C{\_}INCLUDE{\_}PATH}}{93}
+\entry {\code {c{\tt\char43}{\tt\char43}}}{16}
+\entry {C{\tt\char43}{\tt\char43}}{7}
+\entry {C{\tt\char43}{\tt\char43} comments}{158}
+\entry {C{\tt\char43}{\tt\char43} compilation options}{9}
+\entry {C{\tt\char43}{\tt\char43} interface and implementation headers}{181}
+\entry {C{\tt\char43}{\tt\char43} language extensions}{179}
+\entry {C{\tt\char43}{\tt\char43} member fns, automatically \code {inline}}{166}
+\entry {C{\tt\char43}{\tt\char43} misunderstandings}{208}
+\entry {C{\tt\char43}{\tt\char43} named return value}{179}
+\entry {C{\tt\char43}{\tt\char43} options, command line}{21}
+\entry {C{\tt\char43}{\tt\char43} pragmas, effect on inlining}{183}
+\entry {C{\tt\char43}{\tt\char43} signatures}{186}
+\entry {C{\tt\char43}{\tt\char43} source file suffixes}{16}
+\entry {C{\tt\char43}{\tt\char43} static data, declaring and defining}{208}
+\entry {C{\tt\char43}{\tt\char43} subtype polymorphism}{186}
+\entry {C{\tt\char43}{\tt\char43} type abstraction}{186}
+\entry {\code {call}}{273}
+\entry {\code {call} instruction pattern}{322}
+\entry {\code {call} usage}{287}
+\entry {call-clobbered register}{372}
+\entry {call-saved register}{372}
+\entry {call-used register}{372}
+\entry {\code {call{\_}insn}}{280}
+\entry {\code {call{\_}insn} and \samp {/u}}{252}
+\entry {\code {CALL{\_}INSN{\_}FUNCTION{\_}USAGE}}{280}
+\entry {\code {call{\_}pop} instruction pattern}{322}
+\entry {\code {CALL{\_}USED{\_}REGISTERS}}{372}
+\entry {\code {call{\_}used{\_}regs}}{373}
+\entry {\code {call{\_}value} instruction pattern}{322}
+\entry {\code {call{\_}value{\_}pop} instruction pattern}{322}
+\entry {\code {CALLER{\_}SAVE{\_}PROFITABLE}}{401}
+\entry {calling conventions}{386}
+\entry {calling functions in RTL}{287}
+\entry {calling functions through the function vector on the H8/300 processors}{156}
+\entry {\code {CAN{\_}DEBUG{\_}WITHOUT{\_}FP}}{361}
+\entry {\code {CAN{\_}ELIMINATE}}{391}
+\entry {canonicalization of instructions}{330}
+\entry {\code {CANONICALIZE{\_}COMPARISON}}{423}
+\entry {\code {canonicalize{\_}funcptr{\_}for{\_}compare} instruction pattern}{325}
+\entry {case labels in initializers}{149}
+\entry {case ranges}{150}
+\entry {case sensitivity and VMS}{232}
+\entry {\code {CASE{\_}DROPS{\_}THROUGH}}{461}
+\entry {\code {CASE{\_}VALUES{\_}THRESHOLD}}{461}
+\entry {\code {CASE{\_}VECTOR{\_}MODE}}{461}
+\entry {\code {CASE{\_}VECTOR{\_}PC{\_}RELATIVE}}{461}
+\entry {\code {casesi} instruction pattern}{324}
+\entry {cast to a union}{151}
+\entry {casts as lvalues}{142}
+\entry {\code {CC}}{475}
+\entry {\code {cc{\_}status}}{421}
+\entry {\code {CC{\_}STATUS{\_}MDEP}}{421}
+\entry {\code {CC{\_}STATUS{\_}MDEP{\_}INIT}}{422}
+\entry {\code {cc0}}{263}
+\entry {\code {cc0}, RTL sharing}{289}
+\entry {\code {cc0{\_}rtx}}{264}
+\entry {\code {CC1{\_}SPEC}}{354}
+\entry {\code {CC1PLUS{\_}SPEC}}{354}
+\entry {\code {CCmode}}{255}
+\entry {\code {CDImode}}{256}
+\entry {\code {change{\_}address}}{315}
+\entry {\code {CHAR{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {CHECK{\_}FLOAT{\_}VALUE}}{368}
+\entry {\code {CHImode}}{256}
+\entry {class definitions, register}{378}
+\entry {class preference constraints}{306}
+\entry {\code {CLASS{\_}LIKELY{\_}SPILLED{\_}P}}{384}
+\entry {\code {CLASS{\_}MAX{\_}NREGS}}{385}
+\entry {classes of RTX codes}{249}
+\entry {\code {CLEAR{\_}INSN{\_}CACHE}}{414}
+\entry {\code {CLIB}}{475}
+\entry {\code {clobber}}{273}
+\entry {\code {clrstr\var {m}} instruction pattern}{319}
+\entry {\code {cmp\var {m}} instruction pattern}{318}
+\entry {\code {cmpstr\var {m}} instruction pattern}{319}
+\entry {code generation conventions}{88}
+\entry {code generation RTL sequences}{335}
+\entry {code motion}{241}
+\entry {\code {code{\_}label}}{281}
+\entry {\code {code{\_}label} and \samp {/i}}{252}
+\entry {\code {CODE{\_}LABEL{\_}NUMBER}}{281}
+\entry {codes, RTL expression}{247}
+\entry {\code {COImode}}{256}
+\entry {\code {COLLECT{\_}EXPORT{\_}LIST}}{472}
+\entry {combiner pass}{263}
+\entry {command options}{9}
+\entry {comments, C{\tt\char43}{\tt\char43} style}{158}
+\entry {common subexpression elimination}{241}
+\entry {\code {COMP{\_}TYPE{\_}ATTRIBUTES}}{466}
+\entry {\code {compare}}{265}
+\entry {\code {compare}, canonicalization of}{331}
+\entry {comparison of signed and unsigned values, warning}{29}
+\entry {compilation in a separate directory}{121}
+\entry {compiler bugs, reporting}{217}
+\entry {compiler compared to C{\tt\char43}{\tt\char43} preprocessor}{7}
+\entry {compiler options, C{\tt\char43}{\tt\char43}}{21}
+\entry {compiler passes and files}{239}
+\entry {compiler version, specifying}{51}
+\entry {\code {COMPILER{\_}PATH}}{93}
+\entry {complement, bitwise}{267}
+\entry {complex numbers}{144}
+\entry {compound expressions as lvalues}{142}
+\entry {computed gotos}{137}
+\entry {computing the length of an insn}{347}
+\entry {\code {cond}}{269}
+\entry {\code {cond} and attributes}{342}
+\entry {condition code register}{263}
+\entry {condition code status}{421}
+\entry {condition codes}{268}
+\entry {conditional expressions as lvalues}{142}
+\entry {conditional expressions, extensions}{143}
+\entry {\code {CONDITIONAL{\_}REGISTER{\_}USAGE}}{373}
+\entry {conditions, in patterns}{291}
+\entry {configuration file}{469}
+\entry {configurations supported by GNU CC}{104}
+\entry {conflicting types}{206}
+\entry {\code {const} applied to function}{151}
+\entry {\code {const} function attribute}{152}
+\entry {\code {CONST{\_}CALL{\_}P}}{252}
+\entry {\code {CONST{\_}COSTS}}{424}
+\entry {\code {const{\_}double}}{258}
+\entry {\code {const{\_}double}, RTL sharing}{289}
+\entry {\code {CONST{\_}DOUBLE{\_}CHAIN}}{259}
+\entry {\code {CONST{\_}DOUBLE{\_}LOW}}{259}
+\entry {\code {CONST{\_}DOUBLE{\_}MEM}}{259}
+\entry {\code {CONST{\_}DOUBLE{\_}OK{\_}FOR{\_}LETTER{\_}P}}{385}
+\entry {\code {const{\_}int}}{258}
+\entry {\code {const{\_}int} and attribute tests}{342}
+\entry {\code {const{\_}int} and attributes}{341}
+\entry {\code {const{\_}int}, RTL sharing}{289}
+\entry {\code {CONST{\_}OK{\_}FOR{\_}LETTER{\_}P}}{385}
+\entry {\code {const{\_}string}}{259}
+\entry {\code {const{\_}string} and attributes}{342}
+\entry {\code {const{\_}true{\_}rtx}}{258}
+\entry {\code {const0{\_}rtx}}{258}
+\entry {\code {CONST0{\_}RTX}}{259}
+\entry {\code {const1{\_}rtx}}{258}
+\entry {\code {CONST1{\_}RTX}}{259}
+\entry {\code {const2{\_}rtx}}{258}
+\entry {\code {CONST2{\_}RTX}}{259}
+\entry {constant attributes}{348}
+\entry {constant folding}{239}
+\entry {constant folding and floating point}{460}
+\entry {constant propagation}{241}
+\entry {\code {CONSTANT{\_}ADDRESS{\_}P}}{418}
+\entry {\code {CONSTANT{\_}ALIGNMENT}}{365}
+\entry {\code {CONSTANT{\_}P}}{418}
+\entry {\code {CONSTANT{\_}POOL{\_}ADDRESS{\_}P}}{252}
+\entry {constants in constraints}{302}
+\entry {\code {constm1{\_}rtx}}{258}
+\entry {constraint modifier characters}{307}
+\entry {constraint, matching}{303}
+\entry {constraints}{301}
+\entry {constraints, machine specific}{308}
+\entry {constructing calls}{140}
+\entry {constructor expressions}{148}
+\entry {\code {constructor} function attribute}{154}
+\entry {constructors vs \code {goto}}{181}
+\entry {constructors, automatic calls}{132}
+\entry {constructors, output of}{442}
+\entry {contributors}{485}
+\entry {controlling register usage}{373}
+\entry {controlling the compilation driver}{353}
+\entry {conventions, run-time}{237}
+\entry {conversions}{270}
+\entry {Convex options}{59}
+\entry {\code {copy{\_}rtx{\_}if{\_}shared}}{289}
+\entry {core dump}{215}
+\entry {\code {cos}}{18}
+\entry {costs of instructions}{424}
+\entry {\code {COSTS{\_}N{\_}INSNS}}{424}
+\entry {\code {CPLUS{\_}INCLUDE{\_}PATH}}{93}
+\entry {\code {CPP{\_}PREDEFINES}}{359}
+\entry {\code {CPP{\_}SPEC}}{353}
+\entry {\code {CQImode}}{256}
+\entry {cross compilation and floating point}{458}
+\entry {cross compiling}{51}
+\entry {cross-compiler, installation}{122}
+\entry {cross-jumping}{243}
+\entry {\code {CROSS{\_}LIBGCC1}}{473}
+\entry {\code {CRTSTUFF{\_}T{\_}CFLAGS}}{473}
+\entry {\code {CRTSTUFF{\_}T{\_}CFLAGS{\_}S}}{473}
+\entry {\code {CSImode}}{256}
+\entry {\code {CTImode}}{256}
+\entry {\code {CUMULATIVE{\_}ARGS}}{396}
+\entry {\code {current{\_}function{\_}epilogue{\_}delay{\_}list}}{404}
+\entry {\code {current{\_}function{\_}outgoing{\_}args{\_}size}}{392}
+\entry {\code {current{\_}function{\_}pops{\_}args}}{404}
+\entry {\code {current{\_}function{\_}pretend{\_}args{\_}size}}{402}
\initial {D}
-\entry {\samp {d} in constraint}{283}
-\entry {data flow analysis}{227}
-\entry {\code {DATA{\_}ALIGNMENT}}{345}
-\entry {\code {data{\_}section}}{400}
-\entry {\code {DATA{\_}SECTION{\_}ASM{\_}OP}}{399}
-\entry {\code {DBR{\_}OUTPUT{\_}SEQEND}}{417}
-\entry {\code {dbr{\_}sequence{\_}length}}{417}
-\entry {DBX}{185}
-\entry {\code {DBX{\_}BLOCKS{\_}FUNCTION{\_}RELATIVE}}{424}
-\entry {\code {DBX{\_}CONTIN{\_}CHAR}}{423}
-\entry {\code {DBX{\_}CONTIN{\_}LENGTH}}{423}
-\entry {\code {DBX{\_}DEBUGGING{\_}INFO}}{422}
-\entry {\code {DBX{\_}FUNCTION{\_}FIRST}}{423}
-\entry {\code {DBX{\_}LBRAC{\_}FIRST}}{424}
-\entry {\code {DBX{\_}MEMPARM{\_}STABS{\_}LETTER}}{423}
-\entry {\code {DBX{\_}NO{\_}XREFS}}{422}
-\entry {\code {DBX{\_}OUTPUT{\_}ENUM}}{424}
-\entry {\code {DBX{\_}OUTPUT{\_}FUNCTION{\_}END}}{424}
-\entry {\code {DBX{\_}OUTPUT{\_}LBRAC}}{424}
-\entry {\code {DBX{\_}OUTPUT{\_}MAIN{\_}SOURCE{\_}DIRECTORY}}{426}
-\entry {\code {DBX{\_}OUTPUT{\_}MAIN{\_}SOURCE{\_}FILE{\_}END}}{426}
-\entry {\code {DBX{\_}OUTPUT{\_}MAIN{\_}SOURCE{\_}FILENAME}}{426}
-\entry {\code {DBX{\_}OUTPUT{\_}RBRAC}}{424}
-\entry {\code {DBX{\_}OUTPUT{\_}SOURCE{\_}FILENAME}}{426}
-\entry {\code {DBX{\_}OUTPUT{\_}STANDARD{\_}TYPES}}{424}
-\entry {\code {DBX{\_}REGISTER{\_}NUMBER}}{421}
-\entry {\code {DBX{\_}REGPARM{\_}STABS{\_}CODE}}{423}
-\entry {\code {DBX{\_}REGPARM{\_}STABS{\_}LETTER}}{423}
-\entry {\code {DBX{\_}STATIC{\_}CONST{\_}VAR{\_}CODE}}{423}
-\entry {\code {DBX{\_}STATIC{\_}STAB{\_}DATA{\_}SECTION}}{423}
-\entry {\code {DBX{\_}TYPE{\_}DECL{\_}STABS{\_}CODE}}{423}
-\entry {\code {DBX{\_}WORKING{\_}DIRECTORY}}{425}
-\entry {\code {DCmode}}{239}
-\entry {De Morgan's law}{311}
-\entry {dead code}{226}
-\entry {\code {dead{\_}or{\_}set{\_}p}}{313}
-\entry {deallocating variable length arrays}{137}
-\entry {death notes}{357}
-\entry {\code {debug{\_}rtx}}{208}
-\entry {\code {DEBUG{\_}SYMS{\_}TEXT}}{422}
-\entry {\code {DEBUGGER{\_}ARG{\_}OFFSET}}{421}
-\entry {\code {DEBUGGER{\_}AUTO{\_}OFFSET}}{421}
-\entry {debugging information generation}{229}
-\entry {debugging information options}{41}
-\entry {debugging, 88k OCS}{65}
-\entry {declaration scope}{191}
-\entry {declarations inside expressions}{125}
-\entry {declarations, RTL}{254}
-\entry {declaring attributes of functions}{144}
-\entry {declaring static data in C{\tt\char43}{\tt\char43}}{196}
-\entry {default implementation, signature member function}{177}
-\entry {\code {DEFAULT{\_}CALLER{\_}SAVES}}{378}
-\entry {\code {DEFAULT{\_}GDB{\_}EXTENSIONS}}{422}
-\entry {\code {DEFAULT{\_}MAIN{\_}RETURN}}{435}
-\entry {\code {DEFAULT{\_}PCC{\_}STRUCT{\_}RETURN}}{376}
-\entry {\code {DEFAULT{\_}SHORT{\_}ENUMS}}{349}
-\entry {\code {DEFAULT{\_}SIGNED{\_}CHAR}}{349}
-\entry {\code {define{\_}asm{\_}attributes}}{327}
-\entry {\code {define{\_}attr}}{321}
-\entry {\code {define{\_}delay}}{331}
-\entry {\code {define{\_}expand}}{315}
-\entry {\code {define{\_}function{\_}unit}}{332}
-\entry {\code {define{\_}insn}}{273}
-\entry {\code {define{\_}insn} example}{274}
-\entry {\code {define{\_}peephole}}{315}
-\entry {define{\_}split}{318}
-\entry {defining attributes and their values}{321}
-\entry {defining jump instruction patterns}{308}
-\entry {defining peephole optimizers}{311}
-\entry {defining RTL sequences for code generation}{315}
-\entry {defining static data in C{\tt\char43}{\tt\char43}}{196}
-\entry {delay slots, defining}{330}
-\entry {\code {DELAY{\_}SLOTS{\_}FOR{\_}EPILOGUE}}{380}
-\entry {delayed branch scheduling}{229}
-\entry {dependencies for make as output}{87}
-\entry {dependencies, make}{51}
-\entry {\code {DEPENDENCIES{\_}OUTPUT}}{87}
-\entry {Dependent Patterns}{306}
-\entry {\code {destructor} function attribute}{147}
-\entry {destructors vs \code {goto}}{172}
-\entry {destructors, output of}{411}
-\entry {detecting \w {\samp {-traditional}}}{29}
-\entry {\code {DFmode}}{239}
-\entry {dialect options}{27}
-\entry {digits in constraint}{284}
-\entry {\code {DImode}}{239}
-\entry {\code {DIR{\_}SEPARATOR}}{439}
-\entry {directory options}{54}
-\entry {disabling certain registers}{352}
-\entry {dispatch table}{419}
-\entry {\code {div}}{249}
-\entry {\code {div} and attributes}{323}
-\entry {\code {DIVDI3{\_}LIBCALL}}{388}
-\entry {divide instruction, 88k}{67}
-\entry {division}{249}
-\entry {\code {div\var {m}3} instruction pattern}{298}
-\entry {\code {divmod\var {m}4} instruction pattern}{298}
-\entry {\code {DIVSI3{\_}LIBCALL}}{387}
-\entry {dollar signs in identifier names}{149}
-\entry {\code {DOLLARS{\_}IN{\_}IDENTIFIERS}}{435}
-\entry {\code {DONE}}{316}
-\entry {\code {DONT{\_}DECLARE{\_}SYS{\_}SIGLIST}}{438}
-\entry {\code {DONT{\_}REDUCE{\_}ADDR}}{398}
-\entry {double-word arithmetic}{135}
-\entry {\code {DOUBLE{\_}TYPE{\_}SIZE}}{349}
-\entry {downward funargs}{128}
-\entry {driver}{335}
-\entry {DW bit (29k)}{63}
-\entry {\code {DWARF{\_}DEBUGGING{\_}INFO}}{426}
-\entry {\code {DYNAMIC{\_}CHAIN{\_}ADDRESS}}{365}
+\entry {\samp {d} in constraint}{301}
+\entry {data flow analysis}{242}
+\entry {\code {DATA{\_}ALIGNMENT}}{365}
+\entry {\code {data{\_}section}}{429}
+\entry {\code {DATA{\_}SECTION{\_}ASM{\_}OP}}{428}
+\entry {\code {DBR{\_}OUTPUT{\_}SEQEND}}{448}
+\entry {\code {dbr{\_}sequence{\_}length}}{448}
+\entry {DBX}{196}
+\entry {\code {DBX{\_}BLOCKS{\_}FUNCTION{\_}RELATIVE}}{454}
+\entry {\code {DBX{\_}CONTIN{\_}CHAR}}{453}
+\entry {\code {DBX{\_}CONTIN{\_}LENGTH}}{453}
+\entry {\code {DBX{\_}DEBUGGING{\_}INFO}}{452}
+\entry {\code {DBX{\_}FUNCTION{\_}FIRST}}{454}
+\entry {\code {DBX{\_}LBRAC{\_}FIRST}}{454}
+\entry {\code {DBX{\_}MEMPARM{\_}STABS{\_}LETTER}}{454}
+\entry {\code {DBX{\_}NO{\_}XREFS}}{453}
+\entry {\code {DBX{\_}OUTPUT{\_}ENUM}}{455}
+\entry {\code {DBX{\_}OUTPUT{\_}FUNCTION{\_}END}}{455}
+\entry {\code {DBX{\_}OUTPUT{\_}LBRAC}}{455}
+\entry {\code {DBX{\_}OUTPUT{\_}MAIN{\_}SOURCE{\_}DIRECTORY}}{456}
+\entry {\code {DBX{\_}OUTPUT{\_}MAIN{\_}SOURCE{\_}FILE{\_}END}}{457}
+\entry {\code {DBX{\_}OUTPUT{\_}MAIN{\_}SOURCE{\_}FILENAME}}{456}
+\entry {\code {DBX{\_}OUTPUT{\_}RBRAC}}{455}
+\entry {\code {DBX{\_}OUTPUT{\_}SOURCE{\_}FILENAME}}{457}
+\entry {\code {DBX{\_}OUTPUT{\_}STANDARD{\_}TYPES}}{455}
+\entry {\code {DBX{\_}REGISTER{\_}NUMBER}}{451}
+\entry {\code {DBX{\_}REGPARM{\_}STABS{\_}CODE}}{454}
+\entry {\code {DBX{\_}REGPARM{\_}STABS{\_}LETTER}}{454}
+\entry {\code {DBX{\_}STATIC{\_}CONST{\_}VAR{\_}CODE}}{454}
+\entry {\code {DBX{\_}STATIC{\_}STAB{\_}DATA{\_}SECTION}}{453}
+\entry {\code {DBX{\_}TYPE{\_}DECL{\_}STABS{\_}CODE}}{453}
+\entry {\code {DBX{\_}USE{\_}BINCL}}{454}
+\entry {\code {DBX{\_}WORKING{\_}DIRECTORY}}{456}
+\entry {\code {DCmode}}{256}
+\entry {De Morgan's law}{331}
+\entry {dead code}{241}
+\entry {\code {dead{\_}or{\_}set{\_}p}}{333}
+\entry {deallocating variable length arrays}{145}
+\entry {death notes}{378}
+\entry {\code {debug{\_}rtx}}{220}
+\entry {\code {DEBUG{\_}SYMS{\_}TEXT}}{452}
+\entry {\code {DEBUGGER{\_}ARG{\_}OFFSET}}{452}
+\entry {\code {DEBUGGER{\_}AUTO{\_}OFFSET}}{451}
+\entry {debugging information generation}{244}
+\entry {debugging information options}{33}
+\entry {debugging, 88k OCS}{63}
+\entry {declaration scope}{203}
+\entry {declarations inside expressions}{135}
+\entry {declarations, RTL}{272}
+\entry {declaring attributes of functions}{151}
+\entry {declaring static data in C{\tt\char43}{\tt\char43}}{208}
+\entry {default implementation, signature member function}{187}
+\entry {\code {DEFAULT{\_}CALLER{\_}SAVES}}{401}
+\entry {\code {DEFAULT{\_}GDB{\_}EXTENSIONS}}{452}
+\entry {\code {DEFAULT{\_}MAIN{\_}RETURN}}{467}
+\entry {\code {DEFAULT{\_}PCC{\_}STRUCT{\_}RETURN}}{400}
+\entry {\code {DEFAULT{\_}SHORT{\_}ENUMS}}{370}
+\entry {\code {DEFAULT{\_}SIGNED{\_}CHAR}}{370}
+\entry {\code {define{\_}asm{\_}attributes}}{346}
+\entry {\code {define{\_}attr}}{341}
+\entry {\code {define{\_}delay}}{349}
+\entry {\code {define{\_}expand}}{335}
+\entry {\code {define{\_}function{\_}unit}}{351}
+\entry {\code {define{\_}insn}}{291}
+\entry {\code {define{\_}insn} example}{292}
+\entry {\code {define{\_}peephole}}{335}
+\entry {define{\_}split}{338}
+\entry {defining attributes and their values}{341}
+\entry {defining jump instruction patterns}{328}
+\entry {defining peephole optimizers}{332}
+\entry {defining RTL sequences for code generation}{335}
+\entry {defining static data in C{\tt\char43}{\tt\char43}}{208}
+\entry {delay slots, defining}{349}
+\entry {\code {DELAY{\_}SLOTS{\_}FOR{\_}EPILOGUE}}{404}
+\entry {delayed branch scheduling}{243}
+\entry {dependencies for make as output}{94}
+\entry {dependencies, make}{46}
+\entry {\code {DEPENDENCIES{\_}OUTPUT}}{94}
+\entry {Dependent Patterns}{327}
+\entry {\code {destructor} function attribute}{154}
+\entry {destructors vs \code {goto}}{181}
+\entry {destructors, output of}{442}
+\entry {detecting \w {\samp {-traditional}}}{19}
+\entry {\code {DFmode}}{255}
+\entry {dialect options}{17}
+\entry {digits in constraint}{303}
+\entry {\code {DImode}}{255}
+\entry {\code {DIR{\_}SEPARATOR}}{472}
+\entry {directory options}{50}
+\entry {disabling certain registers}{373}
+\entry {dispatch table}{449}
+\entry {\code {div}}{266}
+\entry {\code {div} and attributes}{342}
+\entry {\code {DIVDI3{\_}LIBCALL}}{415}
+\entry {divide instruction, 88k}{65}
+\entry {division}{266}
+\entry {\code {div\var {m}3} instruction pattern}{317}
+\entry {\code {divmod\var {m}4} instruction pattern}{317}
+\entry {\code {DIVSI3{\_}LIBCALL}}{415}
+\entry {dollar signs in identifier names}{158}
+\entry {\code {DOLLARS{\_}IN{\_}IDENTIFIERS}}{466}
+\entry {\code {DONE}}{336}
+\entry {\code {DONT{\_}DECLARE{\_}SYS{\_}SIGLIST}}{471}
+\entry {\code {DONT{\_}REDUCE{\_}ADDR}}{427}
+\entry {double-word arithmetic}{144}
+\entry {\code {DOUBLE{\_}TYPE{\_}SIZE}}{369}
+\entry {downward funargs}{137}
+\entry {driver}{353}
+\entry {DW bit (29k)}{60}
+\entry {\code {DWARF{\_}DEBUGGING{\_}INFO}}{457}
+\entry {\code {DYNAMIC{\_}CHAIN{\_}ADDRESS}}{387}
\initial {E}
-\entry {\samp {E} in constraint}{284}
-\entry {\code {EASY{\_}DIV{\_}EXPR}}{431}
-\entry {\code {EDOM}, implicit usage}{389}
-\entry {\code {ELIGIBLE{\_}FOR{\_}EPILOGUE{\_}DELAY}}{380}
-\entry {\code {ELIMINABLE{\_}REGS}}{368}
-\entry {empty constraints}{295}
-\entry {\code {EMPTY{\_}FIELD{\_}BOUNDARY}}{345}
-\entry {\code {ENCODE{\_}SECTION{\_}INFO}}{401}
-\entry {\code {ENCODE{\_}SECTION{\_}INFO} and address validation}{392}
-\entry {\code {ENCODE{\_}SECTION{\_}INFO} usage}{417}
-\entry {\code {ENDFILE{\_}SPEC}}{337}
-\entry {endianness}{221}
-\entry {\code {enum machine{\_}mode}}{238}
-\entry {\code {enum reg{\_}class}}{358}
-\entry {enumeration clash warnings}{37}
-\entry {environment variables}{86}
-\entry {epilogue}{378}
-\entry {\code {eq}}{252}
-\entry {\code {eq} and attributes}{323}
-\entry {\code {eq{\_}attr}}{324}
-\entry {equal}{252}
-\entry {\code {errno}, implicit usage}{389}
-\entry {error messages}{202}
-\entry {escape sequences, traditional}{28}
-\entry {exclamation point}{288}
-\entry {exclusive-or, bitwise}{250}
-\entry {\code {EXECUTABLE{\_}SUFFIX}}{439}
-\entry {\code {exit}}{28}
-\entry {exit status and VMS}{219}
-\entry {\code {EXIT{\_}BODY}}{436}
-\entry {\code {EXIT{\_}IGNORE{\_}STACK}}{379}
-\entry {\code {EXPAND{\_}BUILTIN{\_}SAVEREGS}}{384}
-\entry {expander definitions}{315}
-\entry {explicit register variables}{162}
-\entry {\code {expr{\_}list}}{269}
-\entry {expression codes}{231}
-\entry {expressions containing statements}{125}
-\entry {expressions, compound, as lvalues}{133}
-\entry {expressions, conditional, as lvalues}{133}
-\entry {expressions, constructor}{140}
-\entry {extended \code {asm}}{157}
-\entry {\code {extend\var {mn}} instruction pattern}{301}
-\entry {extensible constraints}{285}
-\entry {extensions, \code {?:}}{133, 134}
-\entry {extensions, C language}{125}
-\entry {extensions, C{\tt\char43}{\tt\char43} language}{169}
-\entry {\code {extern int target{\_}flags}}{340}
-\entry {external declaration scope}{191}
-\entry {\code {EXTRA{\_}CC{\_}MODES}}{395}
-\entry {\code {EXTRA{\_}CC{\_}NAMES}}{395}
-\entry {\code {EXTRA{\_}CONSTRAINT}}{363}
-\entry {\code {EXTRA{\_}SECTION{\_}FUNCTIONS}}{400}
-\entry {\code {EXTRA{\_}SECTIONS}}{400}
-\entry {\code {extv} instruction pattern}{301}
-\entry {\code {extzv} instruction pattern}{301}
+\entry {\samp {E} in constraint}{302}
+\entry {earlyclobber operand}{307}
+\entry {\code {EASY{\_}DIV{\_}EXPR}}{462}
+\entry {\code {EDOM}, implicit usage}{416}
+\entry {\code {ELIGIBLE{\_}FOR{\_}EPILOGUE{\_}DELAY}}{404}
+\entry {\code {ELIMINABLE{\_}REGS}}{390}
+\entry {empty constraints}{314}
+\entry {\code {EMPTY{\_}FIELD{\_}BOUNDARY}}{365}
+\entry {\code {ENCODE{\_}SECTION{\_}INFO}}{429}
+\entry {\code {ENCODE{\_}SECTION{\_}INFO} and address validation}{419}
+\entry {\code {ENCODE{\_}SECTION{\_}INFO} usage}{448}
+\entry {\code {ENDFILE{\_}SPEC}}{355}
+\entry {endianness}{235}
+\entry {\code {enum machine{\_}mode}}{254}
+\entry {\code {enum reg{\_}class}}{379}
+\entry {environment variables}{92}
+\entry {epilogue}{401}
+\entry {\code {eq}}{269}
+\entry {\code {eq} and attributes}{342}
+\entry {\code {eq{\_}attr}}{343}
+\entry {equal}{269}
+\entry {\code {errno}, implicit usage}{416}
+\entry {error messages}{214}
+\entry {escape sequences, traditional}{19}
+\entry {exclamation point}{306}
+\entry {exclusive-or, bitwise}{267}
+\entry {\code {EXECUTABLE{\_}SUFFIX}}{472}
+\entry {\code {exit}}{18}
+\entry {exit status and VMS}{232}
+\entry {\code {EXIT{\_}BODY}}{467}
+\entry {\code {EXIT{\_}IGNORE{\_}STACK}}{403}
+\entry {\code {EXPAND{\_}BUILTIN{\_}SAVEREGS}}{410}
+\entry {expander definitions}{335}
+\entry {explicit register variables}{172}
+\entry {\code {expr{\_}list}}{287}
+\entry {expression codes}{247}
+\entry {expressions containing statements}{135}
+\entry {expressions, compound, as lvalues}{142}
+\entry {expressions, conditional, as lvalues}{142}
+\entry {expressions, constructor}{148}
+\entry {extended \code {asm}}{167}
+\entry {\code {extend\var {mn}} instruction pattern}{320}
+\entry {extensible constraints}{303}
+\entry {extensions, \code {?:}}{142, 143}
+\entry {extensions, C language}{135}
+\entry {extensions, C{\tt\char43}{\tt\char43} language}{179}
+\entry {\code {extern int target{\_}flags}}{359}
+\entry {external declaration scope}{203}
+\entry {\code {EXTRA{\_}CC{\_}MODES}}{422}
+\entry {\code {EXTRA{\_}CC{\_}NAMES}}{423}
+\entry {\code {EXTRA{\_}CONSTRAINT}}{386}
+\entry {\code {EXTRA{\_}SECTION{\_}FUNCTIONS}}{429}
+\entry {\code {EXTRA{\_}SECTIONS}}{428}
+\entry {\code {EXTRA{\_}SPECS}}{355}
+\entry {\code {extv} instruction pattern}{320}
+\entry {\code {extzv} instruction pattern}{320}
\initial {F}
-\entry {\samp {F} in constraint}{284}
-\entry {\code {fabs}}{28}
-\entry {\code {FAIL}}{316}
-\entry {fatal signal}{203}
-\entry {\code {FATAL{\_}EXIT{\_}CODE}}{437}
-\entry {features, optional, in system conventions}{340}
-\entry {\code {ffs}}{28, 251}
-\entry {\code {ffs\var {m}2} instruction pattern}{299}
-\entry {file name suffix}{24}
-\entry {file names}{52}
-\entry {files and passes of the compiler}{225}
-\entry {final pass}{229}
-\entry {\code {FINAL{\_}PRESCAN{\_}INSN}}{416}
-\entry {\code {FINAL{\_}REG{\_}PARM{\_}STACK{\_}SPACE}}{370}
-\entry {\code {final{\_}scan{\_}insn}}{381}
-\entry {\code {final{\_}sequence}}{417}
-\entry {\code {FINALIZE{\_}PIC}}{402}
-\entry {\code {FIRST{\_}INSN{\_}ADDRESS}}{329}
-\entry {\code {FIRST{\_}PARM{\_}OFFSET}}{365}
-\entry {\code {FIRST{\_}PARM{\_}OFFSET} and virtual registers}{245}
-\entry {\code {FIRST{\_}PSEUDO{\_}REGISTER}}{351}
-\entry {\code {FIRST{\_}STACK{\_}REG}}{356}
-\entry {\code {FIRST{\_}VIRTUAL{\_}REGISTER}}{245}
-\entry {\code {fix}}{254}
-\entry {\code {fix{\_}trunc\var {mn}2} instruction pattern}{300}
-\entry {fixed register}{351}
-\entry {\code {FIXED{\_}REGISTERS}}{351}
-\entry {\code {fixed{\_}regs}}{352}
-\entry {\code {fix\var {mn}2} instruction pattern}{300}
-\entry {\code {FIXUNS{\_}TRUNC{\_}LIKE{\_}FIX{\_}TRUNC}}{431}
-\entry {\code {fixuns{\_}trunc\var {mn}2} instruction pattern}{300}
-\entry {\code {fixuns\var {mn}2} instruction pattern}{300}
-\entry {flags in RTL expression}{235}
-\entry {\code {float}}{254}
-\entry {\code {float} as function value type}{192}
-\entry {\code {FLOAT{\_}ARG{\_}TYPE}}{389}
-\entry {\code {float{\_}extend}}{254}
-\entry {\code {FLOAT{\_}STORE{\_}FLAG{\_}VALUE}}{433}
-\entry {\code {float{\_}truncate}}{254}
-\entry {\code {FLOAT{\_}TYPE{\_}SIZE}}{349}
-\entry {\code {FLOAT{\_}VALUE{\_}TYPE}}{390}
-\entry {\code {FLOAT{\_}WORDS{\_}BIG{\_}ENDIAN}}{343}
-\entry {\code {FLOATIFY}}{389}
-\entry {floating point and cross compilation}{427}
-\entry {\code {float\var {mn}2} instruction pattern}{300}
-\entry {\code {floatuns\var {mn}2} instruction pattern}{300}
-\entry {\code {force{\_}reg}}{296}
-\entry {\code {format} function attribute}{146}
-\entry {forwarding calls}{131}
-\entry {frame layout}{364}
-\entry {\code {FRAME{\_}GROWS{\_}DOWNWARD}}{364}
-\entry {\code {FRAME{\_}GROWS{\_}DOWNWARD} and virtual registers}{245}
-\entry {\code {frame{\_}pointer{\_}needed}}{378}
-\entry {\code {FRAME{\_}POINTER{\_}REGNUM}}{366}
-\entry {\code {FRAME{\_}POINTER{\_}REGNUM} and virtual registers}{245}
-\entry {\code {FRAME{\_}POINTER{\_}REQUIRED}}{367}
-\entry {\code {frame{\_}pointer{\_}rtx}}{367}
-\entry {\code {fscanf}, and constant strings}{190}
-\entry {\code {ftrunc\var {m}2} instruction pattern}{300}
-\entry {function attributes}{144}
-\entry {function call conventions}{223}
-\entry {function entry and exit}{378}
-\entry {function pointers, arithmetic}{139}
-\entry {function prototype declarations}{148}
-\entry {function units, for scheduling}{332}
-\entry {function, size of pointer to}{139}
-\entry {function-call insns}{269}
-\entry {\code {FUNCTION{\_}ARG}}{371}
-\entry {\code {FUNCTION{\_}ARG{\_}ADVANCE}}{374}
-\entry {\code {FUNCTION{\_}ARG{\_}BOUNDARY}}{374}
-\entry {\code {FUNCTION{\_}ARG{\_}CALLEE{\_}COPIES}}{373}
-\entry {\code {FUNCTION{\_}ARG{\_}PADDING}}{374}
-\entry {\code {FUNCTION{\_}ARG{\_}PARTIAL{\_}NREGS}}{372}
-\entry {\code {FUNCTION{\_}ARG{\_}PASS{\_}BY{\_}REFERENCE}}{372}
-\entry {\code {FUNCTION{\_}ARG{\_}REGNO{\_}P}}{374}
-\entry {\code {FUNCTION{\_}BLOCK{\_}PROFILER}}{381}
-\entry {\code {FUNCTION{\_}BOUNDARY}}{344}
-\entry {\code {FUNCTION{\_}CONVERSION{\_}BUG}}{438}
-\entry {\code {FUNCTION{\_}EPILOGUE}}{379}
-\entry {\code {FUNCTION{\_}EPILOGUE} and trampolines}{386}
-\entry {\code {FUNCTION{\_}INCOMING{\_}ARG}}{372}
-\entry {\code {FUNCTION{\_}MODE}}{434}
-\entry {\code {FUNCTION{\_}OUTGOING{\_}VALUE}}{375}
-\entry {\code {FUNCTION{\_}PROFILER}}{381}
-\entry {\code {FUNCTION{\_}PROLOGUE}}{378}
-\entry {\code {FUNCTION{\_}PROLOGUE} and trampolines}{386}
-\entry {\code {FUNCTION{\_}VALUE}}{375}
-\entry {\code {FUNCTION{\_}VALUE{\_}REGNO{\_}P}}{375}
-\entry {functions in arbitrary sections}{144}
-\entry {functions that are passed arguments in registers on the 386}{144, 147}
-\entry {functions that do not pop the argument stack on the 386}{144}
-\entry {functions that do pop the argument stack on the 386}{147}
-\entry {functions that have no side effects}{144}
-\entry {functions that never return}{144}
-\entry {functions that pop the argument stack on the 386}{144, 147}
-\entry {functions with \code {printf} or \code {scanf} style arguments}{144}
-\entry {functions, leaf}{355}
+\entry {\samp {F} in constraint}{302}
+\entry {\code {fabs}}{18}
+\entry {\code {FAIL}}{336}
+\entry {fatal signal}{215}
+\entry {\code {FATAL{\_}EXIT{\_}CODE}}{469}
+\entry {features, optional, in system conventions}{360}
+\entry {\code {ffs}}{18, 268}
+\entry {\code {ffs\var {m}2} instruction pattern}{318}
+\entry {file name suffix}{14}
+\entry {file names}{47}
+\entry {files and passes of the compiler}{239}
+\entry {final pass}{244}
+\entry {\code {FINAL{\_}PRESCAN{\_}INSN}}{446}
+\entry {\code {FINAL{\_}PRESCAN{\_}LABEL}}{447}
+\entry {\code {FINAL{\_}REG{\_}PARM{\_}STACK{\_}SPACE}}{392}
+\entry {\code {final{\_}scan{\_}insn}}{404}
+\entry {\code {final{\_}sequence}}{448}
+\entry {\code {FINALIZE{\_}PIC}}{431}
+\entry {\code {FIRST{\_}INSN{\_}ADDRESS}}{347}
+\entry {\code {FIRST{\_}PARM{\_}OFFSET}}{387}
+\entry {\code {FIRST{\_}PARM{\_}OFFSET} and virtual registers}{261}
+\entry {\code {FIRST{\_}PSEUDO{\_}REGISTER}}{372}
+\entry {\code {FIRST{\_}STACK{\_}REG}}{377}
+\entry {\code {FIRST{\_}VIRTUAL{\_}REGISTER}}{261}
+\entry {\code {fix}}{271}
+\entry {\code {fix{\_}trunc\var {mn}2} instruction pattern}{320}
+\entry {fixed register}{372}
+\entry {\code {FIXED{\_}REGISTERS}}{372}
+\entry {\code {fixed{\_}regs}}{373}
+\entry {\code {fix\var {mn}2} instruction pattern}{319}
+\entry {\code {FIXUNS{\_}TRUNC{\_}LIKE{\_}FIX{\_}TRUNC}}{462}
+\entry {\code {fixuns{\_}trunc\var {mn}2} instruction pattern}{320}
+\entry {\code {fixuns\var {mn}2} instruction pattern}{319}
+\entry {flags in RTL expression}{250}
+\entry {\code {float}}{271}
+\entry {\code {float} as function value type}{204}
+\entry {\code {FLOAT{\_}ARG{\_}TYPE}}{416}
+\entry {\code {float{\_}extend}}{271}
+\entry {\code {FLOAT{\_}STORE{\_}FLAG{\_}VALUE}}{465}
+\entry {\code {float{\_}truncate}}{271}
+\entry {\code {FLOAT{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {FLOAT{\_}VALUE{\_}TYPE}}{417}
+\entry {\code {FLOAT{\_}WORDS{\_}BIG{\_}ENDIAN}}{362}
+\entry {\code {FLOATIFY}}{417}
+\entry {floating point and cross compilation}{458}
+\entry {floating point precision}{40, 207}
+\entry {\code {float\var {mn}2} instruction pattern}{319}
+\entry {\code {floatuns\var {mn}2} instruction pattern}{319}
+\entry {\code {force{\_}reg}}{314}
+\entry {\code {format} function attribute}{153}
+\entry {\code {format{\_}arg} function attribute}{153}
+\entry {forwarding calls}{140}
+\entry {frame layout}{386}
+\entry {\code {FRAME{\_}GROWS{\_}DOWNWARD}}{386}
+\entry {\code {FRAME{\_}GROWS{\_}DOWNWARD} and virtual registers}{261}
+\entry {\code {frame{\_}pointer{\_}needed}}{402}
+\entry {\code {FRAME{\_}POINTER{\_}REGNUM}}{388}
+\entry {\code {FRAME{\_}POINTER{\_}REGNUM} and virtual registers}{261}
+\entry {\code {FRAME{\_}POINTER{\_}REQUIRED}}{390}
+\entry {\code {frame{\_}pointer{\_}rtx}}{389}
+\entry {\code {fscanf}, and constant strings}{201}
+\entry {\code {ftrunc\var {m}2} instruction pattern}{319}
+\entry {function attributes}{151}
+\entry {function call conventions}{237}
+\entry {function entry and exit}{401}
+\entry {function pointers, arithmetic}{148}
+\entry {function prototype declarations}{157}
+\entry {function units, for scheduling}{350}
+\entry {function, size of pointer to}{148}
+\entry {function-call insns}{287}
+\entry {\code {FUNCTION{\_}ARG}}{394}
+\entry {\code {FUNCTION{\_}ARG{\_}ADVANCE}}{397}
+\entry {\code {FUNCTION{\_}ARG{\_}BOUNDARY}}{397}
+\entry {\code {FUNCTION{\_}ARG{\_}CALLEE{\_}COPIES}}{396}
+\entry {\code {FUNCTION{\_}ARG{\_}PADDING}}{397}
+\entry {\code {FUNCTION{\_}ARG{\_}PARTIAL{\_}NREGS}}{395}
+\entry {\code {FUNCTION{\_}ARG{\_}PASS{\_}BY{\_}REFERENCE}}{395}
+\entry {\code {FUNCTION{\_}ARG{\_}REGNO{\_}P}}{397}
+\entry {\code {FUNCTION{\_}BLOCK{\_}PROFILER}}{406}
+\entry {\code {FUNCTION{\_}BLOCK{\_}PROFILER{\_}EXIT}}{408}
+\entry {\code {FUNCTION{\_}BOUNDARY}}{364}
+\entry {\code {FUNCTION{\_}CONVERSION{\_}BUG}}{470}
+\entry {\code {FUNCTION{\_}EPILOGUE}}{403}
+\entry {\code {FUNCTION{\_}EPILOGUE} and trampolines}{413}
+\entry {\code {FUNCTION{\_}INCOMING{\_}ARG}}{395}
+\entry {\code {FUNCTION{\_}MODE}}{465}
+\entry {\code {FUNCTION{\_}OUTGOING{\_}VALUE}}{398}
+\entry {\code {FUNCTION{\_}PROFILER}}{405}
+\entry {\code {FUNCTION{\_}PROLOGUE}}{401}
+\entry {\code {FUNCTION{\_}PROLOGUE} and trampolines}{413}
+\entry {\code {FUNCTION{\_}VALUE}}{398}
+\entry {\code {FUNCTION{\_}VALUE{\_}REGNO{\_}P}}{399}
+\entry {functions called via pointer on the RS/6000 and PowerPC}{155}
+\entry {functions in arbitrary sections}{151}
+\entry {functions that are passed arguments in registers on the 386}{151, 155}
+\entry {functions that do not pop the argument stack on the 386}{151}
+\entry {functions that do pop the argument stack on the 386}{155}
+\entry {functions that have no side effects}{151}
+\entry {functions that never return}{151}
+\entry {functions that pop the argument stack on the 386}{151, 155}
+\entry {functions which are exported from a dll on PowerPC Windows NT}{155}
+\entry {functions which are imported from a dll on PowerPC Windows NT}{155}
+\entry {functions which specify exception handling on PowerPC Windows NT}{156}
+\entry {functions with \code {printf} or \code {scanf} style arguments}{151}
+\entry {functions, leaf}{376}
\initial {G}
-\entry {\samp {g} in constraint}{284}
-\entry {\samp {G} in constraint}{284}
-\entry {\code {g{\tt\char43}{\tt\char43}}}{26}
-\entry {G{\tt\char43}{\tt\char43}}{17}
-\entry {\code {g{\tt\char43}{\tt\char43} 1.\var {xx}}}{26}
-\entry {\code {g{\tt\char43}{\tt\char43}} older version}{26}
-\entry {\code {g{\tt\char43}{\tt\char43}}, separate compiler}{26}
-\entry {GCC}{17}
-\entry {\code {GCC{\_}EXEC{\_}PREFIX}}{86}
-\entry {\code {ge}}{252}
-\entry {\code {ge} and attributes}{323}
-\entry {\code {GEN{\_}ERRNO{\_}RTX}}{389}
-\entry {\code {gencodes}}{226}
-\entry {\code {genconfig}}{229}
-\entry {\code {general{\_}operand}}{276}
-\entry {\code {GENERAL{\_}REGS}}{357}
-\entry {generalized lvalues}{133}
-\entry {generating assembler output}{281}
-\entry {generating insns}{275}
-\entry {\code {genflags}}{226}
-\entry {\code {genflags}, crash on Sun 4}{181}
-\entry {\code {get{\_}attr}}{324}
-\entry {\code {get{\_}attr{\_}length}}{329}
-\entry {\code {GET{\_}CLASS{\_}NARROWEST{\_}MODE}}{242}
-\entry {\code {GET{\_}CODE}}{231}
-\entry {\code {get{\_}frame{\_}size}}{368}
-\entry {\code {get{\_}insns}}{262}
-\entry {\code {get{\_}last{\_}insn}}{262}
-\entry {\code {GET{\_}MODE}}{241}
-\entry {\code {GET{\_}MODE{\_}ALIGNMENT}}{241}
-\entry {\code {GET{\_}MODE{\_}BITSIZE}}{241}
-\entry {\code {GET{\_}MODE{\_}CLASS}}{241}
-\entry {\code {GET{\_}MODE{\_}MASK}}{241}
-\entry {\code {GET{\_}MODE{\_}NAME}}{241}
-\entry {\code {GET{\_}MODE{\_}NUNITS}}{241}
-\entry {\code {GET{\_}MODE{\_}SIZE}}{241}
-\entry {\code {GET{\_}MODE{\_}UNIT{\_}SIZE}}{241}
-\entry {\code {GET{\_}MODE{\_}WIDER{\_}MODE}}{241}
-\entry {\code {GET{\_}RTX{\_}CLASS}}{233}
-\entry {\code {GET{\_}RTX{\_}FORMAT}}{233}
-\entry {\code {GET{\_}RTX{\_}LENGTH}}{233}
-\entry {\code {geu}}{252}
-\entry {\code {geu} and attributes}{323}
-\entry {global offset table}{84}
-\entry {global register after \code {longjmp}}{164}
-\entry {global register allocation}{228}
-\entry {global register variables}{163}
-\entry {\code {GLOBALDEF}}{216}
-\entry {\code {GLOBALREF}}{216}
-\entry {\code {GLOBALVALUEDEF}}{216}
-\entry {\code {GLOBALVALUEREF}}{216}
-\entry {GNU CC and portability}{221}
-\entry {GNU CC command options}{19}
-\entry {\code {GO{\_}IF{\_}LEGITIMATE{\_}ADDRESS}}{391}
-\entry {\code {GO{\_}IF{\_}MODE{\_}DEPENDENT{\_}ADDRESS}}{393}
-\entry {\code {goto} in C{\tt\char43}{\tt\char43}}{172}
-\entry {goto with computed label}{127}
-\entry {gp-relative references (MIPS)}{75}
-\entry {\code {gprof}}{43}
-\entry {greater than}{252}
-\entry {grouping options}{19}
-\entry {\code {gt}}{252}
-\entry {\code {gt} and attributes}{323}
-\entry {\code {gtu}}{252}
-\entry {\code {gtu} and attributes}{323}
+\entry {\samp {g} in constraint}{302}
+\entry {\samp {G} in constraint}{302}
+\entry {\code {g{\tt\char43}{\tt\char43}}}{16}
+\entry {G{\tt\char43}{\tt\char43}}{7}
+\entry {\code {g{\tt\char43}{\tt\char43} 1.\var {xx}}}{16}
+\entry {\code {g{\tt\char43}{\tt\char43}} older version}{16}
+\entry {\code {g{\tt\char43}{\tt\char43}}, separate compiler}{16}
+\entry {GCC}{7}
+\entry {\code {GCC{\_}EXEC{\_}PREFIX}}{92}
+\entry {\code {ge}}{269}
+\entry {\code {ge} and attributes}{342}
+\entry {\code {GEN{\_}ERRNO{\_}RTX}}{416}
+\entry {\code {gencodes}}{240}
+\entry {\code {genconfig}}{244}
+\entry {\code {general{\_}operand}}{294}
+\entry {\code {GENERAL{\_}REGS}}{379}
+\entry {generalized lvalues}{142}
+\entry {generating assembler output}{299}
+\entry {generating insns}{293}
+\entry {\code {genflags}}{240}
+\entry {\code {genflags}, crash on Sun 4}{191}
+\entry {\code {get{\_}attr}}{343}
+\entry {\code {get{\_}attr{\_}length}}{348}
+\entry {\code {GET{\_}CLASS{\_}NARROWEST{\_}MODE}}{258}
+\entry {\code {GET{\_}CODE}}{247}
+\entry {\code {get{\_}frame{\_}size}}{390}
+\entry {\code {get{\_}insns}}{279}
+\entry {\code {get{\_}last{\_}insn}}{279}
+\entry {\code {GET{\_}MODE}}{257}
+\entry {\code {GET{\_}MODE{\_}ALIGNMENT}}{257}
+\entry {\code {GET{\_}MODE{\_}BITSIZE}}{257}
+\entry {\code {GET{\_}MODE{\_}CLASS}}{257}
+\entry {\code {GET{\_}MODE{\_}MASK}}{257}
+\entry {\code {GET{\_}MODE{\_}NAME}}{257}
+\entry {\code {GET{\_}MODE{\_}NUNITS}}{258}
+\entry {\code {GET{\_}MODE{\_}SIZE}}{257}
+\entry {\code {GET{\_}MODE{\_}UNIT{\_}SIZE}}{257}
+\entry {\code {GET{\_}MODE{\_}WIDER{\_}MODE}}{257}
+\entry {\code {GET{\_}RTX{\_}CLASS}}{249}
+\entry {\code {GET{\_}RTX{\_}FORMAT}}{249}
+\entry {\code {GET{\_}RTX{\_}LENGTH}}{248}
+\entry {\code {geu}}{269}
+\entry {\code {geu} and attributes}{342}
+\entry {\code {GIV{\_}SORT{\_}CRITERION}}{468}
+\entry {global offset table}{90}
+\entry {global register after \code {longjmp}}{173}
+\entry {global register allocation}{243}
+\entry {global register variables}{172}
+\entry {\code {GLOBALDEF}}{230}
+\entry {\code {GLOBALREF}}{230}
+\entry {\code {GLOBALVALUEDEF}}{230}
+\entry {\code {GLOBALVALUEREF}}{230}
+\entry {GNU CC and portability}{235}
+\entry {GNU CC command options}{9}
+\entry {\code {GO{\_}IF{\_}LEGITIMATE{\_}ADDRESS}}{419}
+\entry {\code {GO{\_}IF{\_}MODE{\_}DEPENDENT{\_}ADDRESS}}{421}
+\entry {\code {goto} in C{\tt\char43}{\tt\char43}}{181}
+\entry {goto with computed label}{137}
+\entry {gp-relative references (MIPS)}{78}
+\entry {\code {gprof}}{35}
+\entry {greater than}{269}
+\entry {grouping options}{9}
+\entry {\code {gt}}{269}
+\entry {\code {gt} and attributes}{342}
+\entry {\code {gtu}}{269}
+\entry {\code {gtu} and attributes}{342}
\initial {H}
-\entry {\samp {H} in constraint}{284}
-\entry {\code {HANDLE{\_}PRAGMA}}{434}
-\entry {hard registers}{244}
-\entry {\code {HARD{\_}FRAME{\_}POINTER{\_}REGNUM}}{366}
-\entry {\code {HARD{\_}REGNO{\_}MODE{\_}OK}}{353}
-\entry {\code {HARD{\_}REGNO{\_}NREGS}}{353}
-\entry {hardware models and configurations, specifying}{57}
-\entry {\code {HAS{\_}INIT{\_}SECTION}}{414}
-\entry {\code {HAVE{\_}ATEXIT}}{435}
-\entry {\code {HAVE{\_}POST{\_}DECREMENT}}{391}
-\entry {\code {HAVE{\_}POST{\_}INCREMENT}}{391}
-\entry {\code {HAVE{\_}PRE{\_}DECREMENT}}{391}
-\entry {\code {HAVE{\_}PRE{\_}INCREMENT}}{391}
-\entry {\code {HAVE{\_}PUTENV}}{438}
-\entry {\code {HAVE{\_}VPRINTF}}{438}
-\entry {header files and VMS}{215}
-\entry {\code {high}}{243}
-\entry {\code {HImode}}{239}
-\entry {\code {HImode}, in \code {insn}}{264}
-\entry {\code {HOST{\_}BITS{\_}PER{\_}CHAR}}{437}
-\entry {\code {HOST{\_}BITS{\_}PER{\_}INT}}{437}
-\entry {\code {HOST{\_}BITS{\_}PER{\_}LONG}}{437}
-\entry {\code {HOST{\_}BITS{\_}PER{\_}SHORT}}{437}
-\entry {\code {HOST{\_}FLOAT{\_}FORMAT}}{437}
-\entry {\code {HOST{\_}FLOAT{\_}WORDS{\_}BIG{\_}ENDIAN}}{437}
-\entry {\code {HOST{\_}WORDS{\_}BIG{\_}ENDIAN}}{437}
-\entry {HPPA Options}{78}
+\entry {\samp {H} in constraint}{302}
+\entry {\code {HANDLE{\_}PRAGMA}}{466}
+\entry {hard registers}{260}
+\entry {\code {HARD{\_}FRAME{\_}POINTER{\_}REGNUM}}{388}
+\entry {\code {HARD{\_}REGNO{\_}MODE{\_}OK}}{374}
+\entry {\code {HARD{\_}REGNO{\_}NREGS}}{374}
+\entry {hardware models and configurations, specifying}{52}
+\entry {\code {HAS{\_}INIT{\_}SECTION}}{444}
+\entry {\code {HAVE{\_}ATEXIT}}{467}
+\entry {\code {HAVE{\_}POPEN}}{471}
+\entry {\code {HAVE{\_}POST{\_}DECREMENT}}{418}
+\entry {\code {HAVE{\_}POST{\_}INCREMENT}}{418}
+\entry {\code {HAVE{\_}PRE{\_}DECREMENT}}{418}
+\entry {\code {HAVE{\_}PRE{\_}INCREMENT}}{418}
+\entry {\code {HAVE{\_}PUTENV}}{471}
+\entry {\code {HAVE{\_}VPRINTF}}{470}
+\entry {header files and VMS}{229}
+\entry {\code {high}}{260}
+\entry {\code {HImode}}{255}
+\entry {\code {HImode}, in \code {insn}}{282}
+\entry {host makefile fragment}{475}
+\entry {\code {HOST{\_}BITS{\_}PER{\_}CHAR}}{469}
+\entry {\code {HOST{\_}BITS{\_}PER{\_}INT}}{469}
+\entry {\code {HOST{\_}BITS{\_}PER{\_}LONG}}{469}
+\entry {\code {HOST{\_}BITS{\_}PER{\_}SHORT}}{469}
+\entry {\code {HOST{\_}FLOAT{\_}FORMAT}}{469}
+\entry {\code {HOST{\_}FLOAT{\_}WORDS{\_}BIG{\_}ENDIAN}}{469}
+\entry {\code {HOST{\_}WORDS{\_}BIG{\_}ENDIAN}}{469}
+\entry {HPPA Options}{81}
\initial {I}
-\entry {\samp {i} in constraint}{284}
-\entry {\samp {I} in constraint}{284}
-\entry {i386 Options}{76}
-\entry {IBM RS/6000 and PowerPC Options}{68}
-\entry {IBM RT options}{72}
-\entry {IBM RT PC}{188}
-\entry {identifier names, dollar signs in}{149}
-\entry {identifiers, names in assembler code}{161}
-\entry {identifying source, compiler (88k)}{65}
-\entry {\code {IEEE{\_}FLOAT{\_}FORMAT}}{347}
-\entry {\code {if{\_}then{\_}else}}{252}
-\entry {\code {if{\_}then{\_}else} and attributes}{323}
-\entry {\code {if{\_}then{\_}else} usage}{255}
-\entry {\code {immediate{\_}operand}}{276}
-\entry {\code {IMMEDIATE{\_}PREFIX}}{418}
-\entry {implicit argument: return value}{169}
-\entry {\code {IMPLICIT{\_}FIX{\_}EXPR}}{431}
-\entry {implied \code {#pragma implementation}}{173}
-\entry {\code {in{\_}data}}{400}
-\entry {\code {in{\_}struct}}{237}
-\entry {\code {in{\_}struct}, in \code {code{\_}label}}{237}
-\entry {\code {in{\_}struct}, in \code {insn}}{236, 237}
-\entry {\code {in{\_}struct}, in \code {label{\_}ref}}{236}
-\entry {\code {in{\_}struct}, in \code {mem}}{235}
-\entry {\code {in{\_}struct}, in \code {reg}}{235}
-\entry {\code {in{\_}struct}, in \code {subreg}}{235}
-\entry {\code {in{\_}text}}{400}
-\entry {include files and VMS}{215}
-\entry {\code {INCLUDE{\_}DEFAULTS}}{338}
-\entry {inclusive-or, bitwise}{250}
-\entry {\code {INCOMING{\_}REGNO}}{352}
-\entry {incompatibilities of GNU CC}{190}
-\entry {increment operators}{203}
-\entry {\code {INDEX{\_}REG{\_}CLASS}}{359}
-\entry {\code {indirect{\_}jump} instruction pattern}{304}
-\entry {\code {INIT{\_}CUMULATIVE{\_}ARGS}}{373}
-\entry {\code {INIT{\_}CUMULATIVE{\_}INCOMING{\_}ARGS}}{373}
-\entry {\code {INIT{\_}ENVIRONMENT}}{338}
-\entry {\code {INIT{\_}SECTION{\_}ASM{\_}OP}}{400, 414}
-\entry {\code {INIT{\_}TARGET{\_}OPTABS}}{388}
-\entry {\code {INITIAL{\_}ELIMINATION{\_}OFFSET}}{368}
-\entry {\code {INITIAL{\_}FRAME{\_}POINTER{\_}OFFSET}}{368}
-\entry {initialization routines}{411}
-\entry {initializations in expressions}{140}
-\entry {\code {INITIALIZE{\_}TRAMPOLINE}}{385}
-\entry {initializers with labeled elements}{141}
-\entry {initializers, non-constant}{140}
-\entry {\code {inline} automatic for C{\tt\char43}{\tt\char43} member fns}{156}
-\entry {inline functions}{156}
-\entry {inline functions, omission of}{156}
-\entry {inline, automatic}{226}
-\entry {inlining and C{\tt\char43}{\tt\char43} pragmas}{173}
-\entry {\code {insn}}{262}
-\entry {\code {insn} and \samp {/i}}{237}
-\entry {\code {insn} and \samp {/s}}{236}
-\entry {\code {insn} and \samp {/u}}{236}
-\entry {insn attributes}{321}
-\entry {insn canonicalization}{310}
-\entry {insn lengths, computing}{328}
-\entry {insn splitting}{318}
-\entry {\code {insn-attr.h}}{322}
-\entry {\code {INSN{\_}ANNULLED{\_}BRANCH{\_}P}}{236}
-\entry {\code {INSN{\_}CACHE{\_}DEPTH}}{386}
-\entry {\code {INSN{\_}CACHE{\_}LINE{\_}WIDTH}}{386}
-\entry {\code {INSN{\_}CACHE{\_}SIZE}}{386}
-\entry {\code {INSN{\_}CLOBBERS{\_}REGNO{\_}P}}{356}
-\entry {\code {INSN{\_}CODE}}{265}
-\entry {\code {INSN{\_}DELETED{\_}P}}{236}
-\entry {\code {INSN{\_}FROM{\_}TARGET{\_}P}}{236}
-\entry {\code {insn{\_}list}}{269}
-\entry {\code {INSN{\_}REFERENCES{\_}ARE{\_}DELAYED}}{436}
-\entry {\code {INSN{\_}SETS{\_}ARE{\_}DELAYED}}{436}
-\entry {\code {INSN{\_}UID}}{261}
-\entry {insns}{261}
-\entry {insns, generating}{275}
-\entry {insns, recognizing}{275}
-\entry {installation trouble}{179}
-\entry {installing GNU CC}{91}
-\entry {installing GNU CC on the Sun}{118}
-\entry {installing GNU CC on VMS}{119}
-\entry {instruction attributes}{321}
-\entry {instruction combination}{228}
-\entry {instruction patterns}{273}
-\entry {instruction recognizer}{230}
-\entry {instruction scheduling}{228}
-\entry {instruction splitting}{318}
-\entry {\code {insv} instruction pattern}{301}
-\entry {\code {INT{\_}TYPE{\_}SIZE}}{348}
-\entry {\code {INTEGRATE{\_}THRESHOLD}}{434}
-\entry {\code {integrated}}{238}
-\entry {\code {integrated}, in \code {insn}}{236}
-\entry {\code {integrated}, in \code {reg}}{235}
-\entry {integrating function code}{156}
-\entry {Intel 386 Options}{76}
-\entry {Interdependence of Patterns}{306}
-\entry {interface and implementation headers, C{\tt\char43}{\tt\char43}}{172}
-\entry {interfacing to GNU CC output}{223}
-\entry {intermediate C version, nonexistent}{17}
-\entry {\code {INTIFY}}{390}
-\entry {invalid assembly code}{203}
-\entry {invalid input}{204}
-\entry {\code {INVOKE{\_}{\_}main}}{414}
-\entry {invoking \code {g{\tt\char43}{\tt\char43}}}{26}
-\entry {\code {ior}}{250}
-\entry {\code {ior} and attributes}{323}
-\entry {\code {ior}, canonicalization of}{311}
-\entry {\code {ior\var {m}3} instruction pattern}{298}
-\entry {\code {IS{\_}ASM{\_}LOGICAL{\_}LINE{\_}SEPARATOR}}{406}
-\entry {\code {isinf}}{429}
-\entry {\code {isnan}}{429}
+\entry {\samp {i} in constraint}{302}
+\entry {\samp {I} in constraint}{302}
+\entry {i386 Options}{79}
+\entry {IBM RS/6000 and PowerPC Options}{66}
+\entry {IBM RT options}{74}
+\entry {IBM RT PC}{199}
+\entry {identifier names, dollar signs in}{158}
+\entry {identifiers, names in assembler code}{171}
+\entry {identifying source, compiler (88k)}{63}
+\entry {\code {IEEE{\_}FLOAT{\_}FORMAT}}{368}
+\entry {\code {if{\_}then{\_}else}}{269}
+\entry {\code {if{\_}then{\_}else} and attributes}{342}
+\entry {\code {if{\_}then{\_}else} usage}{273}
+\entry {\code {immediate{\_}operand}}{294}
+\entry {\code {IMMEDIATE{\_}PREFIX}}{448}
+\entry {implicit argument: return value}{179}
+\entry {\code {IMPLICIT{\_}FIX{\_}EXPR}}{462}
+\entry {implied \code {#pragma implementation}}{182}
+\entry {\code {in{\_}data}}{428}
+\entry {\code {in{\_}struct}}{253}
+\entry {\code {in{\_}struct}, in \code {code{\_}label}}{252}
+\entry {\code {in{\_}struct}, in \code {insn}}{252, 253}
+\entry {\code {in{\_}struct}, in \code {label{\_}ref}}{252}
+\entry {\code {in{\_}struct}, in \code {mem}}{250}
+\entry {\code {in{\_}struct}, in \code {reg}}{251}
+\entry {\code {in{\_}struct}, in \code {subreg}}{251}
+\entry {\code {in{\_}text}}{428}
+\entry {include files and VMS}{229}
+\entry {\code {INCLUDE{\_}DEFAULTS}}{358}
+\entry {inclusive-or, bitwise}{267}
+\entry {\code {INCOMING{\_}REGNO}}{373}
+\entry {incompatibilities of GNU CC}{201}
+\entry {increment operators}{215}
+\entry {\code {INDEX{\_}REG{\_}CLASS}}{380}
+\entry {\code {indirect{\_}jump} instruction pattern}{324}
+\entry {\code {INIT{\_}CUMULATIVE{\_}ARGS}}{396}
+\entry {\code {INIT{\_}CUMULATIVE{\_}INCOMING{\_}ARGS}}{396}
+\entry {\code {INIT{\_}ENVIRONMENT}}{357}
+\entry {\code {INIT{\_}SECTION{\_}ASM{\_}OP}}{428, 444}
+\entry {\code {INIT{\_}TARGET{\_}OPTABS}}{416}
+\entry {\code {INITIAL{\_}ELIMINATION{\_}OFFSET}}{391}
+\entry {\code {INITIAL{\_}FRAME{\_}POINTER{\_}OFFSET}}{390}
+\entry {initialization routines}{442}
+\entry {initializations in expressions}{148}
+\entry {\code {INITIALIZE{\_}TRAMPOLINE}}{413}
+\entry {initializers with labeled elements}{149}
+\entry {initializers, non-constant}{148}
+\entry {\code {inline} automatic for C{\tt\char43}{\tt\char43} member fns}{166}
+\entry {inline functions}{166}
+\entry {inline functions, omission of}{166}
+\entry {inline, automatic}{240}
+\entry {inlining and C{\tt\char43}{\tt\char43} pragmas}{183}
+\entry {\code {insn}}{280}
+\entry {\code {insn} and \samp {/i}}{253}
+\entry {\code {insn} and \samp {/s}}{252}
+\entry {\code {insn} and \samp {/u}}{252}
+\entry {insn attributes}{340}
+\entry {insn canonicalization}{330}
+\entry {insn lengths, computing}{347}
+\entry {insn splitting}{338}
+\entry {\code {insn-attr.h}}{341}
+\entry {\code {INSN{\_}ANNULLED{\_}BRANCH{\_}P}}{252}
+\entry {\code {INSN{\_}CACHE{\_}DEPTH}}{414}
+\entry {\code {INSN{\_}CACHE{\_}LINE{\_}WIDTH}}{413}
+\entry {\code {INSN{\_}CACHE{\_}SIZE}}{413}
+\entry {\code {INSN{\_}CLOBBERS{\_}REGNO{\_}P}}{378}
+\entry {\code {INSN{\_}CODE}}{283}
+\entry {\code {INSN{\_}DELETED{\_}P}}{252}
+\entry {\code {INSN{\_}FROM{\_}TARGET{\_}P}}{252}
+\entry {\code {insn{\_}list}}{287}
+\entry {\code {INSN{\_}REFERENCES{\_}ARE{\_}DELAYED}}{467}
+\entry {\code {INSN{\_}SETS{\_}ARE{\_}DELAYED}}{467}
+\entry {\code {INSN{\_}UID}}{279}
+\entry {insns}{279}
+\entry {insns, generating}{293}
+\entry {insns, recognizing}{293}
+\entry {\code {INSTALL}}{475}
+\entry {installation trouble}{189}
+\entry {installing GNU CC}{97}
+\entry {installing GNU CC on the Sun}{127}
+\entry {installing GNU CC on VMS}{128}
+\entry {instruction attributes}{340}
+\entry {instruction combination}{242}
+\entry {instruction patterns}{291}
+\entry {instruction recognizer}{244}
+\entry {instruction scheduling}{242, 243}
+\entry {instruction splitting}{338}
+\entry {\code {insv} instruction pattern}{320}
+\entry {\code {INT{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {INTEGRATE{\_}THRESHOLD}}{465}
+\entry {\code {integrated}}{254}
+\entry {\code {integrated}, in \code {insn}}{251}
+\entry {\code {integrated}, in \code {reg}}{251}
+\entry {integrating function code}{166}
+\entry {Intel 386 Options}{79}
+\entry {Interdependence of Patterns}{327}
+\entry {interface and implementation headers, C{\tt\char43}{\tt\char43}}{181}
+\entry {interfacing to GNU CC output}{237}
+\entry {intermediate C version, nonexistent}{7}
+\entry {interrupt handler functions on the H8/300 processors}{156}
+\entry {\code {INTIFY}}{417}
+\entry {invalid assembly code}{215}
+\entry {invalid input}{216}
+\entry {\code {INVOKE{\_}{\_}main}}{444}
+\entry {invoking \code {g{\tt\char43}{\tt\char43}}}{16}
+\entry {\code {ior}}{267}
+\entry {\code {ior} and attributes}{342}
+\entry {\code {ior}, canonicalization of}{331}
+\entry {\code {ior\var {m}3} instruction pattern}{317}
+\entry {\code {IS{\_}ASM{\_}LOGICAL{\_}LINE{\_}SEPARATOR}}{435}
+\entry {\code {isinf}}{459}
+\entry {\code {isnan}}{460}
\initial {J}
-\entry {jump instruction patterns}{308}
-\entry {jump instructions and \code {set}}{255}
-\entry {jump optimization}{226}
-\entry {jump threading}{227}
-\entry {\code {jump{\_}insn}}{262}
-\entry {\code {JUMP{\_}LABEL}}{263}
-\entry {\code {JUMP{\_}TABLES{\_}IN{\_}TEXT{\_}SECTION}}{400}
+\entry {jump instruction patterns}{328}
+\entry {jump instructions and \code {set}}{273}
+\entry {jump optimization}{241}
+\entry {jump threading}{241}
+\entry {\code {jump{\_}insn}}{280}
+\entry {\code {JUMP{\_}LABEL}}{280}
+\entry {\code {JUMP{\_}TABLES{\_}IN{\_}TEXT{\_}SECTION}}{429}
\initial {K}
-\entry {kernel and user registers (29k)}{63}
-\entry {keywords, alternate}{165}
-\entry {known causes of trouble}{179}
+\entry {kernel and user registers (29k)}{60}
+\entry {keywords, alternate}{174}
+\entry {known causes of trouble}{189}
\initial {L}
-\entry {\code {LABEL{\_}NUSES}}{263}
-\entry {\code {LABEL{\_}OUTSIDE{\_}LOOP{\_}P}}{236}
-\entry {\code {LABEL{\_}PRESERVE{\_}P}}{237}
-\entry {\code {label{\_}ref}}{243}
-\entry {\code {label{\_}ref} and \samp {/s}}{236}
-\entry {\code {label{\_}ref}, RTL sharing}{271}
-\entry {labeled elements in initializers}{141}
-\entry {labels as values}{127}
-\entry {\code {labs}}{28}
-\entry {language dialect options}{27}
-\entry {large bit shifts (88k)}{68}
-\entry {large return values}{376}
-\entry {\code {LAST{\_}STACK{\_}REG}}{356}
-\entry {\code {LAST{\_}VIRTUAL{\_}REGISTER}}{245}
-\entry {\code {LD{\_}FINI{\_}SWITCH}}{414}
-\entry {\code {LD{\_}INIT{\_}SWITCH}}{414}
-\entry {\code {LDD{\_}SUFFIX}}{415}
-\entry {\code {ldexp}}{428}
-\entry {\code {le}}{252}
-\entry {\code {le} and attributes}{323}
-\entry {leaf functions}{355}
-\entry {\code {leaf{\_}function}}{355}
-\entry {\code {leaf{\_}function{\_}p}}{303}
-\entry {\code {LEAF{\_}REG{\_}REMAP}}{355}
-\entry {\code {LEAF{\_}REGISTERS}}{355}
-\entry {left rotate}{250}
-\entry {left shift}{250}
-\entry {\code {LEGITIMATE{\_}CONSTANT{\_}P}}{393}
-\entry {\code {LEGITIMATE{\_}PIC{\_}OPERAND{\_}P}}{402}
-\entry {\code {LEGITIMIZE{\_}ADDRESS}}{393}
-\entry {length-zero arrays}{136}
-\entry {less than}{252}
-\entry {less than or equal}{252}
-\entry {\code {leu}}{252}
-\entry {\code {leu} and attributes}{323}
-\entry {\code {LIB{\_}SPEC}}{336}
-\entry {\code {LIBCALL{\_}VALUE}}{375}
-\entry {\file {libgcc.a}}{387}
-\entry {\code {LIBGCC{\_}NEEDS{\_}DOUBLE}}{389}
-\entry {\code {LIBGCC{\_}SPEC}}{337}
-\entry {\code {LIBGCC2{\_}WORDS{\_}BIG{\_}ENDIAN}}{342}
-\entry {Libraries}{52}
-\entry {library subroutine names}{387}
-\entry {\code {LIBRARY{\_}PATH}}{87}
-\entry {\code {LIMIT{\_}RELOAD{\_}CLASS}}{360}
-\entry {link options}{52}
-\entry {\code {LINK{\_}LIBGCC{\_}SPECIAL}}{337}
-\entry {\code {LINK{\_}LIBGCC{\_}SPECIAL{\_}1}}{337}
-\entry {\code {LINK{\_}SPEC}}{336}
-\entry {\code {lo{\_}sum}}{248}
-\entry {load address instruction}{285}
-\entry {\code {LOAD{\_}EXTEND{\_}OP}}{431}
-\entry {\code {load{\_}multiple} instruction pattern}{297}
-\entry {local labels}{126}
-\entry {local register allocation}{228}
-\entry {local variables in macros}{132}
-\entry {local variables, specifying registers}{164}
-\entry {\code {LOCAL{\_}INCLUDE{\_}DIR}}{338}
-\entry {\code {LOCAL{\_}LABEL{\_}PREFIX}}{418}
-\entry {\code {LOG{\_}LINKS}}{265}
-\entry {logical-and, bitwise}{250}
-\entry {\code {long long} data types}{135}
-\entry {\code {LONG{\_}DOUBLE{\_}TYPE{\_}SIZE}}{349}
-\entry {\code {LONG{\_}LONG{\_}TYPE{\_}SIZE}}{348}
-\entry {\code {LONG{\_}TYPE{\_}SIZE}}{348}
-\entry {\code {longjmp}}{164}
-\entry {\code {longjmp} and automatic variables}{28, 223}
-\entry {\code {longjmp} incompatibilities}{190}
-\entry {\code {longjmp} warnings}{38}
-\entry {\code {LONGJMP{\_}RESTORE{\_}FROM{\_}STACK}}{369}
-\entry {loop optimization}{227}
-\entry {\code {lshiftrt}}{250}
-\entry {\code {lshiftrt} and attributes}{323}
-\entry {\code {lshr\var {m}3} instruction pattern}{299}
-\entry {\code {lt}}{252}
-\entry {\code {lt} and attributes}{323}
-\entry {\code {ltu}}{252}
-\entry {lvalues, generalized}{133}
+\entry {\code {LABEL{\_}NUSES}}{281}
+\entry {\code {LABEL{\_}OUTSIDE{\_}LOOP{\_}P}}{252}
+\entry {\code {LABEL{\_}PRESERVE{\_}P}}{252}
+\entry {\code {label{\_}ref}}{259}
+\entry {\code {label{\_}ref} and \samp {/s}}{252}
+\entry {\code {label{\_}ref}, RTL sharing}{289}
+\entry {labeled elements in initializers}{149}
+\entry {labels as values}{137}
+\entry {\code {labs}}{18}
+\entry {language dialect options}{17}
+\entry {large bit shifts (88k)}{66}
+\entry {large return values}{399}
+\entry {\code {LAST{\_}STACK{\_}REG}}{377}
+\entry {\code {LAST{\_}VIRTUAL{\_}REGISTER}}{261}
+\entry {\code {LD{\_}FINI{\_}SWITCH}}{444}
+\entry {\code {LD{\_}INIT{\_}SWITCH}}{444}
+\entry {\code {LDD{\_}SUFFIX}}{445}
+\entry {\code {ldexp}}{459}
+\entry {\code {le}}{269}
+\entry {\code {le} and attributes}{342}
+\entry {leaf functions}{376}
+\entry {\code {leaf{\_}function}}{377}
+\entry {\code {leaf{\_}function{\_}p}}{323}
+\entry {\code {LEAF{\_}REG{\_}REMAP}}{376}
+\entry {\code {LEAF{\_}REGISTERS}}{376}
+\entry {left rotate}{267}
+\entry {left shift}{267}
+\entry {\code {LEGITIMATE{\_}CONSTANT{\_}P}}{421}
+\entry {\code {LEGITIMATE{\_}PIC{\_}OPERAND{\_}P}}{431}
+\entry {\code {LEGITIMIZE{\_}ADDRESS}}{420}
+\entry {length-zero arrays}{145}
+\entry {less than}{269}
+\entry {less than or equal}{269}
+\entry {\code {leu}}{269}
+\entry {\code {leu} and attributes}{342}
+\entry {\code {LIB{\_}SPEC}}{355}
+\entry {\code {LIB2FUNCS{\_}EXTRA}}{473}
+\entry {\code {LIBCALL{\_}VALUE}}{398}
+\entry {\file {libgcc.a}}{414}
+\entry {\code {LIBGCC{\_}NEEDS{\_}DOUBLE}}{416}
+\entry {\code {LIBGCC{\_}SPEC}}{355}
+\entry {\code {LIBGCC1}}{473}
+\entry {\code {LIBGCC2{\_}CFLAGS}}{473}
+\entry {\code {LIBGCC2{\_}WORDS{\_}BIG{\_}ENDIAN}}{362}
+\entry {Libraries}{48}
+\entry {library subroutine names}{414}
+\entry {\code {LIBRARY{\_}PATH}}{93}
+\entry {\code {LIMIT{\_}RELOAD{\_}CLASS}}{381}
+\entry {link options}{47}
+\entry {\code {LINK{\_}LIBGCC{\_}SPECIAL}}{356}
+\entry {\code {LINK{\_}LIBGCC{\_}SPECIAL{\_}1}}{356}
+\entry {\code {LINK{\_}SPEC}}{355}
+\entry {\code {lo{\_}sum}}{265}
+\entry {load address instruction}{303}
+\entry {\code {LOAD{\_}EXTEND{\_}OP}}{462}
+\entry {\code {load{\_}multiple} instruction pattern}{316}
+\entry {local labels}{136}
+\entry {local register allocation}{243}
+\entry {local variables in macros}{141}
+\entry {local variables, specifying registers}{174}
+\entry {\code {LOCAL{\_}INCLUDE{\_}DIR}}{357}
+\entry {\code {LOCAL{\_}LABEL{\_}PREFIX}}{448}
+\entry {\code {LOG{\_}LINKS}}{283}
+\entry {logical-and, bitwise}{267}
+\entry {\code {long long} data types}{144}
+\entry {\code {LONG{\_}DOUBLE{\_}TYPE{\_}SIZE}}{370}
+\entry {\code {LONG{\_}LONG{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {LONG{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {longjmp}}{173}
+\entry {\code {longjmp} and automatic variables}{19, 237}
+\entry {\code {longjmp} incompatibilities}{202}
+\entry {\code {longjmp} warnings}{30}
+\entry {\code {LONGJMP{\_}RESTORE{\_}FROM{\_}STACK}}{391}
+\entry {loop optimization}{241}
+\entry {\code {lshiftrt}}{267}
+\entry {\code {lshiftrt} and attributes}{342}
+\entry {\code {lshr\var {m}3} instruction pattern}{318}
+\entry {\code {lt}}{269}
+\entry {\code {lt} and attributes}{342}
+\entry {\code {ltu}}{269}
+\entry {lvalues, generalized}{142}
\initial {M}
-\entry {\samp {m} in constraint}{283}
-\entry {M680x0 options}{57}
-\entry {M88k options}{65}
-\entry {machine dependent options}{57}
-\entry {machine description macros}{335}
-\entry {machine descriptions}{273}
-\entry {machine mode conversions}{253}
-\entry {machine modes}{238}
-\entry {machine specific constraints}{290}
-\entry {\code {MACHINE{\_}DEPENDENT{\_}REORG}}{436}
-\entry {macro with variable arguments}{138}
-\entry {macros containing \code {asm}}{160}
-\entry {macros, inline alternative}{156}
-\entry {macros, local labels}{126}
-\entry {macros, local variables in}{132}
-\entry {macros, statements in expressions}{125}
-\entry {macros, target description}{335}
-\entry {macros, types of arguments}{132}
-\entry {\code {main} and the exit status}{219}
-\entry {make}{51}
-\entry {\code {make{\_}safe{\_}from}}{317}
-\entry {\code {match{\_}dup}}{276}
-\entry {\code {match{\_}dup} and attributes}{328}
-\entry {\code {match{\_}op{\_}dup}}{278}
-\entry {\code {match{\_}operand}}{275}
-\entry {\code {match{\_}operand} and attributes}{323}
-\entry {\code {match{\_}operator}}{276}
-\entry {\code {match{\_}par{\_}dup}}{279}
-\entry {\code {match{\_}parallel}}{278}
-\entry {\code {match{\_}scratch}}{276}
-\entry {matching constraint}{284}
-\entry {matching operands}{280}
-\entry {math libraries}{224}
-\entry {math, in RTL}{248}
-\entry {\code {MAX{\_}BITS{\_}PER{\_}WORD}}{343}
-\entry {\code {MAX{\_}CHAR{\_}TYPE{\_}SIZE}}{349}
-\entry {\code {MAX{\_}FIXED{\_}MODE{\_}SIZE}}{347}
-\entry {\code {MAX{\_}INT{\_}TYPE{\_}SIZE}}{348}
-\entry {\code {MAX{\_}LONG{\_}TYPE{\_}SIZE}}{348}
-\entry {\code {MAX{\_}MOVE{\_}MAX}}{431}
-\entry {\code {MAX{\_}OFILE{\_}ALIGNMENT}}{344}
-\entry {\code {MAX{\_}REGS{\_}PER{\_}ADDRESS}}{391}
-\entry {\code {MAX{\_}WCHAR{\_}TYPE{\_}SIZE}}{350}
-\entry {maximum operator}{171}
-\entry {\code {max\var {m}3} instruction pattern}{298}
-\entry {\code {MAYBE{\_}REG{\_}PARM{\_}STACK{\_}SPACE}}{370}
-\entry {\code {mcount}}{381}
-\entry {\code {MD{\_}CALL{\_}PROTOTYPES}}{439}
-\entry {\code {MD{\_}EXEC{\_}PREFIX}}{337}
-\entry {\code {MD{\_}STARTFILE{\_}PREFIX}}{338}
-\entry {\code {MD{\_}STARTFILE{\_}PREFIX{\_}1}}{338}
-\entry {\code {mem}}{248}
-\entry {\code {mem} and \samp {/s}}{235}
-\entry {\code {mem} and \samp {/u}}{235}
-\entry {\code {mem} and \samp {/v}}{235}
-\entry {\code {mem}, RTL sharing}{271}
-\entry {\code {MEM{\_}IN{\_}STRUCT{\_}P}}{235}
-\entry {\code {MEM{\_}VOLATILE{\_}P}}{235}
-\entry {member fns, automatically \code {inline}}{156}
-\entry {\code {memcmp}}{28}
-\entry {\code {memcpy}}{28}
-\entry {\code {memcpy}, implicit usage}{389}
-\entry {memory model (29k)}{63}
-\entry {memory reference, nonoffsettable}{287}
-\entry {memory references in constraints}{283}
-\entry {\code {MEMORY{\_}MOVE{\_}COST}}{397}
-\entry {\code {memset}, implicit usage}{389}
-\entry {messages, warning}{35}
-\entry {messages, warning and error}{202}
-\entry {middle-operands, omitted}{134}
-\entry {\code {MIN{\_}UNITS{\_}PER{\_}WORD}}{343}
-\entry {minimum operator}{171}
-\entry {\code {min\var {m}3} instruction pattern}{298}
-\entry {\code {minus}}{248}
-\entry {\code {minus} and attributes}{323}
-\entry {\code {minus}, canonicalization of}{310}
-\entry {MIPS options}{73}
-\entry {misunderstandings in C{\tt\char43}{\tt\char43}}{196}
-\entry {\code {mktemp}, and constant strings}{190}
-\entry {\code {mod}}{249}
-\entry {\code {mod} and attributes}{323}
-\entry {\code {MODDI3{\_}LIBCALL}}{388}
-\entry {\code {mode} attribute}{152}
-\entry {mode classes}{240}
-\entry {\code {MODE{\_}CC}}{240}
-\entry {\code {MODE{\_}COMPLEX{\_}FLOAT}}{240}
-\entry {\code {MODE{\_}COMPLEX{\_}INT}}{240}
-\entry {\code {MODE{\_}FLOAT}}{240}
-\entry {\code {MODE{\_}FUNCTION}}{240}
-\entry {\code {MODE{\_}INT}}{240}
-\entry {\code {MODE{\_}PARTIAL{\_}INT}}{240}
-\entry {\code {MODE{\_}RANDOM}}{241}
-\entry {\code {MODES{\_}TIEABLE{\_}P}}{354}
-\entry {modifiers in constraints}{289}
-\entry {\code {mod\var {m}3} instruction pattern}{298}
-\entry {\code {MODSI3{\_}LIBCALL}}{388}
-\entry {\code {MOVE{\_}MAX}}{431}
-\entry {\code {MOVE{\_}RATIO}}{398}
-\entry {\code {mov\var {m}} instruction pattern}{296}
-\entry {\code {mov\var {mode}cc} instruction pattern}{301}
-\entry {\code {movstrict\var {m}} instruction pattern}{297}
-\entry {\code {movstr\var {m}} instruction pattern}{299}
-\entry {\code {MULDI3{\_}LIBCALL}}{388}
-\entry {\code {mulhisi3} instruction pattern}{298}
-\entry {\code {mul\var {m}3} instruction pattern}{298}
-\entry {\code {mulqihi3} instruction pattern}{298}
-\entry {\code {MULSI3{\_}LIBCALL}}{387}
-\entry {\code {mulsidi3} instruction pattern}{298}
-\entry {\code {mult}}{249}
-\entry {\code {mult} and attributes}{323}
-\entry {\code {mult}, canonicalization of}{310}
-\entry {\code {MULTIBYTE{\_}CHARS}}{438}
-\entry {multiple alternative constraints}{287}
-\entry {multiplication}{249}
-\entry {multiprecision arithmetic}{135}
-\entry {\code {MUST{\_}PASS{\_}IN{\_}STACK}, and \code {FUNCTION{\_}ARG}}{372}
+\entry {\samp {m} in constraint}{301}
+\entry {M680x0 options}{53}
+\entry {M88k options}{63}
+\entry {machine dependent options}{52}
+\entry {machine description macros}{353}
+\entry {machine descriptions}{291}
+\entry {machine mode conversions}{270}
+\entry {machine modes}{254}
+\entry {machine specific constraints}{308}
+\entry {\code {MACHINE{\_}DEPENDENT{\_}REORG}}{468}
+\entry {\code {MACHINE{\_}STATE{\_}RESTORE}}{408}
+\entry {\code {MACHINE{\_}STATE{\_}SAVE}}{408}
+\entry {macro with variable arguments}{146}
+\entry {macros containing \code {asm}}{170}
+\entry {macros, inline alternative}{166}
+\entry {macros, local labels}{136}
+\entry {macros, local variables in}{141}
+\entry {macros, statements in expressions}{135}
+\entry {macros, target description}{353}
+\entry {macros, types of arguments}{141}
+\entry {\code {main} and the exit status}{232}
+\entry {make}{46}
+\entry {\code {make{\_}safe{\_}from}}{337}
+\entry {makefile fragment}{473}
+\entry {\code {match{\_}dup}}{294}
+\entry {\code {match{\_}dup} and attributes}{347}
+\entry {\code {match{\_}op{\_}dup}}{296}
+\entry {\code {match{\_}operand}}{293}
+\entry {\code {match{\_}operand} and attributes}{342}
+\entry {\code {match{\_}operator}}{294}
+\entry {\code {match{\_}par{\_}dup}}{297}
+\entry {\code {match{\_}parallel}}{296}
+\entry {\code {match{\_}scratch}}{294}
+\entry {matching constraint}{303}
+\entry {matching operands}{298}
+\entry {math libraries}{238}
+\entry {math, in RTL}{265}
+\entry {\code {MAX{\_}BITS{\_}PER{\_}WORD}}{363}
+\entry {\code {MAX{\_}CHAR{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {MAX{\_}FIXED{\_}MODE{\_}SIZE}}{367}
+\entry {\code {MAX{\_}INT{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {MAX{\_}LONG{\_}TYPE{\_}SIZE}}{369}
+\entry {\code {MAX{\_}MOVE{\_}MAX}}{462}
+\entry {\code {MAX{\_}OFILE{\_}ALIGNMENT}}{365}
+\entry {\code {MAX{\_}REGS{\_}PER{\_}ADDRESS}}{419}
+\entry {\code {MAX{\_}WCHAR{\_}TYPE{\_}SIZE}}{371}
+\entry {maximum operator}{181}
+\entry {\code {MAYBE{\_}REG{\_}PARM{\_}STACK{\_}SPACE}}{392}
+\entry {\code {mcount}}{406}
+\entry {\code {MD{\_}CALL{\_}PROTOTYPES}}{471}
+\entry {\code {MD{\_}EXEC{\_}PREFIX}}{357}
+\entry {\code {MD{\_}STARTFILE{\_}PREFIX}}{357}
+\entry {\code {MD{\_}STARTFILE{\_}PREFIX{\_}1}}{357}
+\entry {\code {mem}}{265}
+\entry {\code {mem} and \samp {/s}}{250}
+\entry {\code {mem} and \samp {/u}}{251}
+\entry {\code {mem} and \samp {/v}}{250}
+\entry {\code {mem}, RTL sharing}{289}
+\entry {\code {MEM{\_}IN{\_}STRUCT{\_}P}}{250}
+\entry {\code {MEM{\_}VOLATILE{\_}P}}{250}
+\entry {member fns, automatically \code {inline}}{166}
+\entry {\code {memcmp}}{18}
+\entry {\code {memcpy}}{18}
+\entry {\code {memcpy}, implicit usage}{416}
+\entry {memory model (29k)}{60}
+\entry {memory reference, nonoffsettable}{305}
+\entry {memory references in constraints}{301}
+\entry {\code {MEMORY{\_}MOVE{\_}COST}}{426}
+\entry {\code {memset}, implicit usage}{416}
+\entry {messages, warning}{26}
+\entry {messages, warning and error}{214}
+\entry {middle-operands, omitted}{143}
+\entry {\code {MIN{\_}UNITS{\_}PER{\_}WORD}}{363}
+\entry {minimum operator}{181}
+\entry {\code {minus}}{265}
+\entry {\code {minus} and attributes}{342}
+\entry {\code {minus}, canonicalization of}{331}
+\entry {MIPS options}{75}
+\entry {misunderstandings in C{\tt\char43}{\tt\char43}}{208}
+\entry {\code {mktemp}, and constant strings}{201}
+\entry {\code {mod}}{266}
+\entry {\code {mod} and attributes}{342}
+\entry {\code {MODDI3{\_}LIBCALL}}{415}
+\entry {\code {mode} attribute}{160}
+\entry {mode classes}{256}
+\entry {\code {MODE{\_}CC}}{257}
+\entry {\code {MODE{\_}COMPLEX{\_}FLOAT}}{256}
+\entry {\code {MODE{\_}COMPLEX{\_}INT}}{256}
+\entry {\code {MODE{\_}FLOAT}}{256}
+\entry {\code {MODE{\_}FUNCTION}}{256}
+\entry {\code {MODE{\_}INT}}{256}
+\entry {\code {MODE{\_}PARTIAL{\_}INT}}{256}
+\entry {\code {MODE{\_}RANDOM}}{257}
+\entry {\code {MODES{\_}TIEABLE{\_}P}}{376}
+\entry {modifiers in constraints}{307}
+\entry {\code {mod\var {m}3} instruction pattern}{317}
+\entry {\code {MODSI3{\_}LIBCALL}}{415}
+\entry {\code {MOVE{\_}MAX}}{462}
+\entry {\code {MOVE{\_}RATIO}}{427}
+\entry {\code {mov\var {m}} instruction pattern}{314}
+\entry {\code {mov\var {mode}cc} instruction pattern}{320}
+\entry {\code {movstrict\var {m}} instruction pattern}{316}
+\entry {\code {movstr\var {m}} instruction pattern}{318}
+\entry {\code {MULDI3{\_}LIBCALL}}{415}
+\entry {\code {mulhisi3} instruction pattern}{317}
+\entry {\code {mul\var {m}3} instruction pattern}{317}
+\entry {\code {mulqihi3} instruction pattern}{317}
+\entry {\code {MULSI3{\_}LIBCALL}}{414}
+\entry {\code {mulsidi3} instruction pattern}{317}
+\entry {\code {mult}}{266}
+\entry {\code {mult} and attributes}{342}
+\entry {\code {mult}, canonicalization of}{331}
+\entry {\code {MULTIBYTE{\_}CHARS}}{470}
+\entry {\code {MULTILIB{\_}DEFAULTS}}{356}
+\entry {\code {MULTILIB{\_}DIRNAMES}}{474}
+\entry {\code {MULTILIB{\_}EXCEPTIONS}}{474}
+\entry {\code {MULTILIB{\_}MATCHES}}{474}
+\entry {\code {MULTILIB{\_}OPTIONS}}{473}
+\entry {multiple alternative constraints}{305}
+\entry {multiplication}{266}
+\entry {multiprecision arithmetic}{144}
+\entry {\code {MUST{\_}PASS{\_}IN{\_}STACK}, and \code {FUNCTION{\_}ARG}}{395}
\initial {N}
-\entry {\samp {n} in constraint}{284}
-\entry {\code {N{\_}REG{\_}CLASSES}}{358}
-\entry {name augmentation}{219}
-\entry {named patterns and conditions}{274}
-\entry {named return value in C{\tt\char43}{\tt\char43}}{169}
-\entry {names used in assembler code}{161}
-\entry {names, pattern}{296}
-\entry {naming convention, implementation headers}{173}
-\entry {naming types}{131}
-\entry {\code {ne}}{252}
-\entry {\code {ne} and attributes}{323}
-\entry {\code {neg}}{249}
-\entry {\code {neg} and attributes}{323}
-\entry {\code {neg}, canonicalization of}{310}
-\entry {\code {neg\var {m}2} instruction pattern}{299}
-\entry {nested functions}{128}
-\entry {nested functions, trampolines for}{385}
-\entry {newline vs string constants}{29}
-\entry {\code {next{\_}cc0{\_}user}}{309}
-\entry {\code {NEXT{\_}INSN}}{262}
-\entry {\code {NEXT{\_}OBJC{\_}RUNTIME}}{390}
-\entry {nil}{232}
-\entry {no constraints}{295}
-\entry {no-op move instructions}{229}
-\entry {\code {NO{\_}BUILTIN{\_}PTRDIFF{\_}TYPE}}{336}
-\entry {\code {NO{\_}BUILTIN{\_}SIZE{\_}TYPE}}{335}
-\entry {\code {NO{\_}DOLLAR{\_}IN{\_}LABEL}}{435}
-\entry {\code {NO{\_}DOT{\_}IN{\_}LABEL}}{435}
-\entry {\code {NO{\_}FUNCTION{\_}CSE}}{399}
-\entry {\code {NO{\_}IMPLICIT{\_}EXTERN{\_}C}}{434}
-\entry {\code {NO{\_}MD{\_}PROTOTYPES}}{439}
-\entry {\code {NO{\_}RECURSIVE{\_}FUNCTION{\_}CSE}}{399}
-\entry {\code {NO{\_}REGS}}{357}
-\entry {\code {NO{\_}STAB{\_}H}}{439}
-\entry {\code {NO{\_}SYS{\_}SIGLIST}}{438}
-\entry {\code {nocommon} attribute}{152}
-\entry {non-constant initializers}{140}
-\entry {non-static inline function}{156}
-\entry {\code {NON{\_}SAVING{\_}SETJMP}}{352}
-\entry {\code {nongcc{\_}SI{\_}type}}{390}
-\entry {\code {nongcc{\_}word{\_}type}}{390}
-\entry {nonoffsettable memory reference}{287}
-\entry {\code {nop} instruction pattern}{304}
-\entry {\code {noreturn} function attribute}{145}
-\entry {\code {not}}{250}
-\entry {\code {not} and attributes}{323}
-\entry {not equal}{252}
-\entry {not using constraints}{295}
-\entry {\code {not}, canonicalization of}{310}
-\entry {\code {note}}{264}
-\entry {\code {NOTE{\_}INSN{\_}BLOCK{\_}BEG}}{264}
-\entry {\code {NOTE{\_}INSN{\_}BLOCK{\_}END}}{264}
-\entry {\code {NOTE{\_}INSN{\_}DELETED}}{264}
-\entry {\code {NOTE{\_}INSN{\_}FUNCTION{\_}END}}{264}
-\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}BEG}}{264}
-\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}CONT}}{264}
-\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}END}}{264}
-\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}VTOP}}{264}
-\entry {\code {NOTE{\_}INSN{\_}SETJMP}}{264}
-\entry {\code {NOTE{\_}LINE{\_}NUMBER}}{264}
-\entry {\code {NOTE{\_}SOURCE{\_}FILE}}{264}
-\entry {\code {NOTICE{\_}UPDATE{\_}CC}}{394}
-\entry {\code {NUM{\_}MACHINE{\_}MODES}}{241}
+\entry {\samp {n} in constraint}{302}
+\entry {\code {N{\_}REG{\_}CLASSES}}{380}
+\entry {name augmentation}{232}
+\entry {named patterns and conditions}{291}
+\entry {named return value in C{\tt\char43}{\tt\char43}}{179}
+\entry {names used in assembler code}{171}
+\entry {names, pattern}{314}
+\entry {naming convention, implementation headers}{182}
+\entry {naming types}{141}
+\entry {\code {ne}}{269}
+\entry {\code {ne} and attributes}{342}
+\entry {\code {neg}}{266}
+\entry {\code {neg} and attributes}{342}
+\entry {\code {neg}, canonicalization of}{331}
+\entry {\code {neg\var {m}2} instruction pattern}{318}
+\entry {nested functions}{137}
+\entry {nested functions, trampolines for}{412}
+\entry {newline vs string constants}{20}
+\entry {\code {next{\_}cc0{\_}user}}{329}
+\entry {\code {NEXT{\_}INSN}}{279}
+\entry {\code {NEXT{\_}OBJC{\_}RUNTIME}}{418}
+\entry {nil}{248}
+\entry {no constraints}{314}
+\entry {no-op move instructions}{243}
+\entry {\code {NO{\_}BUILTIN{\_}PTRDIFF{\_}TYPE}}{354}
+\entry {\code {NO{\_}BUILTIN{\_}SIZE{\_}TYPE}}{354}
+\entry {\code {NO{\_}DBX{\_}FUNCTION{\_}END}}{456}
+\entry {\code {NO{\_}DOLLAR{\_}IN{\_}LABEL}}{467}
+\entry {\code {NO{\_}DOT{\_}IN{\_}LABEL}}{467}
+\entry {\code {NO{\_}FUNCTION{\_}CSE}}{427}
+\entry {\code {NO{\_}IMPLICIT{\_}EXTERN{\_}C}}{466}
+\entry {\code {NO{\_}MD{\_}PROTOTYPES}}{471}
+\entry {\code {NO{\_}RECURSIVE{\_}FUNCTION{\_}CSE}}{427}
+\entry {\code {NO{\_}REGS}}{379}
+\entry {\code {NO{\_}STAB{\_}H}}{471}
+\entry {\code {NO{\_}SYS{\_}SIGLIST}}{471}
+\entry {\code {nocommon} attribute}{161}
+\entry {non-constant initializers}{148}
+\entry {non-static inline function}{167}
+\entry {\code {NON{\_}SAVING{\_}SETJMP}}{373}
+\entry {\code {nongcc{\_}SI{\_}type}}{417}
+\entry {\code {nongcc{\_}word{\_}type}}{417}
+\entry {nonoffsettable memory reference}{305}
+\entry {\code {nop} instruction pattern}{324}
+\entry {\code {noreturn} function attribute}{151}
+\entry {\code {not}}{267}
+\entry {\code {not} and attributes}{342}
+\entry {not equal}{269}
+\entry {not using constraints}{314}
+\entry {\code {not}, canonicalization of}{331}
+\entry {\code {note}}{281}
+\entry {\code {NOTE{\_}INSN{\_}BLOCK{\_}BEG}}{281}
+\entry {\code {NOTE{\_}INSN{\_}BLOCK{\_}END}}{281}
+\entry {\code {NOTE{\_}INSN{\_}DELETED}}{281}
+\entry {\code {NOTE{\_}INSN{\_}FUNCTION{\_}END}}{282}
+\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}BEG}}{282}
+\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}CONT}}{282}
+\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}END}}{282}
+\entry {\code {NOTE{\_}INSN{\_}LOOP{\_}VTOP}}{282}
+\entry {\code {NOTE{\_}INSN{\_}SETJMP}}{282}
+\entry {\code {NOTE{\_}LINE{\_}NUMBER}}{281}
+\entry {\code {NOTE{\_}SOURCE{\_}FILE}}{281}
+\entry {\code {NOTICE{\_}UPDATE{\_}CC}}{422}
+\entry {\code {NUM{\_}MACHINE{\_}MODES}}{257}
\initial {O}
-\entry {\samp {o} in constraint}{283}
-\entry {\code {OBJC{\_}GEN{\_}METHOD{\_}LABEL}}{411}
-\entry {\code {OBJC{\_}INCLUDE{\_}PATH}}{87}
-\entry {\code {OBJC{\_}INT{\_}SELECTORS}}{350}
-\entry {\code {OBJC{\_}PROLOGUE}}{404}
-\entry {\code {OBJC{\_}SELECTORS{\_}WITHOUT{\_}LABELS}}{350}
-\entry {\code {OBJECT{\_}FORMAT{\_}COFF}}{415}
-\entry {\code {OBJECT{\_}FORMAT{\_}ROSE}}{415}
-\entry {\code {OBJECT{\_}SUFFIX}}{439}
-\entry {Objective C}{17}
-\entry {\code {OBSTACK{\_}CHUNK{\_}ALLOC}}{438}
-\entry {\code {OBSTACK{\_}CHUNK{\_}FREE}}{438}
-\entry {\code {OBSTACK{\_}CHUNK{\_}SIZE}}{438}
-\entry {\code {obstack{\_}free}}{105}
-\entry {OCS (88k)}{65}
-\entry {offsettable address}{283}
-\entry {old-style function definitions}{148}
-\entry {omitted middle-operands}{134}
-\entry {\code {one{\_}cmpl\var {m}2} instruction pattern}{299}
-\entry {\code {ONLY{\_}INT{\_}FIELDS}}{437}
-\entry {open coding}{156}
-\entry {operand access}{232}
-\entry {operand constraints}{283}
-\entry {operand substitution}{279}
-\entry {\code {operands}}{274}
-\entry {\code {OPTIMIZATION{\_}OPTIONS}}{341}
-\entry {optimize options}{45}
-\entry {optional hardware or system features}{340}
-\entry {options to control warnings}{35}
-\entry {options, C{\tt\char43}{\tt\char43}}{31}
-\entry {options, code generation}{83}
-\entry {options, debugging}{41}
-\entry {options, dialect}{27}
-\entry {options, directory search}{54}
-\entry {options, GNU CC command}{19}
-\entry {options, grouping}{19}
-\entry {options, linking}{52}
-\entry {options, optimization}{45}
-\entry {options, order}{19}
-\entry {options, preprocessor}{49}
-\entry {order of evaluation, side effects}{201}
-\entry {order of options}{19}
-\entry {order of register allocation}{352}
-\entry {\code {ORDER{\_}REGS{\_}FOR{\_}LOCAL{\_}ALLOC}}{353}
-\entry {Ordering of Patterns}{306}
-\entry {other directory, compilation in}{111}
-\entry {\code {OUTGOING{\_}REG{\_}PARM{\_}STACK{\_}SPACE}}{370}
-\entry {\code {OUTGOING{\_}REGNO}}{352}
-\entry {output file option}{26}
-\entry {output of assembler code}{402}
-\entry {output statements}{281}
-\entry {output templates}{279}
-\entry {\code {output{\_}addr{\_}const}}{404}
-\entry {\code {output{\_}asm{\_}insn}}{282}
-\entry {overflow while constant folding}{429}
-\entry {\code {OVERLAPPING{\_}REGNO{\_}P}}{356}
-\entry {overloaded virtual fn, warning}{41}
-\entry {\code {OVERRIDE{\_}OPTIONS}}{341}
+\entry {\samp {o} in constraint}{301}
+\entry {\code {OBJC{\_}GEN{\_}METHOD{\_}LABEL}}{441}
+\entry {\code {OBJC{\_}INCLUDE{\_}PATH}}{93}
+\entry {\code {OBJC{\_}INT{\_}SELECTORS}}{371}
+\entry {\code {OBJC{\_}PROLOGUE}}{433}
+\entry {\code {OBJC{\_}SELECTORS{\_}WITHOUT{\_}LABELS}}{371}
+\entry {\code {OBJECT{\_}FORMAT{\_}COFF}}{445}
+\entry {\code {OBJECT{\_}FORMAT{\_}ROSE}}{445}
+\entry {\code {OBJECT{\_}SUFFIX}}{472}
+\entry {Objective C}{7}
+\entry {\code {OBSTACK{\_}CHUNK{\_}ALLOC}}{470}
+\entry {\code {OBSTACK{\_}CHUNK{\_}FREE}}{470}
+\entry {\code {OBSTACK{\_}CHUNK{\_}SIZE}}{470}
+\entry {\code {obstack{\_}free}}{113}
+\entry {OCS (88k)}{63}
+\entry {offsettable address}{301}
+\entry {old-style function definitions}{157}
+\entry {\code {OLDAR}}{475}
+\entry {\code {OLDCC}}{475}
+\entry {omitted middle-operands}{143}
+\entry {\code {one{\_}cmpl\var {m}2} instruction pattern}{318}
+\entry {\code {ONLY{\_}INT{\_}FIELDS}}{470}
+\entry {open coding}{166}
+\entry {operand access}{248}
+\entry {operand constraints}{301}
+\entry {operand substitution}{298}
+\entry {\code {operands}}{292}
+\entry {\code {OPTIMIZATION{\_}OPTIONS}}{361}
+\entry {optimize options}{39}
+\entry {optional hardware or system features}{360}
+\entry {options to control warnings}{26}
+\entry {options, C{\tt\char43}{\tt\char43}}{21}
+\entry {options, code generation}{88}
+\entry {options, debugging}{33}
+\entry {options, dialect}{17}
+\entry {options, directory search}{50}
+\entry {options, GNU CC command}{9}
+\entry {options, grouping}{9}
+\entry {options, linking}{47}
+\entry {options, optimization}{39}
+\entry {options, order}{9}
+\entry {options, preprocessor}{44}
+\entry {order of evaluation, side effects}{213}
+\entry {order of options}{9}
+\entry {order of register allocation}{374}
+\entry {\code {ORDER{\_}REGS{\_}FOR{\_}LOCAL{\_}ALLOC}}{374}
+\entry {Ordering of Patterns}{327}
+\entry {other directory, compilation in}{121}
+\entry {\code {OUTGOING{\_}REG{\_}PARM{\_}STACK{\_}SPACE}}{393}
+\entry {\code {OUTGOING{\_}REGNO}}{373}
+\entry {output file option}{16}
+\entry {output of assembler code}{431}
+\entry {output statements}{299}
+\entry {output templates}{298}
+\entry {\code {output{\_}addr{\_}const}}{434}
+\entry {\code {output{\_}asm{\_}insn}}{300}
+\entry {overflow while constant folding}{460}
+\entry {\code {OVERLAPPING{\_}REGNO{\_}P}}{377}
+\entry {overloaded virtual fn, warning}{32}
+\entry {\code {OVERRIDE{\_}OPTIONS}}{361}
\initial {P}
-\entry {\samp {p} in constraint}{285}
-\entry {\code {packed} attribute}{152}
-\entry {\code {parallel}}{257}
-\entry {parameter forward declaration}{138}
-\entry {parameters, miscellaneous}{430}
-\entry {\code {PARM{\_}BOUNDARY}}{344}
-\entry {\code {PARSE{\_}LDD{\_}OUTPUT}}{415}
-\entry {parser generator, Bison}{94}
-\entry {parsing pass}{225}
-\entry {passes and files of the compiler}{225}
-\entry {passing arguments}{223}
-\entry {\code {PATH{\_}SEPARATOR}}{439}
-\entry {\code {PATTERN}}{265}
-\entry {pattern conditions}{274}
-\entry {pattern names}{296}
-\entry {Pattern Ordering}{306}
-\entry {patterns}{273}
-\entry {\code {pc}}{248}
-\entry {\code {pc} and attributes}{328}
-\entry {\code {pc}, RTL sharing}{271}
-\entry {\code {pc{\_}rtx}}{248}
-\entry {\code {PCC{\_}BITFIELD{\_}TYPE{\_}MATTERS}}{345}
-\entry {\code {PCC{\_}STATIC{\_}STRUCT{\_}RETURN}}{377}
-\entry {\code {PDImode}}{239}
-\entry {peephole optimization}{229}
-\entry {peephole optimization, RTL representation}{258}
-\entry {peephole optimizer definitions}{311}
-\entry {percent sign}{279}
-\entry {\code {perform{\_}\dots {}}}{390}
-\entry {PIC}{84, 401}
-\entry {\code {PIC{\_}OFFSET{\_}TABLE{\_}REG{\_}CALL{\_}CLOBBERED}}{401}
-\entry {\code {PIC{\_}OFFSET{\_}TABLE{\_}REGNUM}}{401}
-\entry {\code {plus}}{248}
-\entry {\code {plus} and attributes}{323}
-\entry {\code {plus}, canonicalization of}{310}
-\entry {\code {Pmode}}{434}
-\entry {pointer arguments}{146}
-\entry {\code {POINTER{\_}SIZE}}{343}
-\entry {\code {POINTERS{\_}EXTEND{\_}UNSIGNED}}{343}
-\entry {portability}{221}
-\entry {portions of temporary objects, pointers to}{197}
-\entry {position independent code}{401}
-\entry {\code {POSIX}}{438}
-\entry {\code {post{\_}dec}}{260}
-\entry {\code {post{\_}inc}}{260}
-\entry {\code {pragma}}{434}
-\entry {pragma, reason for not using}{147}
-\entry {pragmas in C{\tt\char43}{\tt\char43}, effect on inlining}{173}
-\entry {pragmas, interface and implementation}{172}
-\entry {\code {pre{\_}dec}}{259}
-\entry {\code {pre{\_}inc}}{260}
-\entry {predefined macros}{340}
-\entry {\code {PREDICATE{\_}CODES}}{430}
-\entry {\code {PREFERRED{\_}DEBUGGING{\_}TYPE}}{421}
-\entry {\code {PREFERRED{\_}OUTPUT{\_}RELOAD{\_}CLASS}}{360}
-\entry {\code {PREFERRED{\_}RELOAD{\_}CLASS}}{359}
-\entry {preprocessing numbers}{193}
-\entry {preprocessing tokens}{193}
-\entry {preprocessor options}{49}
-\entry {\code {PRESERVE{\_}DEATH{\_}INFO{\_}REGNO{\_}P}}{357}
-\entry {\code {prev{\_}cc0{\_}setter}}{309}
-\entry {\code {PREV{\_}INSN}}{261}
-\entry {\code {prev{\_}nonnote{\_}insn}}{313}
-\entry {\code {PRINT{\_}OPERAND}}{417}
-\entry {\code {PRINT{\_}OPERAND{\_}ADDRESS}}{417}
-\entry {\code {PRINT{\_}OPERAND{\_}PUNCT{\_}VALID{\_}P}}{417}
-\entry {processor selection (29k)}{63}
-\entry {product}{249}
-\entry {\code {prof}}{43}
-\entry {\code {PROFILE{\_}BEFORE{\_}PROLOGUE}}{381}
-\entry {profiling, code generation}{381}
-\entry {program counter}{248}
-\entry {prologue}{378}
-\entry {\code {PROMOTE{\_}FOR{\_}CALL{\_}ONLY}}{344}
-\entry {\code {PROMOTE{\_}FUNCTION{\_}ARGS}}{344}
-\entry {\code {PROMOTE{\_}FUNCTION{\_}RETURN}}{344}
-\entry {\code {PROMOTE{\_}MODE}}{343}
-\entry {\code {PROMOTE{\_}PROTOTYPES}}{369}
-\entry {promotion of formal parameters}{148}
-\entry {pseudo registers}{244}
-\entry {\code {PSImode}}{239}
-\entry {\code {PTRDIFF{\_}TYPE}}{349}
-\entry {push address instruction}{285}
-\entry {\code {PUSH{\_}ROUNDING}}{369}
-\entry {\code {PUSH{\_}ROUNDING}, interaction with \code {STACK{\_}BOUNDARY}}{344}
-\entry {\code {PUT{\_}CODE}}{231}
-\entry {\code {PUT{\_}MODE}}{241}
-\entry {\code {PUT{\_}REG{\_}NOTE{\_}KIND}}{266}
-\entry {\code {PUT{\_}SDB{\_}\dots {}}}{426}
-\entry {\code {putenv}}{438}
+\entry {\samp {p} in constraint}{303}
+\entry {\code {packed} attribute}{161}
+\entry {\code {parallel}}{275}
+\entry {parameter forward declaration}{146}
+\entry {parameters, miscellaneous}{461}
+\entry {\code {PARM{\_}BOUNDARY}}{364}
+\entry {\code {PARSE{\_}LDD{\_}OUTPUT}}{445}
+\entry {parser generator, Bison}{101}
+\entry {parsing pass}{239}
+\entry {passes and files of the compiler}{239}
+\entry {passing arguments}{237}
+\entry {\code {PATH{\_}SEPARATOR}}{472}
+\entry {\code {PATTERN}}{282}
+\entry {pattern conditions}{291}
+\entry {pattern names}{314}
+\entry {Pattern Ordering}{327}
+\entry {patterns}{291}
+\entry {\code {pc}}{264}
+\entry {\code {pc} and attributes}{347}
+\entry {\code {pc}, RTL sharing}{289}
+\entry {\code {pc{\_}rtx}}{264}
+\entry {\code {PCC{\_}BITFIELD{\_}TYPE{\_}MATTERS}}{366}
+\entry {\code {PCC{\_}STATIC{\_}STRUCT{\_}RETURN}}{400}
+\entry {\code {PDImode}}{255}
+\entry {peephole optimization}{244}
+\entry {peephole optimization, RTL representation}{276}
+\entry {peephole optimizer definitions}{332}
+\entry {percent sign}{298}
+\entry {\code {perform{\_}\dots {}}}{418}
+\entry {PIC}{90, 430}
+\entry {\code {PIC{\_}OFFSET{\_}TABLE{\_}REG{\_}CALL{\_}CLOBBERED}}{430}
+\entry {\code {PIC{\_}OFFSET{\_}TABLE{\_}REGNUM}}{430}
+\entry {\code {plus}}{265}
+\entry {\code {plus} and attributes}{342}
+\entry {\code {plus}, canonicalization of}{331}
+\entry {\code {Pmode}}{465}
+\entry {pointer arguments}{153}
+\entry {\code {POINTER{\_}SIZE}}{363}
+\entry {\code {POINTERS{\_}EXTEND{\_}UNSIGNED}}{363}
+\entry {\code {popen}}{471}
+\entry {portability}{235}
+\entry {portions of temporary objects, pointers to}{208}
+\entry {position independent code}{430}
+\entry {\code {POSIX}}{471}
+\entry {\code {post{\_}dec}}{277}
+\entry {\code {post{\_}inc}}{277}
+\entry {\code {pragma}}{466}
+\entry {pragma, reason for not using}{157}
+\entry {pragmas in C{\tt\char43}{\tt\char43}, effect on inlining}{183}
+\entry {pragmas, interface and implementation}{182}
+\entry {\code {pre{\_}dec}}{277}
+\entry {\code {pre{\_}inc}}{277}
+\entry {predefined macros}{359}
+\entry {\code {PREDICATE{\_}CODES}}{461}
+\entry {\code {PREFERRED{\_}DEBUGGING{\_}TYPE}}{452}
+\entry {\code {PREFERRED{\_}OUTPUT{\_}RELOAD{\_}CLASS}}{381}
+\entry {\code {PREFERRED{\_}RELOAD{\_}CLASS}}{381}
+\entry {preprocessing numbers}{204}
+\entry {preprocessing tokens}{204}
+\entry {preprocessor options}{44}
+\entry {\code {PRESERVE{\_}DEATH{\_}INFO{\_}REGNO{\_}P}}{378}
+\entry {\code {prev{\_}active{\_}insn}}{333}
+\entry {\code {prev{\_}cc0{\_}setter}}{329}
+\entry {\code {PREV{\_}INSN}}{279}
+\entry {\code {PRINT{\_}OPERAND}}{447}
+\entry {\code {PRINT{\_}OPERAND{\_}ADDRESS}}{448}
+\entry {\code {PRINT{\_}OPERAND{\_}PUNCT{\_}VALID{\_}P}}{447}
+\entry {\code {probe} instruction pattern}{326}
+\entry {processor selection (29k)}{60}
+\entry {product}{266}
+\entry {\code {prof}}{35}
+\entry {\code {PROFILE{\_}BEFORE{\_}PROLOGUE}}{406}
+\entry {\code {profile{\_}block{\_}flag}}{406, 407, 408}
+\entry {profiling, code generation}{405}
+\entry {program counter}{264}
+\entry {prologue}{401}
+\entry {\code {PROMOTE{\_}FOR{\_}CALL{\_}ONLY}}{364}
+\entry {\code {PROMOTE{\_}FUNCTION{\_}ARGS}}{364}
+\entry {\code {PROMOTE{\_}FUNCTION{\_}RETURN}}{364}
+\entry {\code {PROMOTE{\_}MODE}}{363}
+\entry {\code {PROMOTE{\_}PROTOTYPES}}{391}
+\entry {promotion of formal parameters}{157}
+\entry {pseudo registers}{260}
+\entry {\code {PSImode}}{255}
+\entry {\code {PTRDIFF{\_}TYPE}}{370}
+\entry {push address instruction}{303}
+\entry {\code {PUSH{\_}ROUNDING}}{391}
+\entry {\code {PUSH{\_}ROUNDING}, interaction with \code {STACK{\_}BOUNDARY}}{364}
+\entry {\code {PUT{\_}CODE}}{247}
+\entry {\code {PUT{\_}MODE}}{257}
+\entry {\code {PUT{\_}REG{\_}NOTE{\_}KIND}}{284}
+\entry {\code {PUT{\_}SDB{\_}\dots {}}}{457}
+\entry {\code {putenv}}{471}
\initial {Q}
-\entry {\samp {Q}, in constraint}{285}
-\entry {\code {QImode}}{239}
-\entry {\code {QImode}, in \code {insn}}{264}
-\entry {\code {qsort}, and global register variables}{163}
-\entry {question mark}{288}
-\entry {quotient}{249}
+\entry {\samp {Q}, in constraint}{303}
+\entry {\code {QImode}}{255}
+\entry {\code {QImode}, in \code {insn}}{282}
+\entry {\code {qsort}, and global register variables}{173}
+\entry {question mark}{306}
+\entry {quotient}{266}
\initial {R}
-\entry {\samp {r} in constraint}{283}
-\entry {r0-relative references (88k)}{66}
-\entry {ranges in case statements}{143}
-\entry {read-only strings}{190}
-\entry {\code {READONLY{\_}DATA{\_}SECTION}}{400}
-\entry {\code {REAL{\_}ARITHMETIC}}{429}
-\entry {\code {REAL{\_}INFINITY}}{428}
-\entry {\code {REAL{\_}NM{\_}FILE{\_}NAME}}{415}
-\entry {\code {REAL{\_}VALUE{\_}ATOF}}{428}
-\entry {\code {REAL{\_}VALUE{\_}FIX}}{428}
-\entry {\code {REAL{\_}VALUE{\_}FROM{\_}INT}}{430}
-\entry {\code {REAL{\_}VALUE{\_}ISINF}}{429}
-\entry {\code {REAL{\_}VALUE{\_}ISNAN}}{429}
-\entry {\code {REAL{\_}VALUE{\_}LDEXP}}{428}
-\entry {\code {REAL{\_}VALUE{\_}NEGATE}}{429}
-\entry {\code {REAL{\_}VALUE{\_}RNDZINT}}{428}
-\entry {\code {REAL{\_}VALUE{\_}TO{\_}DECIMAL}}{406}
-\entry {\code {REAL{\_}VALUE{\_}TO{\_}INT}}{430}
-\entry {\code {REAL{\_}VALUE{\_}TO{\_}TARGET{\_}DOUBLE}}{406}
-\entry {\code {REAL{\_}VALUE{\_}TO{\_}TARGET{\_}LONG{\_}DOUBLE}}{406}
-\entry {\code {REAL{\_}VALUE{\_}TO{\_}TARGET{\_}SINGLE}}{406}
-\entry {\code {REAL{\_}VALUE{\_}TRUNCATE}}{429}
-\entry {\code {REAL{\_}VALUE{\_}TYPE}}{428}
-\entry {\code {REAL{\_}VALUE{\_}UNSIGNED{\_}FIX}}{428}
-\entry {\code {REAL{\_}VALUE{\_}UNSIGNED{\_}RNDZINT}}{428}
-\entry {\code {REAL{\_}VALUES{\_}EQUAL}}{428}
-\entry {\code {REAL{\_}VALUES{\_}LESS}}{428}
-\entry {\code {recog{\_}operand}}{416}
-\entry {recognizing insns}{275}
-\entry {\code {reg}}{244}
-\entry {\code {reg} and \samp {/i}}{235}
-\entry {\code {reg} and \samp {/s}}{235}
-\entry {\code {reg} and \samp {/u}}{235}
-\entry {\code {reg} and \samp {/v}}{235}
-\entry {\code {reg}, RTL sharing}{271}
-\entry {\code {REG{\_}ALLOC{\_}ORDER}}{352}
-\entry {\code {REG{\_}CC{\_}SETTER}}{269}
-\entry {\code {REG{\_}CC{\_}USER}}{269}
-\entry {\code {REG{\_}CLASS{\_}CONTENTS}}{358}
-\entry {\code {REG{\_}CLASS{\_}FROM{\_}LETTER}}{359}
-\entry {\code {REG{\_}CLASS{\_}NAMES}}{358}
-\entry {\code {REG{\_}DEAD}}{266}
-\entry {\code {REG{\_}DEP{\_}ANTI}}{269}
-\entry {\code {REG{\_}DEP{\_}OUTPUT}}{269}
-\entry {\code {REG{\_}EQUAL}}{267}
-\entry {\code {REG{\_}EQUIV}}{267}
-\entry {\code {REG{\_}FUNCTION{\_}VALUE{\_}P}}{235}
-\entry {\code {REG{\_}INC}}{266}
-\entry {\code {REG{\_}LABEL}}{267}
-\entry {\code {REG{\_}LIBCALL}}{269}
-\entry {\code {REG{\_}LOOP{\_}TEST{\_}P}}{235}
-\entry {\code {reg{\_}names}}{417}
-\entry {\code {REG{\_}NO{\_}CONFLICT}}{267}
-\entry {\code {REG{\_}NONNEG}}{266}
-\entry {\code {REG{\_}NOTE{\_}KIND}}{266}
-\entry {\code {REG{\_}NOTES}}{265}
-\entry {\code {REG{\_}OK{\_}FOR{\_}BASE{\_}P}}{392}
-\entry {\code {REG{\_}OK{\_}FOR{\_}INDEX{\_}P}}{392}
-\entry {\code {REG{\_}OK{\_}STRICT}}{391}
-\entry {\code {REG{\_}PARM{\_}STACK{\_}SPACE}}{369}
-\entry {\code {REG{\_}PARM{\_}STACK{\_}SPACE}, and \code {FUNCTION{\_}ARG}}{372}
-\entry {\code {REG{\_}RETVAL}}{268}
-\entry {\code {REG{\_}UNUSED}}{268}
-\entry {\code {REG{\_}USERVAR{\_}P}}{235}
-\entry {\code {REG{\_}WAS{\_}0}}{268}
-\entry {register allocation}{228}
-\entry {register allocation order}{352}
-\entry {register allocation, stupid}{227}
-\entry {register class definitions}{357}
-\entry {register class preference constraints}{288}
-\entry {register class preference pass}{228}
-\entry {register pairs}{354}
-\entry {register positions in frame (88k)}{65}
-\entry {Register Transfer Language (RTL)}{231}
-\entry {register usage}{351}
-\entry {register use analysis}{227}
-\entry {register variable after \code {longjmp}}{164}
-\entry {register-to-stack conversion}{229}
-\entry {\code {REGISTER{\_}MOVE{\_}COST}}{397}
-\entry {\code {REGISTER{\_}NAMES}}{416}
-\entry {\code {register{\_}operand}}{276}
-\entry {\code {REGISTER{\_}PREFIX}}{418}
-\entry {registers}{157}
-\entry {registers arguments}{371}
-\entry {registers for local variables}{164}
-\entry {registers in constraints}{283}
-\entry {registers, global allocation}{162}
-\entry {registers, global variables in}{163}
-\entry {\code {REGNO{\_}OK{\_}FOR{\_}BASE{\_}P}}{359}
-\entry {\code {REGNO{\_}OK{\_}FOR{\_}INDEX{\_}P}}{359}
-\entry {\code {REGNO{\_}REG{\_}CLASS}}{359}
-\entry {\code {regs{\_}ever{\_}live}}{378}
-\entry {relative costs}{396}
-\entry {\code {RELATIVE{\_}PREFIX{\_}NOT{\_}LINKDIR}}{337}
-\entry {reload pass}{246}
-\entry {\code {reload{\_}completed}}{303}
-\entry {\code {reload{\_}in} instruction pattern}{297}
-\entry {\code {reload{\_}in{\_}progress}}{296}
-\entry {\code {reload{\_}out} instruction pattern}{297}
-\entry {reloading}{228}
-\entry {remainder}{249}
-\entry {reordering, warning}{38}
-\entry {reporting bugs}{203}
-\entry {representation of RTL}{231}
-\entry {rest argument (in macro)}{138}
-\entry {\code {rest{\_}of{\_}compilation}}{225}
-\entry {\code {rest{\_}of{\_}decl{\_}compilation}}{225}
-\entry {\code {restore{\_}stack{\_}block} instruction pattern}{305}
-\entry {\code {restore{\_}stack{\_}function} instruction pattern}{305}
-\entry {\code {restore{\_}stack{\_}nonlocal} instruction pattern}{305}
-\entry {\code {return}}{256}
-\entry {\code {return} instruction pattern}{303}
-\entry {return value of \code {main}}{219}
-\entry {return value, named, in C{\tt\char43}{\tt\char43}}{169}
-\entry {return values in registers}{374}
-\entry {\code {return}, in C{\tt\char43}{\tt\char43} function header}{169}
-\entry {\code {RETURN{\_}ADDR{\_}IN{\_}PREVIOUS{\_}FRAME}}{365}
-\entry {\code {RETURN{\_}ADDR{\_}RTX}}{365}
-\entry {\code {RETURN{\_}IN{\_}MEMORY}}{376}
-\entry {\code {RETURN{\_}POPS{\_}ARGS}}{370}
-\entry {returning aggregate values}{376}
-\entry {returning structures and unions}{223}
-\entry {\code {REVERSIBLE{\_}CC{\_}MODE}}{396}
-\entry {right rotate}{250}
-\entry {right shift}{250}
-\entry {\code {rotate}}{250}
-\entry {\code {rotatert}}{250}
-\entry {\code {rotl\var {m}3} instruction pattern}{299}
-\entry {\code {rotr\var {m}3} instruction pattern}{299}
-\entry {\code {ROUND{\_}TYPE{\_}ALIGN}}{347}
-\entry {\code {ROUND{\_}TYPE{\_}SIZE}}{347}
-\entry {RS/6000 and PowerPC Options}{68}
-\entry {RT options}{72}
-\entry {RT PC}{188}
-\entry {RTL addition}{248}
-\entry {RTL comparison}{248}
-\entry {RTL comparison operations}{251}
-\entry {RTL constant expression types}{242}
-\entry {RTL constants}{242}
-\entry {RTL declarations}{254}
-\entry {RTL difference}{248}
-\entry {RTL expression}{231}
-\entry {RTL expressions for arithmetic}{248}
-\entry {RTL format}{232}
-\entry {RTL format characters}{232}
-\entry {RTL function-call insns}{269}
-\entry {RTL generation}{226}
-\entry {RTL insn template}{275}
-\entry {RTL integers}{231}
-\entry {RTL memory expressions}{244}
-\entry {RTL object types}{231}
-\entry {RTL postdecrement}{259}
-\entry {RTL postincrement}{259}
-\entry {RTL predecrement}{259}
-\entry {RTL preincrement}{259}
-\entry {RTL register expressions}{244}
-\entry {RTL representation}{231}
-\entry {RTL side effect expressions}{255}
-\entry {RTL strings}{231}
-\entry {RTL structure sharing assumptions}{271}
-\entry {RTL subtraction}{248}
-\entry {RTL sum}{248}
-\entry {RTL vectors}{231}
-\entry {RTX (See RTL)}{231}
-\entry {\code {RTX{\_}COSTS}}{396}
-\entry {\code {RTX{\_}INTEGRATED{\_}P}}{236}
-\entry {\code {RTX{\_}UNCHANGING{\_}P}}{235}
-\entry {run-time conventions}{223}
-\entry {run-time options}{83}
-\entry {run-time target specification}{340}
+\entry {\samp {r} in constraint}{301}
+\entry {r0-relative references (88k)}{64}
+\entry {ranges in case statements}{150}
+\entry {read-only strings}{201}
+\entry {\code {READONLY{\_}DATA{\_}SECTION}}{429}
+\entry {\code {REAL{\_}ARITHMETIC}}{460}
+\entry {\code {REAL{\_}INFINITY}}{459}
+\entry {\code {REAL{\_}NM{\_}FILE{\_}NAME}}{445}
+\entry {\code {REAL{\_}VALUE{\_}ATOF}}{459}
+\entry {\code {REAL{\_}VALUE{\_}FIX}}{459}
+\entry {\code {REAL{\_}VALUE{\_}FROM{\_}INT}}{461}
+\entry {\code {REAL{\_}VALUE{\_}ISINF}}{459}
+\entry {\code {REAL{\_}VALUE{\_}ISNAN}}{460}
+\entry {\code {REAL{\_}VALUE{\_}LDEXP}}{459}
+\entry {\code {REAL{\_}VALUE{\_}NEGATE}}{460}
+\entry {\code {REAL{\_}VALUE{\_}RNDZINT}}{459}
+\entry {\code {REAL{\_}VALUE{\_}TO{\_}DECIMAL}}{436}
+\entry {\code {REAL{\_}VALUE{\_}TO{\_}INT}}{460}
+\entry {\code {REAL{\_}VALUE{\_}TO{\_}TARGET{\_}DOUBLE}}{435}
+\entry {\code {REAL{\_}VALUE{\_}TO{\_}TARGET{\_}LONG{\_}DOUBLE}}{435}
+\entry {\code {REAL{\_}VALUE{\_}TO{\_}TARGET{\_}SINGLE}}{435}
+\entry {\code {REAL{\_}VALUE{\_}TRUNCATE}}{460}
+\entry {\code {REAL{\_}VALUE{\_}TYPE}}{458}
+\entry {\code {REAL{\_}VALUE{\_}UNSIGNED{\_}FIX}}{459}
+\entry {\code {REAL{\_}VALUE{\_}UNSIGNED{\_}RNDZINT}}{459}
+\entry {\code {REAL{\_}VALUES{\_}EQUAL}}{458}
+\entry {\code {REAL{\_}VALUES{\_}LESS}}{459}
+\entry {\code {recog{\_}operand}}{446}
+\entry {recognizing insns}{293}
+\entry {\code {reg}}{260}
+\entry {\code {reg} and \samp {/i}}{251}
+\entry {\code {reg} and \samp {/s}}{251}
+\entry {\code {reg} and \samp {/u}}{251}
+\entry {\code {reg} and \samp {/v}}{251}
+\entry {\code {reg}, RTL sharing}{289}
+\entry {\code {REG{\_}ALLOC{\_}ORDER}}{374}
+\entry {\code {REG{\_}CC{\_}SETTER}}{287}
+\entry {\code {REG{\_}CC{\_}USER}}{287}
+\entry {\code {REG{\_}CLASS{\_}CONTENTS}}{380}
+\entry {\code {REG{\_}CLASS{\_}FROM{\_}LETTER}}{380}
+\entry {\code {REG{\_}CLASS{\_}NAMES}}{380}
+\entry {\code {REG{\_}DEAD}}{284}
+\entry {\code {REG{\_}DEP{\_}ANTI}}{287}
+\entry {\code {REG{\_}DEP{\_}OUTPUT}}{287}
+\entry {\code {REG{\_}EQUAL}}{285}
+\entry {\code {REG{\_}EQUIV}}{285}
+\entry {\code {REG{\_}FUNCTION{\_}VALUE{\_}P}}{251}
+\entry {\code {REG{\_}INC}}{284}
+\entry {\code {REG{\_}LABEL}}{285}
+\entry {\code {REG{\_}LIBCALL}}{287}
+\entry {\code {REG{\_}LOOP{\_}TEST{\_}P}}{251}
+\entry {\code {reg{\_}names}}{447}
+\entry {\code {REG{\_}NO{\_}CONFLICT}}{284}
+\entry {\code {REG{\_}NONNEG}}{284}
+\entry {\code {REG{\_}NOTE{\_}KIND}}{284}
+\entry {\code {REG{\_}NOTES}}{283}
+\entry {\code {REG{\_}OK{\_}FOR{\_}BASE{\_}P}}{420}
+\entry {\code {REG{\_}OK{\_}FOR{\_}INDEX{\_}P}}{420}
+\entry {\code {REG{\_}OK{\_}STRICT}}{419}
+\entry {\code {REG{\_}PARM{\_}STACK{\_}SPACE}}{392}
+\entry {\code {REG{\_}PARM{\_}STACK{\_}SPACE}, and \code {FUNCTION{\_}ARG}}{395}
+\entry {\code {REG{\_}RETVAL}}{286}
+\entry {\code {REG{\_}UNUSED}}{286}
+\entry {\code {REG{\_}USERVAR{\_}P}}{251}
+\entry {\code {REG{\_}WAS{\_}0}}{286}
+\entry {register allocation}{243}
+\entry {register allocation order}{374}
+\entry {register allocation, stupid}{242}
+\entry {register class definitions}{378}
+\entry {register class preference constraints}{306}
+\entry {register class preference pass}{242}
+\entry {register pairs}{375}
+\entry {register positions in frame (88k)}{63, 64}
+\entry {Register Transfer Language (RTL)}{247}
+\entry {register usage}{372}
+\entry {register use analysis}{241}
+\entry {register variable after \code {longjmp}}{173}
+\entry {register-to-stack conversion}{244}
+\entry {\code {REGISTER{\_}MOVE{\_}COST}}{425}
+\entry {\code {REGISTER{\_}NAMES}}{446}
+\entry {\code {register{\_}operand}}{294}
+\entry {\code {REGISTER{\_}PREFIX}}{448}
+\entry {registers}{167}
+\entry {registers arguments}{394}
+\entry {registers for local variables}{174}
+\entry {registers in constraints}{301}
+\entry {registers, global allocation}{172}
+\entry {registers, global variables in}{172}
+\entry {\code {REGNO{\_}OK{\_}FOR{\_}BASE{\_}P}}{381}
+\entry {\code {REGNO{\_}OK{\_}FOR{\_}INDEX{\_}P}}{381}
+\entry {\code {REGNO{\_}REG{\_}CLASS}}{380}
+\entry {\code {regs{\_}ever{\_}live}}{402}
+\entry {relative costs}{424}
+\entry {\code {RELATIVE{\_}PREFIX{\_}NOT{\_}LINKDIR}}{357}
+\entry {reload pass}{263}
+\entry {\code {reload{\_}completed}}{323}
+\entry {\code {reload{\_}in} instruction pattern}{316}
+\entry {\code {reload{\_}in{\_}progress}}{315}
+\entry {\code {reload{\_}out} instruction pattern}{316}
+\entry {reloading}{243}
+\entry {remainder}{266}
+\entry {reordering, warning}{29}
+\entry {reporting bugs}{215}
+\entry {representation of RTL}{247}
+\entry {rest argument (in macro)}{146}
+\entry {\code {rest{\_}of{\_}compilation}}{239}
+\entry {\code {rest{\_}of{\_}decl{\_}compilation}}{239}
+\entry {\code {restore{\_}stack{\_}block} instruction pattern}{325}
+\entry {\code {restore{\_}stack{\_}function} instruction pattern}{325}
+\entry {\code {restore{\_}stack{\_}nonlocal} instruction pattern}{325}
+\entry {\code {return}}{273}
+\entry {\code {return} instruction pattern}{323}
+\entry {return value of \code {main}}{232}
+\entry {return value, named, in C{\tt\char43}{\tt\char43}}{179}
+\entry {return values in registers}{398}
+\entry {\code {return}, in C{\tt\char43}{\tt\char43} function header}{179}
+\entry {\code {RETURN{\_}ADDR{\_}IN{\_}PREVIOUS{\_}FRAME}}{388}
+\entry {\code {RETURN{\_}ADDR{\_}RTX}}{387}
+\entry {\code {RETURN{\_}ADDRESS{\_}POINTER{\_}REGNUM}}{389}
+\entry {\code {RETURN{\_}IN{\_}MEMORY}}{399}
+\entry {\code {RETURN{\_}POPS{\_}ARGS}}{393}
+\entry {returning aggregate values}{399}
+\entry {returning structures and unions}{237}
+\entry {\code {REVERSIBLE{\_}CC{\_}MODE}}{423}
+\entry {right rotate}{267}
+\entry {right shift}{267}
+\entry {\code {rotate}}{267}
+\entry {\code {rotatert}}{267}
+\entry {\code {rotl\var {m}3} instruction pattern}{318}
+\entry {\code {rotr\var {m}3} instruction pattern}{318}
+\entry {\code {ROUND{\_}TYPE{\_}ALIGN}}{367}
+\entry {\code {ROUND{\_}TYPE{\_}SIZE}}{367}
+\entry {RS/6000 and PowerPC Options}{66}
+\entry {RT options}{74}
+\entry {RT PC}{199}
+\entry {RTL addition}{265}
+\entry {RTL comparison}{265}
+\entry {RTL comparison operations}{268}
+\entry {RTL constant expression types}{258}
+\entry {RTL constants}{258}
+\entry {RTL declarations}{272}
+\entry {RTL difference}{265}
+\entry {RTL expression}{247}
+\entry {RTL expressions for arithmetic}{265}
+\entry {RTL format}{248}
+\entry {RTL format characters}{248}
+\entry {RTL function-call insns}{287}
+\entry {RTL generation}{240}
+\entry {RTL insn template}{293}
+\entry {RTL integers}{247}
+\entry {RTL memory expressions}{260}
+\entry {RTL object types}{247}
+\entry {RTL postdecrement}{277}
+\entry {RTL postincrement}{277}
+\entry {RTL predecrement}{277}
+\entry {RTL preincrement}{277}
+\entry {RTL register expressions}{260}
+\entry {RTL representation}{247}
+\entry {RTL side effect expressions}{272}
+\entry {RTL strings}{247}
+\entry {RTL structure sharing assumptions}{288}
+\entry {RTL subtraction}{265}
+\entry {RTL sum}{265}
+\entry {RTL vectors}{247}
+\entry {RTX (See RTL)}{247}
+\entry {\code {RTX{\_}COSTS}}{424}
+\entry {\code {RTX{\_}INTEGRATED{\_}P}}{251}
+\entry {\code {RTX{\_}UNCHANGING{\_}P}}{251}
+\entry {run-time conventions}{237}
+\entry {run-time options}{88}
+\entry {run-time target specification}{359}
\initial {S}
-\entry {\samp {s} in constraint}{284}
-\entry {\code {save{\_}stack{\_}block} instruction pattern}{305}
-\entry {\code {save{\_}stack{\_}function} instruction pattern}{305}
-\entry {\code {save{\_}stack{\_}nonlocal} instruction pattern}{305}
-\entry {\code {saveable{\_}obstack}}{392}
-\entry {scalars, returned as values}{374}
-\entry {\code {scanf}, and constant strings}{190}
-\entry {\code {SCCS{\_}DIRECTIVE}}{434}
-\entry {\code {SCHED{\_}GROUP{\_}P}}{237}
-\entry {scheduling, delayed branch}{229}
-\entry {scheduling, instruction}{228}
-\entry {\code {SCmode}}{239}
-\entry {\code {s\var {cond}} instruction pattern}{301}
-\entry {scope of a variable length array}{137}
-\entry {scope of declaration}{195}
-\entry {scope of external declarations}{191}
-\entry {\code {scratch}}{246}
-\entry {scratch operands}{246}
-\entry {\code {scratch}, RTL sharing}{271}
-\entry {\code {SDB{\_}ALLOW{\_}FORWARD{\_}REFERENCES}}{427}
-\entry {\code {SDB{\_}ALLOW{\_}UNKNOWN{\_}REFERENCES}}{427}
-\entry {\code {SDB{\_}DEBUGGING{\_}INFO}}{426}
-\entry {\code {SDB{\_}DELIM}}{427}
-\entry {\code {SDB{\_}GENERATE{\_}FAKE}}{427}
-\entry {search path}{54}
-\entry {second include path}{50}
-\entry {\code {SECONDARY{\_}INPUT{\_}RELOAD{\_}CLASS}}{360}
-\entry {\code {SECONDARY{\_}MEMORY{\_}NEEDED}}{361}
-\entry {\code {SECONDARY{\_}MEMORY{\_}NEEDED{\_}MODE}}{362}
-\entry {\code {SECONDARY{\_}MEMORY{\_}NEEDED{\_}RTX}}{361}
-\entry {\code {SECONDARY{\_}OUTPUT{\_}RELOAD{\_}CLASS}}{360}
-\entry {\code {SECONDARY{\_}RELOAD{\_}CLASS}}{360}
-\entry {\code {section} function attribute}{146}
-\entry {\code {section} variable attribute}{152}
-\entry {\code {SELECT{\_}CC{\_}MODE}}{395}
-\entry {\code {SELECT{\_}RTX{\_}SECTION}}{400}
-\entry {\code {SELECT{\_}SECTION}}{400}
-\entry {separate directory, compilation in}{111}
-\entry {\code {sequence}}{258}
-\entry {sequential consistency on 88k}{66}
-\entry {\code {set}}{255}
-\entry {\code {set{\_}attr}}{326}
-\entry {\code {set{\_}attr{\_}alternative}}{326}
-\entry {\code {SET{\_}DEFAULT{\_}TYPE{\_}ATTRIBUTES}}{435}
-\entry {\code {SET{\_}DEST}}{256}
-\entry {\code {SET{\_}SRC}}{256}
-\entry {\code {setjmp}}{164}
-\entry {\code {setjmp} incompatibilities}{190}
-\entry {\code {SETUP{\_}FRAME{\_}ADDRESSES}}{365}
-\entry {\code {SETUP{\_}INCOMING{\_}VARARGS}}{384}
-\entry {\code {SFmode}}{239}
-\entry {shared strings}{190}
-\entry {shared VMS run time system}{219}
-\entry {\code {SHARED{\_}SECTION{\_}ASM{\_}OP}}{399}
-\entry {sharing of RTL components}{271}
-\entry {shift}{250}
-\entry {\code {SHIFT{\_}COUNT{\_}TRUNCATED}}{431}
-\entry {\code {SHORT{\_}TYPE{\_}SIZE}}{348}
-\entry {side effect in ?:}{135}
-\entry {side effects, macro argument}{126}
-\entry {side effects, order of evaluation}{201}
-\entry {\code {sign{\_}extend}}{254}
-\entry {\code {sign{\_}extract}}{253}
-\entry {\code {sign{\_}extract}, canonicalization of}{311}
-\entry {\code {signature}}{176}
-\entry {\code {signature} in C{\tt\char43}{\tt\char43}, advantages}{177}
-\entry {signature member function default implementation}{177}
-\entry {signatures, C{\tt\char43}{\tt\char43}}{176}
-\entry {signed division}{249}
-\entry {signed maximum}{250}
-\entry {signed minimum}{250}
-\entry {\code {SIGNED{\_}CHAR{\_}SPEC}}{336}
-\entry {\code {SImode}}{239}
-\entry {simple constraints}{283}
-\entry {simplifications, arithmetic}{225}
-\entry {\code {sin}}{28}
-\entry {\code {SIZE{\_}TYPE}}{349}
-\entry {\code {sizeof}}{132}
-\entry {\code {SLOW{\_}BYTE{\_}ACCESS}}{398}
-\entry {\code {SLOW{\_}UNALIGNED{\_}ACCESS}}{398}
-\entry {\code {SLOW{\_}ZERO{\_}EXTEND}}{398}
-\entry {\code {SMALL{\_}REGISTER{\_}CLASSES}}{362}
-\entry {smaller data references (88k)}{66}
-\entry {smaller data references (MIPS)}{75}
-\entry {\code {smax}}{250}
-\entry {\code {smin}}{250}
-\entry {\code {smul\var {m}3{\_}highpart} instruction pattern}{298}
-\entry {SPARC options}{59}
-\entry {specified registers}{162}
-\entry {specifying compiler version and target machine}{55}
-\entry {specifying hardware config}{57}
-\entry {specifying machine version}{55}
-\entry {specifying registers for local variables}{164}
-\entry {speed of instructions}{396}
-\entry {splitting instructions}{318}
-\entry {\code {sqrt}}{28, 250}
-\entry {\code {sqrt\var {m}2} instruction pattern}{299}
-\entry {square root}{250}
-\entry {\code {sscanf}, and constant strings}{190}
-\entry {stack arguments}{369}
-\entry {stack checks (29k)}{64}
-\entry {stack frame layout}{364}
-\entry {\code {STACK{\_}BOUNDARY}}{344}
-\entry {\code {STACK{\_}DYNAMIC{\_}OFFSET}}{365}
-\entry {\code {STACK{\_}DYNAMIC{\_}OFFSET} and virtual registers}{245}
-\entry {\code {STACK{\_}GROWS{\_}DOWNWARD}}{364}
-\entry {\code {STACK{\_}PARMS{\_}IN{\_}REG{\_}PARM{\_}AREA}}{370}
-\entry {\code {STACK{\_}POINTER{\_}OFFSET}}{364}
-\entry {\code {STACK{\_}POINTER{\_}OFFSET} and virtual registers}{245}
-\entry {\code {STACK{\_}POINTER{\_}REGNUM}}{366}
-\entry {\code {STACK{\_}POINTER{\_}REGNUM} and virtual registers}{245}
-\entry {\code {stack{\_}pointer{\_}rtx}}{367}
-\entry {\code {STACK{\_}REGS}}{356}
-\entry {stage1}{95}
-\entry {standard pattern names}{296}
-\entry {\code {STANDARD{\_}EXEC{\_}PREFIX}}{337}
-\entry {\code {STANDARD{\_}INCLUDE{\_}DIR}}{338}
-\entry {\code {STANDARD{\_}STARTFILE{\_}PREFIX}}{337}
-\entry {start files}{114}
-\entry {\code {STARTFILE{\_}SPEC}}{337}
-\entry {\code {STARTING{\_}FRAME{\_}OFFSET}}{364}
-\entry {\code {STARTING{\_}FRAME{\_}OFFSET} and virtual registers}{245}
-\entry {statements inside expressions}{125}
-\entry {static data in C{\tt\char43}{\tt\char43}, declaring and defining}{196}
-\entry {\code {STATIC{\_}CHAIN}}{367}
-\entry {\code {STATIC{\_}CHAIN{\_}INCOMING}}{367}
-\entry {\code {STATIC{\_}CHAIN{\_}INCOMING{\_}REGNUM}}{366}
-\entry {\code {STATIC{\_}CHAIN{\_}REGNUM}}{366}
-\entry {\file {stdarg.h} and register arguments}{372}
-\entry {\file {stdarg.h} and RT PC}{72}
-\entry {storage layout}{342}
-\entry {\code {STORE{\_}FLAG{\_}VALUE}}{432}
-\entry {\samp {store{\_}multiple} instruction pattern}{298}
-\entry {storem bug (29k)}{64}
-\entry {\code {strcmp}}{28}
-\entry {\code {strcpy}}{28, 345}
-\entry {strength-reduction}{227}
-\entry {\code {STRICT{\_}ALIGNMENT}}{345}
-\entry {\code {STRICT{\_}ARGUMENT{\_}NAMING}}{384}
-\entry {\code {strict{\_}low{\_}part}}{255}
-\entry {string constants}{190}
-\entry {string constants vs newline}{29}
-\entry {\code {STRIP{\_}NAME{\_}ENCODING}}{401}
-\entry {\code {strlen}}{28}
-\entry {\code {strlen\var {m}} instruction pattern}{300}
-\entry {\code {STRUCT{\_}VALUE}}{377}
-\entry {\code {STRUCT{\_}VALUE{\_}INCOMING}}{377}
-\entry {\code {STRUCT{\_}VALUE{\_}INCOMING{\_}REGNUM}}{377}
-\entry {\code {STRUCT{\_}VALUE{\_}REGNUM}}{377}
-\entry {structure passing (88k)}{68}
-\entry {structure value address}{376}
-\entry {\code {STRUCTURE{\_}SIZE{\_}BOUNDARY}}{345}
-\entry {structures}{192}
-\entry {structures, constructor expression}{140}
-\entry {structures, returning}{223}
-\entry {stupid register allocation}{227}
-\entry {\code {sub\var {m}3} instruction pattern}{298}
-\entry {submodel options}{57}
-\entry {\code {subreg}}{245}
-\entry {\code {subreg} and \samp {/s}}{235}
-\entry {\code {subreg} and \samp {/u}}{235}
-\entry {\code {subreg}, in \code {strict{\_}low{\_}part}}{255}
-\entry {\code {subreg}, special reload handling}{246}
-\entry {\code {SUBREG{\_}PROMOTED{\_}UNSIGNED{\_}P}}{235}
-\entry {\code {SUBREG{\_}PROMOTED{\_}VAR{\_}P}}{235}
-\entry {\code {SUBREG{\_}REG}}{246}
-\entry {\code {SUBREG{\_}WORD}}{246}
-\entry {subscripting}{139}
-\entry {subscripting and function values}{139}
-\entry {subtype polymorphism, C{\tt\char43}{\tt\char43}}{176}
-\entry {\code {SUCCESS{\_}EXIT{\_}CODE}}{437}
-\entry {suffixes for C{\tt\char43}{\tt\char43} source}{26}
-\entry {Sun installation}{118}
-\entry {\code {SUPPORTS{\_}WEAK}}{409}
-\entry {suppressing warnings}{35}
-\entry {surprises in C{\tt\char43}{\tt\char43}}{196}
-\entry {SVr4}{66}
-\entry {\code {SWITCH{\_}TAKES{\_}ARG}}{335}
-\entry {\code {SWITCHES{\_}NEED{\_}SPACES}}{335}
-\entry {\code {symbol{\_}ref}}{243}
-\entry {\code {symbol{\_}ref} and \samp {/u}}{236}
-\entry {\code {symbol{\_}ref} and \samp {/v}}{236}
-\entry {\code {symbol{\_}ref}, RTL sharing}{271}
-\entry {\code {SYMBOL{\_}REF{\_}FLAG}}{236}
-\entry {\code {SYMBOL{\_}REF{\_}FLAG}, in \code {ENCODE{\_}SECTION{\_}INFO}}{401}
-\entry {\code {SYMBOL{\_}REF{\_}USED}}{236}
-\entry {symbolic label}{271}
-\entry {syntax checking}{35}
-\entry {synthesized methods, warning}{41}
-\entry {\code {sys{\_}siglist}}{439}
-\entry {\code {SYSTEM{\_}INCLUDE{\_}DIR}}{338}
+\entry {\samp {s} in constraint}{302}
+\entry {\code {save{\_}stack{\_}block} instruction pattern}{325}
+\entry {\code {save{\_}stack{\_}function} instruction pattern}{325}
+\entry {\code {save{\_}stack{\_}nonlocal} instruction pattern}{325}
+\entry {\code {saveable{\_}obstack}}{420}
+\entry {scalars, returned as values}{398}
+\entry {\code {scanf}, and constant strings}{201}
+\entry {\code {SCCS{\_}DIRECTIVE}}{466}
+\entry {\code {SCHED{\_}GROUP{\_}P}}{253}
+\entry {scheduling, delayed branch}{243}
+\entry {scheduling, instruction}{242, 243}
+\entry {\code {SCmode}}{256}
+\entry {\code {s\var {cond}} instruction pattern}{321}
+\entry {scope of a variable length array}{145}
+\entry {scope of declaration}{206}
+\entry {scope of external declarations}{203}
+\entry {\code {scratch}}{263}
+\entry {scratch operands}{263}
+\entry {\code {scratch}, RTL sharing}{289}
+\entry {\code {SDB{\_}ALLOW{\_}FORWARD{\_}REFERENCES}}{458}
+\entry {\code {SDB{\_}ALLOW{\_}UNKNOWN{\_}REFERENCES}}{458}
+\entry {\code {SDB{\_}DEBUGGING{\_}INFO}}{457}
+\entry {\code {SDB{\_}DELIM}}{457}
+\entry {\code {SDB{\_}GENERATE{\_}FAKE}}{457}
+\entry {search path}{50}
+\entry {second include path}{45}
+\entry {\code {SECONDARY{\_}INPUT{\_}RELOAD{\_}CLASS}}{382}
+\entry {\code {SECONDARY{\_}MEMORY{\_}NEEDED}}{383}
+\entry {\code {SECONDARY{\_}MEMORY{\_}NEEDED{\_}MODE}}{383}
+\entry {\code {SECONDARY{\_}MEMORY{\_}NEEDED{\_}RTX}}{383}
+\entry {\code {SECONDARY{\_}OUTPUT{\_}RELOAD{\_}CLASS}}{382}
+\entry {\code {SECONDARY{\_}RELOAD{\_}CLASS}}{382}
+\entry {\code {section} function attribute}{154}
+\entry {\code {section} variable attribute}{161}
+\entry {\code {SELECT{\_}CC{\_}MODE}}{423}
+\entry {\code {SELECT{\_}RTX{\_}SECTION}}{429}
+\entry {\code {SELECT{\_}SECTION}}{429}
+\entry {separate directory, compilation in}{121}
+\entry {\code {sequence}}{276}
+\entry {sequential consistency on 88k}{64}
+\entry {\code {set}}{272}
+\entry {\code {set{\_}attr}}{345}
+\entry {\code {set{\_}attr{\_}alternative}}{345}
+\entry {\code {SET{\_}DEFAULT{\_}TYPE{\_}ATTRIBUTES}}{466}
+\entry {\code {SET{\_}DEST}}{273}
+\entry {\code {SET{\_}SRC}}{273}
+\entry {\code {setjmp}}{173}
+\entry {\code {setjmp} incompatibilities}{202}
+\entry {\code {SETUP{\_}FRAME{\_}ADDRESSES}}{387}
+\entry {\code {SETUP{\_}INCOMING{\_}VARARGS}}{411}
+\entry {\code {SFmode}}{255}
+\entry {shared strings}{201}
+\entry {shared VMS run time system}{232}
+\entry {\code {SHARED{\_}BSS{\_}SECTION{\_}ASM{\_}OP}}{428}
+\entry {\code {SHARED{\_}SECTION{\_}ASM{\_}OP}}{428}
+\entry {sharing of RTL components}{288}
+\entry {shift}{267}
+\entry {\code {SHIFT{\_}COUNT{\_}TRUNCATED}}{463}
+\entry {\code {SHORT{\_}TYPE{\_}SIZE}}{369}
+\entry {side effect in ?:}{143}
+\entry {side effects, macro argument}{135}
+\entry {side effects, order of evaluation}{213}
+\entry {\code {sign{\_}extend}}{270}
+\entry {\code {sign{\_}extract}}{270}
+\entry {\code {sign{\_}extract}, canonicalization of}{332}
+\entry {\code {signature}}{186}
+\entry {\code {signature} in C{\tt\char43}{\tt\char43}, advantages}{187}
+\entry {signature member function default implementation}{187}
+\entry {signatures, C{\tt\char43}{\tt\char43}}{186}
+\entry {signed and unsigned values, comparison warning}{29}
+\entry {signed division}{266}
+\entry {signed maximum}{266}
+\entry {signed minimum}{266}
+\entry {\code {SIGNED{\_}CHAR{\_}SPEC}}{354}
+\entry {\code {SImode}}{255}
+\entry {simple constraints}{301}
+\entry {simplifications, arithmetic}{239}
+\entry {\code {sin}}{18}
+\entry {\code {SIZE{\_}TYPE}}{370}
+\entry {\code {sizeof}}{141}
+\entry {\code {SLOW{\_}BYTE{\_}ACCESS}}{426}
+\entry {\code {SLOW{\_}UNALIGNED{\_}ACCESS}}{426}
+\entry {\code {SLOW{\_}ZERO{\_}EXTEND}}{426}
+\entry {\code {SMALL{\_}REGISTER{\_}CLASSES}}{384}
+\entry {smaller data references (88k)}{64}
+\entry {smaller data references (MIPS)}{78}
+\entry {smaller data references (PowerPC)}{74}
+\entry {\code {smax}}{266}
+\entry {\code {smax\var {m}3} instruction pattern}{317}
+\entry {\code {smin}}{266}
+\entry {\code {smin\var {m}3} instruction pattern}{317}
+\entry {\code {smul\var {m}3{\_}highpart} instruction pattern}{317}
+\entry {SPARC options}{55}
+\entry {specified registers}{172}
+\entry {specifying compiler version and target machine}{51}
+\entry {specifying hardware config}{52}
+\entry {specifying machine version}{51}
+\entry {specifying registers for local variables}{174}
+\entry {speed of instructions}{424}
+\entry {splitting instructions}{338}
+\entry {\code {sqrt}}{18, 267}
+\entry {\code {sqrt\var {m}2} instruction pattern}{318}
+\entry {square root}{267}
+\entry {\code {sscanf}, and constant strings}{201}
+\entry {stack arguments}{391}
+\entry {stack checks (29k)}{61}
+\entry {stack frame layout}{386}
+\entry {\code {STACK{\_}BOUNDARY}}{364}
+\entry {\code {STACK{\_}DYNAMIC{\_}OFFSET}}{387}
+\entry {\code {STACK{\_}DYNAMIC{\_}OFFSET} and virtual registers}{262}
+\entry {\code {STACK{\_}GROWS{\_}DOWNWARD}}{386}
+\entry {\code {STACK{\_}PARMS{\_}IN{\_}REG{\_}PARM{\_}AREA}}{393}
+\entry {\code {STACK{\_}POINTER{\_}OFFSET}}{387}
+\entry {\code {STACK{\_}POINTER{\_}OFFSET} and virtual registers}{262}
+\entry {\code {STACK{\_}POINTER{\_}REGNUM}}{388}
+\entry {\code {STACK{\_}POINTER{\_}REGNUM} and virtual registers}{262}
+\entry {\code {stack{\_}pointer{\_}rtx}}{389}
+\entry {\code {STACK{\_}REGS}}{377}
+\entry {stage1}{102}
+\entry {standard pattern names}{314}
+\entry {\code {STANDARD{\_}EXEC{\_}PREFIX}}{357}
+\entry {\code {STANDARD{\_}INCLUDE{\_}DIR}}{358}
+\entry {\code {STANDARD{\_}STARTFILE{\_}PREFIX}}{357}
+\entry {start files}{124}
+\entry {\code {STARTFILE{\_}SPEC}}{355}
+\entry {\code {STARTING{\_}FRAME{\_}OFFSET}}{386}
+\entry {\code {STARTING{\_}FRAME{\_}OFFSET} and virtual registers}{261}
+\entry {statements inside expressions}{135}
+\entry {static data in C{\tt\char43}{\tt\char43}, declaring and defining}{208}
+\entry {\code {STATIC{\_}CHAIN}}{389}
+\entry {\code {STATIC{\_}CHAIN{\_}INCOMING}}{389}
+\entry {\code {STATIC{\_}CHAIN{\_}INCOMING{\_}REGNUM}}{389}
+\entry {\code {STATIC{\_}CHAIN{\_}REGNUM}}{389}
+\entry {\file {stdarg.h} and register arguments}{394}
+\entry {\file {stdarg.h} and RT PC}{74}
+\entry {storage layout}{362}
+\entry {\code {STORE{\_}FLAG{\_}VALUE}}{463}
+\entry {\samp {store{\_}multiple} instruction pattern}{316}
+\entry {storem bug (29k)}{61}
+\entry {\code {strcmp}}{18}
+\entry {\code {strcpy}}{18, 365}
+\entry {strength-reduction}{241}
+\entry {\code {STRICT{\_}ALIGNMENT}}{366}
+\entry {\code {STRICT{\_}ARGUMENT{\_}NAMING}}{411}
+\entry {\code {strict{\_}low{\_}part}}{272}
+\entry {string constants}{201}
+\entry {string constants vs newline}{20}
+\entry {\code {STRIP{\_}NAME{\_}ENCODING}}{430}
+\entry {\code {strlen}}{18}
+\entry {\code {strlen\var {m}} instruction pattern}{319}
+\entry {\code {STRUCT{\_}VALUE}}{400}
+\entry {\code {STRUCT{\_}VALUE{\_}INCOMING}}{400}
+\entry {\code {STRUCT{\_}VALUE{\_}INCOMING{\_}REGNUM}}{400}
+\entry {\code {STRUCT{\_}VALUE{\_}REGNUM}}{400}
+\entry {structure passing (88k)}{66}
+\entry {structure value address}{399}
+\entry {\code {STRUCTURE{\_}SIZE{\_}BOUNDARY}}{365}
+\entry {structures}{204}
+\entry {structures, constructor expression}{148}
+\entry {structures, returning}{237}
+\entry {stupid register allocation}{242}
+\entry {\code {sub\var {m}3} instruction pattern}{317}
+\entry {submodel options}{52}
+\entry {\code {subreg}}{262}
+\entry {\code {subreg} and \samp {/s}}{251}
+\entry {\code {subreg} and \samp {/u}}{251}
+\entry {\code {subreg}, in \code {strict{\_}low{\_}part}}{272}
+\entry {\code {subreg}, special reload handling}{263}
+\entry {\code {SUBREG{\_}PROMOTED{\_}UNSIGNED{\_}P}}{251}
+\entry {\code {SUBREG{\_}PROMOTED{\_}VAR{\_}P}}{251}
+\entry {\code {SUBREG{\_}REG}}{263}
+\entry {\code {SUBREG{\_}WORD}}{263}
+\entry {subscripting}{147}
+\entry {subscripting and function values}{147}
+\entry {subtype polymorphism, C{\tt\char43}{\tt\char43}}{186}
+\entry {\code {SUCCESS{\_}EXIT{\_}CODE}}{469}
+\entry {suffixes for C{\tt\char43}{\tt\char43} source}{16}
+\entry {Sun installation}{127}
+\entry {\code {SUPPORTS{\_}WEAK}}{439}
+\entry {suppressing warnings}{26}
+\entry {surprises in C{\tt\char43}{\tt\char43}}{208}
+\entry {SVr4}{65}
+\entry {\code {SWITCH{\_}TAKES{\_}ARG}}{353}
+\entry {\code {SWITCHES{\_}NEED{\_}SPACES}}{353}
+\entry {\code {symbol{\_}ref}}{259}
+\entry {\code {symbol{\_}ref} and \samp {/u}}{252}
+\entry {\code {symbol{\_}ref} and \samp {/v}}{252}
+\entry {\code {symbol{\_}ref}, RTL sharing}{289}
+\entry {\code {SYMBOL{\_}REF{\_}FLAG}}{252}
+\entry {\code {SYMBOL{\_}REF{\_}FLAG}, in \code {ENCODE{\_}SECTION{\_}INFO}}{430}
+\entry {\code {SYMBOL{\_}REF{\_}USED}}{252}
+\entry {symbolic label}{289}
+\entry {syntax checking}{26}
+\entry {synthesized methods, warning}{33}
+\entry {\code {sys{\_}siglist}}{471}
+\entry {\code {SYSTEM{\_}INCLUDE{\_}DIR}}{358}
\initial {T}
-\entry {\code {tablejump} instruction pattern}{304}
-\entry {tagging insns}{325}
-\entry {tail recursion optimization}{226}
-\entry {target description macros}{335}
-\entry {target machine, specifying}{55}
-\entry {target options}{55}
-\entry {target specifications}{340}
-\entry {target-parameter-dependent code}{226}
-\entry {\code {TARGET{\_}BELL}}{350}
-\entry {\code {TARGET{\_}BS}}{350}
-\entry {\code {TARGET{\_}CR}}{350}
-\entry {\code {TARGET{\_}EDOM}}{389}
-\entry {\code {TARGET{\_}FF}}{350}
-\entry {\code {TARGET{\_}FLOAT{\_}FORMAT}}{347}
-\entry {\code {TARGET{\_}MEM{\_}FUNCTIONS}}{389}
-\entry {\code {TARGET{\_}NEWLINE}}{350}
-\entry {\code {TARGET{\_}OPTIONS}}{341}
-\entry {\code {TARGET{\_}SWITCHES}}{340}
-\entry {\code {TARGET{\_}TAB}}{350}
-\entry {\code {TARGET{\_}VERSION}}{341}
-\entry {\code {TARGET{\_}VT}}{350}
-\entry {\code {TCmode}}{239}
-\entry {\code {tcov}}{43}
-\entry {template debugging}{38}
-\entry {template instantiation}{174}
-\entry {temporaries, lifetime of}{197}
-\entry {termination routines}{411}
-\entry {\code {text{\_}section}}{400}
-\entry {\code {TEXT{\_}SECTION{\_}ASM{\_}OP}}{399}
-\entry {\code {TFmode}}{239}
-\entry {thunks}{128}
-\entry {\code {TImode}}{239}
-\entry {\file {tm.h} macros}{335}
-\entry {\code {TMPDIR}}{86}
-\entry {top level of compiler}{225}
-\entry {traditional C language}{28}
-\entry {\code {TRADITIONAL{\_}RETURN{\_}FLOAT}}{374}
-\entry {\code {TRAMPOLINE{\_}ALIGNMENT}}{385}
-\entry {\code {TRAMPOLINE{\_}SECTION}}{385}
-\entry {\code {TRAMPOLINE{\_}SIZE}}{385}
-\entry {\code {TRAMPOLINE{\_}TEMPLATE}}{385}
-\entry {trampolines for nested functions}{385}
-\entry {\code {TRANSFER{\_}FROM{\_}TRAMPOLINE}}{387}
-\entry {\code {TRULY{\_}NOOP{\_}TRUNCATION}}{432}
-\entry {\code {truncate}}{254}
-\entry {\code {trunc\var {mn}} instruction pattern}{301}
-\entry {\code {tst\var {m}} instruction pattern}{299}
-\entry {type abstraction, C{\tt\char43}{\tt\char43}}{176}
-\entry {type alignment}{150}
-\entry {type attributes}{153}
-\entry {typedef names as function parameters}{192}
-\entry {\code {typeof}}{132}
+\entry {\file {t-\var {target}}}{473}
+\entry {\code {tablejump} instruction pattern}{324}
+\entry {tagging insns}{344}
+\entry {tail recursion optimization}{240}
+\entry {target description macros}{353}
+\entry {target machine, specifying}{51}
+\entry {target makefile fragment}{473}
+\entry {target options}{51}
+\entry {target specifications}{359}
+\entry {target-parameter-dependent code}{240}
+\entry {\code {TARGET{\_}BELL}}{371}
+\entry {\code {TARGET{\_}BS}}{371}
+\entry {\code {TARGET{\_}CR}}{371}
+\entry {\code {TARGET{\_}EDOM}}{416}
+\entry {\code {TARGET{\_}FF}}{371}
+\entry {\code {TARGET{\_}FLOAT{\_}FORMAT}}{368}
+\entry {\code {TARGET{\_}MEM{\_}FUNCTIONS}}{416}
+\entry {\code {TARGET{\_}NEWLINE}}{371}
+\entry {\code {TARGET{\_}OPTIONS}}{360}
+\entry {\code {TARGET{\_}SWITCHES}}{360}
+\entry {\code {TARGET{\_}TAB}}{371}
+\entry {\code {TARGET{\_}VERSION}}{361}
+\entry {\code {TARGET{\_}VT}}{371}
+\entry {\code {TCmode}}{256}
+\entry {\code {tcov}}{35}
+\entry {template debugging}{29}
+\entry {template instantiation}{183}
+\entry {temporaries, lifetime of}{208}
+\entry {termination routines}{442}
+\entry {\code {text{\_}section}}{429}
+\entry {\code {TEXT{\_}SECTION{\_}ASM{\_}OP}}{428}
+\entry {\code {TFmode}}{255}
+\entry {thunks}{137}
+\entry {\code {TImode}}{255}
+\entry {\file {tm.h} macros}{353}
+\entry {\code {TMPDIR}}{92}
+\entry {top level of compiler}{239}
+\entry {traditional C language}{18}
+\entry {\code {TRADITIONAL{\_}RETURN{\_}FLOAT}}{398}
+\entry {\code {TRAMPOLINE{\_}ALIGNMENT}}{412}
+\entry {\code {TRAMPOLINE{\_}SECTION}}{412}
+\entry {\code {TRAMPOLINE{\_}SIZE}}{412}
+\entry {\code {TRAMPOLINE{\_}TEMPLATE}}{412}
+\entry {trampolines for nested functions}{412}
+\entry {\code {TRANSFER{\_}FROM{\_}TRAMPOLINE}}{414}
+\entry {\code {TRULY{\_}NOOP{\_}TRUNCATION}}{463}
+\entry {\code {truncate}}{271}
+\entry {\code {trunc\var {mn}} instruction pattern}{320}
+\entry {\code {tst\var {m}} instruction pattern}{318}
+\entry {type abstraction, C{\tt\char43}{\tt\char43}}{186}
+\entry {type alignment}{159}
+\entry {type attributes}{162}
+\entry {typedef names as function parameters}{203}
+\entry {\code {typeof}}{141}
\initial {U}
-\entry {\code {udiv}}{249}
-\entry {\code {UDIVDI3{\_}LIBCALL}}{388}
-\entry {\code {udiv\var {m}3} instruction pattern}{298}
-\entry {\code {udivmod\var {m}4} instruction pattern}{299}
-\entry {\code {UDIVSI3{\_}LIBCALL}}{388}
-\entry {Ultrix calling convention}{188}
-\entry {\code {umax}}{250}
-\entry {\code {umax\var {m}3} instruction pattern}{298}
-\entry {\code {umin}}{250}
-\entry {\code {umin\var {m}3} instruction pattern}{298}
-\entry {\code {umod}}{249}
-\entry {\code {UMODDI3{\_}LIBCALL}}{388}
-\entry {\code {umod\var {m}3} instruction pattern}{298}
-\entry {\code {UMODSI3{\_}LIBCALL}}{388}
-\entry {\code {umulhisi3} instruction pattern}{298}
-\entry {\code {umul\var {m}3{\_}highpart} instruction pattern}{298}
-\entry {\code {umulqihi3} instruction pattern}{298}
-\entry {\code {umulsidi3} instruction pattern}{298}
-\entry {\code {unchanging}}{238}
-\entry {\code {unchanging}, in \code {call{\_}insn}}{236}
-\entry {\code {unchanging}, in \code {insn}}{236}
-\entry {\code {unchanging}, in \code {reg} and \code {mem}}{235}
-\entry {\code {unchanging}, in \code {subreg}}{235}
-\entry {\code {unchanging}, in \code {symbol{\_}ref}}{236}
-\entry {undefined behavior}{203}
-\entry {undefined function value}{203}
-\entry {underscores in variables in macros}{132}
-\entry {underscores, avoiding (88k)}{65}
-\entry {union, casting to a}{143}
-\entry {unions}{192}
-\entry {unions, returning}{223}
-\entry {\code {UNITS{\_}PER{\_}WORD}}{343}
-\entry {\code {UNKNOWN{\_}FLOAT{\_}FORMAT}}{347}
-\entry {unreachable code}{226}
-\entry {unresolved references and \code {-nodefaultlibs}}{53}
-\entry {unresolved references and \code {-nostdlib}}{53}
-\entry {\code {unshare{\_}all{\_}rtl}}{271}
-\entry {unsigned division}{249}
-\entry {unsigned greater than}{252}
-\entry {unsigned less than}{252}
-\entry {unsigned minimum and maximum}{250}
-\entry {\code {unsigned{\_}fix}}{254}
-\entry {\code {unsigned{\_}float}}{254}
-\entry {\code {unspec}}{259}
-\entry {\code {unspec{\_}volatile}}{259}
-\entry {\code {untyped{\_}call} instruction pattern}{303}
-\entry {\code {untyped{\_}return} instruction pattern}{304}
-\entry {\code {use}}{257}
-\entry {\code {USE{\_}C{\_}ALLOCA}}{438}
-\entry {\code {USE{\_}PROTOTYPES}}{439}
-\entry {\code {used}}{237}
-\entry {\code {used}, in \code {symbol{\_}ref}}{236}
-\entry {\code {USER{\_}LABEL{\_}PREFIX}}{418}
-\entry {\code {USG}}{437}
+\entry {\code {udiv}}{266}
+\entry {\code {UDIVDI3{\_}LIBCALL}}{415}
+\entry {\code {udiv\var {m}3} instruction pattern}{317}
+\entry {\code {udivmod\var {m}4} instruction pattern}{317}
+\entry {\code {UDIVSI3{\_}LIBCALL}}{415}
+\entry {Ultrix calling convention}{199}
+\entry {\code {umax}}{267}
+\entry {\code {umax\var {m}3} instruction pattern}{317}
+\entry {\code {umin}}{267}
+\entry {\code {umin\var {m}3} instruction pattern}{317}
+\entry {\code {umod}}{266}
+\entry {\code {UMODDI3{\_}LIBCALL}}{416}
+\entry {\code {umod\var {m}3} instruction pattern}{317}
+\entry {\code {UMODSI3{\_}LIBCALL}}{415}
+\entry {\code {umulhisi3} instruction pattern}{317}
+\entry {\code {umul\var {m}3{\_}highpart} instruction pattern}{317}
+\entry {\code {umulqihi3} instruction pattern}{317}
+\entry {\code {umulsidi3} instruction pattern}{317}
+\entry {\code {unchanging}}{254}
+\entry {\code {unchanging}, in \code {call{\_}insn}}{252}
+\entry {\code {unchanging}, in \code {insn}}{252}
+\entry {\code {unchanging}, in \code {reg} and \code {mem}}{251}
+\entry {\code {unchanging}, in \code {subreg}}{251}
+\entry {\code {unchanging}, in \code {symbol{\_}ref}}{252}
+\entry {undefined behavior}{215}
+\entry {undefined function value}{215}
+\entry {underscores in variables in macros}{141}
+\entry {underscores, avoiding (88k)}{63}
+\entry {union, casting to a}{151}
+\entry {unions}{204}
+\entry {unions, returning}{237}
+\entry {\code {UNIQUE{\_}SECTION}}{430}
+\entry {\code {UNITS{\_}PER{\_}WORD}}{363}
+\entry {\code {UNKNOWN{\_}FLOAT{\_}FORMAT}}{368}
+\entry {unreachable code}{241}
+\entry {unresolved references and \code {-nodefaultlibs}}{49}
+\entry {unresolved references and \code {-nostdlib}}{49}
+\entry {\code {unshare{\_}all{\_}rtl}}{289}
+\entry {unsigned division}{266}
+\entry {unsigned greater than}{269}
+\entry {unsigned less than}{269}
+\entry {unsigned minimum and maximum}{267}
+\entry {\code {unsigned{\_}fix}}{271}
+\entry {\code {unsigned{\_}float}}{271}
+\entry {\code {unspec}}{276}
+\entry {\code {unspec{\_}volatile}}{276}
+\entry {\code {untyped{\_}call} instruction pattern}{322}
+\entry {\code {untyped{\_}return} instruction pattern}{323}
+\entry {\code {use}}{275}
+\entry {\code {USE{\_}C{\_}ALLOCA}}{470}
+\entry {\code {USE{\_}PROTOTYPES}}{471}
+\entry {\code {used}}{253}
+\entry {\code {used}, in \code {symbol{\_}ref}}{252}
+\entry {\code {USER{\_}LABEL{\_}PREFIX}}{448}
+\entry {\code {USG}}{469}
\initial {V}
-\entry {\samp {V} in constraint}{283}
-\entry {\code {VALID{\_}MACHINE{\_}DECL{\_}ATTRIBUTE}}{434}
-\entry {\code {VALID{\_}MACHINE{\_}TYPE{\_}ATTRIBUTE}}{435}
-\entry {value after \code {longjmp}}{164}
-\entry {values, returned by functions}{374}
-\entry {varargs implementation}{382}
-\entry {\file {varargs.h} and RT PC}{72}
-\entry {variable alignment}{150}
-\entry {variable attributes}{150}
-\entry {variable number of arguments}{138}
-\entry {variable-length array scope}{137}
-\entry {variable-length arrays}{137}
-\entry {variables in specified registers}{162}
-\entry {variables, local, in macros}{132}
-\entry {Vax calling convention}{188}
-\entry {VAX options}{59}
-\entry {\code {VAX{\_}FLOAT{\_}FORMAT}}{347}
-\entry {\file {VAXCRTL}}{219}
-\entry {\code {VIRTUAL{\_}INCOMING{\_}ARGS{\_}REGNUM}}{245}
-\entry {\code {VIRTUAL{\_}OUTGOING{\_}ARGS{\_}REGNUM}}{245}
-\entry {\code {VIRTUAL{\_}STACK{\_}DYNAMIC{\_}REGNUM}}{245}
-\entry {\code {VIRTUAL{\_}STACK{\_}VARS{\_}REGNUM}}{245}
-\entry {\code {VMS}}{437}
-\entry {VMS and case sensitivity}{219}
-\entry {VMS and include files}{215}
-\entry {VMS installation}{119}
-\entry {void pointers, arithmetic}{139}
-\entry {void, size of pointer to}{139}
-\entry {\code {VOIDmode}}{239}
-\entry {\code {volatil}}{237}
-\entry {\code {volatil}, in \code {insn}}{236}
-\entry {\code {volatil}, in \code {mem}}{235}
-\entry {\code {volatil}, in \code {reg}}{235}
-\entry {\code {volatil}, in \code {symbol{\_}ref}}{236}
-\entry {\code {volatile} applied to function}{144}
-\entry {volatile memory references}{237}
-\entry {voting between constraint alternatives}{288}
-\entry {\code {vprintf}}{438}
+\entry {\samp {V} in constraint}{301}
+\entry {\code {VALID{\_}MACHINE{\_}DECL{\_}ATTRIBUTE}}{466}
+\entry {\code {VALID{\_}MACHINE{\_}TYPE{\_}ATTRIBUTE}}{466}
+\entry {value after \code {longjmp}}{173}
+\entry {values, returned by functions}{398}
+\entry {varargs implementation}{409}
+\entry {\file {varargs.h} and RT PC}{74}
+\entry {variable alignment}{159}
+\entry {variable attributes}{159}
+\entry {variable number of arguments}{146}
+\entry {variable-length array scope}{145}
+\entry {variable-length arrays}{145}
+\entry {variables in specified registers}{172}
+\entry {variables, local, in macros}{141}
+\entry {Vax calling convention}{199}
+\entry {VAX options}{55}
+\entry {\code {VAX{\_}FLOAT{\_}FORMAT}}{368}
+\entry {\file {VAXCRTL}}{232}
+\entry {\code {VIRTUAL{\_}INCOMING{\_}ARGS{\_}REGNUM}}{261}
+\entry {\code {VIRTUAL{\_}OUTGOING{\_}ARGS{\_}REGNUM}}{262}
+\entry {\code {VIRTUAL{\_}STACK{\_}DYNAMIC{\_}REGNUM}}{261}
+\entry {\code {VIRTUAL{\_}STACK{\_}VARS{\_}REGNUM}}{261}
+\entry {\code {VMS}}{469}
+\entry {VMS and case sensitivity}{232}
+\entry {VMS and include files}{229}
+\entry {VMS installation}{128}
+\entry {void pointers, arithmetic}{148}
+\entry {void, size of pointer to}{148}
+\entry {\code {VOIDmode}}{256}
+\entry {\code {volatil}}{253}
+\entry {\code {volatil}, in \code {insn}}{252}
+\entry {\code {volatil}, in \code {mem}}{250}
+\entry {\code {volatil}, in \code {reg}}{251}
+\entry {\code {volatil}, in \code {symbol{\_}ref}}{252}
+\entry {\code {volatile} applied to function}{151}
+\entry {volatile memory references}{253}
+\entry {voting between constraint alternatives}{306}
+\entry {\code {vprintf}}{470}
\initial {W}
-\entry {warning for enumeration conversions}{37}
-\entry {warning for overloaded virtual fn}{41}
-\entry {warning for reordering of member initializers}{38}
-\entry {warning for synthesized methods}{41}
-\entry {warning messages}{35}
-\entry {warnings vs errors}{202}
-\entry {\code {WCHAR{\_}TYPE}}{350}
-\entry {\code {WCHAR{\_}TYPE{\_}SIZE}}{350}
-\entry {\code {weak} attribute}{147}
-\entry {\code {which{\_}alternative}}{282}
-\entry {whitespace}{192}
-\entry {\code {word{\_}mode}}{242}
-\entry {\code {WORD{\_}REGISTER{\_}OPERATIONS}}{431}
-\entry {\code {WORD{\_}SWITCH{\_}TAKES{\_}ARG}}{335}
-\entry {\code {WORDS{\_}BIG{\_}ENDIAN}}{342}
-\entry {\code {WORDS{\_}BIG{\_}ENDIAN}, effect on \code {subreg}}{246}
+\entry {warning for comparison of signed and unsigned values}{29}
+\entry {warning for overloaded virtual fn}{32}
+\entry {warning for reordering of member initializers}{29}
+\entry {warning for synthesized methods}{33}
+\entry {warning messages}{26}
+\entry {warnings vs errors}{214}
+\entry {\code {WCHAR{\_}TYPE}}{370}
+\entry {\code {WCHAR{\_}TYPE{\_}SIZE}}{371}
+\entry {\code {weak} attribute}{154}
+\entry {\code {which{\_}alternative}}{300}
+\entry {whitespace}{203}
+\entry {\code {word{\_}mode}}{258}
+\entry {\code {WORD{\_}REGISTER{\_}OPERATIONS}}{462}
+\entry {\code {WORD{\_}SWITCH{\_}TAKES{\_}ARG}}{353}
+\entry {\code {WORDS{\_}BIG{\_}ENDIAN}}{362}
+\entry {\code {WORDS{\_}BIG{\_}ENDIAN}, effect on \code {subreg}}{263}
\initial {X}
-\entry {\samp {X} in constraint}{284}
-\entry {\code {XCmode}}{239}
-\entry {\code {XCOFF{\_}DEBUGGING{\_}INFO}}{422}
-\entry {\code {XEXP}}{233}
-\entry {\code {XFmode}}{239}
-\entry {\code {XINT}}{233}
-\entry {\file {xm-\var {machine}.h}}{437}
-\entry {\code {xor}}{250}
-\entry {\code {xor}, canonicalization of}{311}
-\entry {\code {xor\var {m}3} instruction pattern}{298}
-\entry {\code {XSTR}}{233}
-\entry {\code {XVEC}}{234}
-\entry {\code {XVECEXP}}{234}
-\entry {\code {XVECLEN}}{234}
-\entry {\code {XWINT}}{233}
+\entry {\samp {X} in constraint}{303}
+\entry {\file {x-\var {host}}}{475}
+\entry {\code {XCmode}}{256}
+\entry {\code {XCOFF{\_}DEBUGGING{\_}INFO}}{452}
+\entry {\code {XEXP}}{249}
+\entry {\code {XFmode}}{255}
+\entry {\code {XINT}}{249}
+\entry {\file {xm-\var {machine}.h}}{469}
+\entry {\code {xor}}{267}
+\entry {\code {xor}, canonicalization of}{331}
+\entry {\code {xor\var {m}3} instruction pattern}{317}
+\entry {\code {XSTR}}{249}
+\entry {\code {XVEC}}{250}
+\entry {\code {XVECEXP}}{250}
+\entry {\code {XVECLEN}}{250}
+\entry {\code {XWINT}}{249}
\initial {Z}
-\entry {zero division on 88k}{67}
-\entry {zero-length arrays}{136}
-\entry {\code {zero{\_}extend}}{254}
-\entry {\code {zero{\_}extend\var {mn}} instruction pattern}{301}
-\entry {\code {zero{\_}extract}}{253}
-\entry {\code {zero{\_}extract}, canonicalization of}{311}
+\entry {zero division on 88k}{65}
+\entry {zero-length arrays}{145}
+\entry {\code {zero{\_}extend}}{271}
+\entry {\code {zero{\_}extend\var {mn}} instruction pattern}{320}
+\entry {\code {zero{\_}extract}}{270}
+\entry {\code {zero{\_}extract}, canonicalization of}{332}
diff --git a/gnu/usr.bin/gcc/gen-protos.c b/gnu/usr.bin/gcc/gen-protos.c
index 44c900ae0a6..0284c18ba4a 100644
--- a/gnu/usr.bin/gcc/gen-protos.c
+++ b/gnu/usr.bin/gcc/gen-protos.c
@@ -1,5 +1,5 @@
/* gen-protos.c - massages a list of prototypes, for use by fixproto.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -22,9 +22,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "cpplib.h"
#include "cpphash.h"
+int verbose = 0;
+char *progname;
+
#define HASH_SIZE 2503 /* a prime */
+int hash_tab[HASH_SIZE];
+int next_index;
-int
+static int
hashf (name, len, hashsize)
register U_CHAR *name;
register int len;
@@ -38,40 +43,129 @@ hashf (name, len, hashsize)
return MAKE_POS (r) % hashsize;
}
-int hash_tab[HASH_SIZE];
-int verbose = 0;
+static void
+add_hash (fname)
+ char *fname;
+{
+ int i, i0;
-sstring linebuf;
+ /* NOTE: If you edit this, also edit lookup_std_proto in fix-header.c !! */
+ i = hashf (fname, strlen (fname), HASH_SIZE);
+ i0 = i;
+ if (hash_tab[i] != 0)
+ {
+ for (;;)
+ {
+ i = (i+1) % HASH_SIZE;
+ if (i == i0)
+ abort ();
+ if (hash_tab[i] == 0)
+ break;
+ }
+ }
+ hash_tab[i] = next_index;
-/* Avoid error if config defines abort as fancy_abort.
- It's not worth "really" implementing this because ordinary
- compiler users never run fix-header. */
+ next_index++;
+}
-void
-fancy_abort ()
+/* Given a function prototype, fill in the fields of FN.
+ The result is a boolean indicating if a function prototype was found.
+
+ The input string is modified (trailing NULs are inserted).
+ The fields of FN point to the input string. */
+
+static int
+parse_fn_proto (start, end, fn)
+ char *start, *end;
+ struct fn_decl *fn;
{
- abort ();
+ register char *ptr;
+ int param_nesting = 1;
+ char *param_start, *param_end, *decl_start, *name_start, *name_end;
+
+ ptr = end - 1;
+ while (*ptr == ' ' || *ptr == '\t') ptr--;
+ if (*ptr-- != ';')
+ {
+ fprintf (stderr, "Funny input line: %s\n", start);
+ return 0;
+ }
+ while (*ptr == ' ' || *ptr == '\t') ptr--;
+ if (*ptr != ')')
+ {
+ fprintf (stderr, "Funny input line: %s\n", start);
+ return 0;
+ }
+ param_end = ptr;
+ for (;;)
+ {
+ int c = *--ptr;
+ if (c == '(' && --param_nesting == 0)
+ break;
+ else if (c == ')')
+ param_nesting++;
+ }
+ param_start = ptr+1;
+
+ ptr--;
+ while (*ptr == ' ' || *ptr == '\t') ptr--;
+
+ if (!isalnum (*ptr))
+ {
+ if (verbose)
+ fprintf (stderr, "%s: Can't handle this complex prototype: %s\n",
+ progname, start);
+ return 0;
+ }
+ name_end = ptr+1;
+
+ while (isalnum (*ptr) || *ptr == '_') --ptr;
+ name_start = ptr+1;
+ while (*ptr == ' ' || *ptr == '\t') ptr--;
+ ptr[1] = 0;
+ *param_end = 0;
+ *name_end = 0;
+
+ decl_start = start;
+ if (strncmp (decl_start, "typedef ", 8) == 0)
+ return 0;
+ if (strncmp (decl_start, "extern ", 7) == 0)
+ decl_start += 7;
+
+ fn->fname = name_start;
+ fn->rtype = decl_start;
+ fn->params = param_start;
+ return 1;
}
int
main (argc, argv)
int argc;
- char** argv;
+ char **argv;
{
FILE *inf = stdin;
FILE *outf = stdout;
- int next_index = 0;
- int i, i0;
+ int i;
+ sstring linebuf;
+ char **optr;
+ struct fn_decl fn_decl;
+
+ i = strlen (argv[0]);
+ while (i > 0 && argv[0][i-1] != '/') --i;
+ progname = &argv[0][i];
+
+ INIT_SSTRING (&linebuf);
fprintf (outf, "struct fn_decl std_protos[] = {\n");
+ /* A hash table entry of 0 means "unused" so reserve it. */
+ fprintf (outf, " {\"\", \"\", \"\"},\n");
+ next_index = 1;
+
for (;;)
{
int c = skip_spaces (inf, ' ');
- int param_nesting = 1;
- char *param_start, *param_end, *decl_start,
- *name_start, *name_end;
- register char *ptr;
+
if (c == EOF)
break;
linebuf.ptr = linebuf.base;
@@ -82,83 +176,18 @@ main (argc, argv)
if (linebuf.base[0] == '\0') /* skip empty line */
continue;
- ptr = linebuf.ptr - 1;
- while (*ptr == ' ' || *ptr == '\t') ptr--;
- if (*ptr-- != ';')
- {
- fprintf (stderr, "Funny input line: %s\n", linebuf.base);
- continue;
- }
- while (*ptr == ' ' || *ptr == '\t') ptr--;
- if (*ptr != ')')
- {
- fprintf (stderr, "Funny input line: %s\n", linebuf.base);
- continue;
- }
- param_end = ptr;
- for (;;)
- {
- int c = *--ptr;
- if (c == '(' && --param_nesting == 0)
- break;
- else if (c == ')')
- param_nesting++;
- }
- param_start = ptr+1;
-
- ptr--;
- while (*ptr == ' ' || *ptr == '\t') ptr--;
-
- if (!isalnum (*ptr))
- {
- if (verbose)
- fprintf (stderr, "%s: Can't handle this complex prototype: %s\n",
- argv[0], linebuf.base);
- continue;
- }
- name_end = ptr+1;
-
- while (isalnum (*ptr) || *ptr == '_') --ptr;
- name_start = ptr+1;
- while (*ptr == ' ' || *ptr == '\t') ptr--;
- ptr[1] = 0;
- *name_end = 0;
- *param_end = 0;
- *name_end = 0;
-
- decl_start = linebuf.base;
- if (strncmp (decl_start, "typedef ", 8) == 0)
+ if (! parse_fn_proto (linebuf.base, linebuf.ptr, &fn_decl))
continue;
- if (strncmp (decl_start, "extern ", 7) == 0)
- decl_start += 7;
-
-
- /* NOTE: If you edit this,
- also edit lookup_std_proto in fix-header.c !! */
- i = hashf (name_start, name_end - name_start, HASH_SIZE);
- i0 = i;
- if (hash_tab[i] != 0)
- {
- for (;;)
- {
- i = (i+1) % HASH_SIZE;
- if (i == i0)
- abort ();
- if (hash_tab[i] == 0)
- break;
- }
- }
- hash_tab[i] = next_index;
- fprintf (outf, " {\"%s\", \"%s\", \"%s\" },\n",
- name_start, decl_start, param_start);
+ add_hash (fn_decl.fname);
- next_index++;
+ fprintf (outf, " {\"%s\", \"%s\", \"%s\"},\n",
+ fn_decl.fname, fn_decl.rtype, fn_decl.params);
if (c == EOF)
break;
}
- fprintf (outf, "{0, 0, 0}\n};\n");
+ fprintf (outf, " {0, 0, 0}\n};\n");
fprintf (outf, "#define HASH_SIZE %d\n", HASH_SIZE);
@@ -170,6 +199,16 @@ main (argc, argv)
return 0;
}
+/* Avoid error if config defines abort as fancy_abort.
+ It's not worth "really" implementing this because ordinary
+ compiler users never run fix-header. */
+
+void
+fancy_abort ()
+{
+ abort ();
+}
+
void
fatal (s)
char *s;
diff --git a/gnu/usr.bin/gcc/genattr.c b/gnu/usr.bin/gcc/genattr.c
index f87ce06bd61..c351fc5ad5f 100644
--- a/gnu/usr.bin/gcc/genattr.c
+++ b/gnu/usr.bin/gcc/genattr.c
@@ -1,5 +1,5 @@
/* Generate attribute information (insn-attr.h) from machine description.
- Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1994, 1996 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -275,14 +275,6 @@ from the machine description file `md'. */\n\n");
/* For compatibility, define the attribute `alternative', which is just
a reference to the variable `which_alternative'. */
- printf("#ifndef PROTO\n");
- printf("#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)\n");
- printf("#define PROTO(ARGS) ARGS\n");
- printf("#else\n");
- printf("#define PROTO(ARGS) ()\n");
- printf("#endif\n");
- printf("#endif\n");
-
printf ("#define HAVE_ATTR_alternative\n");
printf ("#define get_attr_alternative(insn) which_alternative\n");
diff --git a/gnu/usr.bin/gcc/genattrtab.c b/gnu/usr.bin/gcc/genattrtab.c
index c764871a482..c16a6acb9b3 100644
--- a/gnu/usr.bin/gcc/genattrtab.c
+++ b/gnu/usr.bin/gcc/genattrtab.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to compute values of attributes.
- Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GNU CC.
@@ -102,17 +102,25 @@ Boston, MA 02111-1307, USA. */
#else
#include <varargs.h>
#endif
+#include <stdio.h>
#include "rtl.h"
#include "insn-config.h" /* For REGISTER_CONSTRAINTS */
-#include <stdio.h>
-#ifndef VMS
-#ifndef USG
-#include <sys/time.h>
-#include <sys/resource.h>
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
#endif
#endif
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
/* We must include obstack.h after <sys/time.h>, to avoid lossage with
/usr/include/sys/stdtypes.h on Sun OS 4.x. */
#include "obstack.h"
@@ -146,12 +154,12 @@ void fancy_abort ();
struct insn_def
{
- int insn_code; /* Instruction number. */
- int insn_index; /* Expression numer in file, for errors. */
- struct insn_def *next; /* Next insn in chain. */
- rtx def; /* The DEFINE_... */
+ int insn_code; /* Instruction number. */
+ int insn_index; /* Expression numer in file, for errors. */
+ struct insn_def *next; /* Next insn in chain. */
+ rtx def; /* The DEFINE_... */
int num_alternatives; /* Number of alternatives. */
- int vec_idx; /* Index of attribute vector in `def'. */
+ int vec_idx; /* Index of attribute vector in `def'. */
};
/* Once everything has been read in, we store in each attribute value a list
@@ -182,15 +190,15 @@ struct attr_value
struct attr_desc
{
- char *name; /* Name of attribute. */
- struct attr_desc *next; /* Next attribute. */
- int is_numeric; /* Values of this attribute are numeric. */
+ char *name; /* Name of attribute. */
+ struct attr_desc *next; /* Next attribute. */
+ int is_numeric; /* Values of this attribute are numeric. */
int negative_ok; /* Allow negative numeric values. */
int unsigned_p; /* Make the output function unsigned int. */
int is_const; /* Attribute value constant for each run. */
- int is_special; /* Don't call `write_attr_set'. */
- struct attr_value *first_value; /* First value of this attribute. */
- struct attr_value *default_val; /* Default value for this attribute. */
+ int is_special; /* Don't call `write_attr_set'. */
+ struct attr_value *first_value; /* First value of this attribute. */
+ struct attr_value *default_val; /* Default value for this attribute. */
};
#define NULL_ATTR (struct attr_desc *) NULL
@@ -208,7 +216,7 @@ struct range
struct delay_desc
{
rtx def; /* DEFINE_DELAY expression. */
- struct delay_desc *next; /* Next DEFINE_DELAY. */
+ struct delay_desc *next; /* Next DEFINE_DELAY. */
int num; /* Number of DEFINE_DELAY, starting at 1. */
};
@@ -236,7 +244,7 @@ struct function_unit
int multiplicity; /* Number of units of this type. */
int simultaneity; /* Maximum number of simultaneous insns
on this function unit or 0 if unlimited. */
- rtx condexp; /* Expression TRUE for insn needing unit. */
+ rtx condexp; /* Expression TRUE for insn needing unit. */
int num_opclasses; /* Number of different operation types. */
struct function_unit_op *ops; /* Pointer to first operation type. */
int needs_conflict_function; /* Nonzero if a conflict function required. */
@@ -299,7 +307,7 @@ struct dimension
int num_values; /* Length of the values list. */
};
-/* Other variables. */
+/* Other variables. */
static int insn_code_number;
static int insn_index_number;
@@ -393,7 +401,9 @@ static rtx zero_fn PROTO((rtx));
static rtx one_fn PROTO((rtx));
static rtx max_fn PROTO((rtx));
static rtx simplify_cond PROTO((rtx, int, int));
+#if 0
static rtx simplify_by_alternatives PROTO((rtx, int, int));
+#endif
static rtx simplify_by_exploding PROTO((rtx));
static int find_and_mark_used_attributes PROTO((rtx, rtx *, int *));
static void unmark_used_attributes PROTO((rtx, struct dimension *, int));
@@ -483,6 +493,8 @@ struct attr_hash *attr_hash_table[RTL_HASH_SIZE];
codes are made. */
#define RTL_HASH(RTL) ((HOST_WIDE_INT) (RTL) & 0777777)
+rtx pc_rtx;
+
/* Add an entry to the hash table for RTL with hash code HASHCODE. */
static void
@@ -741,7 +753,7 @@ attr_printf VPROTO((register int len, char *fmt, ...))
#ifndef __STDC__
len = va_arg (p, int);
- fmt = va_arg (p, char*);
+ fmt = va_arg (p, char *);
#endif
/* Print the string into a temporary location. */
@@ -862,6 +874,9 @@ attr_copy_rtx (orig)
case PC:
case CC0:
return orig;
+
+ default:
+ break;
}
copy = rtx_alloc (code);
@@ -1152,7 +1167,7 @@ check_attr_value (exp, attr)
/* A constant SYMBOL_REF is valid as a constant attribute test and
is expanded later by make_canonical into a COND. */
return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
- /* Otherwise, fall through... */
+ /* Otherwise, fall through... */
default:
fatal ("Invalid operation `%s' for attribute value",
@@ -1239,7 +1254,7 @@ convert_set_attr (exp, num_alt, insn_code, insn_index)
/* Scan all definitions, checking for validity. Also, convert any SET_ATTR
and SET_ATTR_ALTERNATIVE expressions to the corresponding SET
- expressions. */
+ expressions. */
static void
check_defs ()
@@ -1382,7 +1397,7 @@ make_canonical (attr, exp)
RTX_UNCHANGING_P (exp) = 1;
exp = check_attr_value (exp, attr);
/* Goto COND case since this is now a COND. Note that while the
- new expression is rescanned, all symbol_ref notes are mared as
+ new expression is rescanned, all symbol_ref notes are marked as
unchanging. */
goto cond;
@@ -1403,7 +1418,7 @@ make_canonical (attr, exp)
int allsame = 1;
rtx defval;
- /* First, check for degenerate COND. */
+ /* First, check for degenerate COND. */
if (XVECLEN (exp, 0) == 0)
return make_canonical (attr, XEXP (exp, 1));
defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
@@ -1418,8 +1433,11 @@ make_canonical (attr, exp)
}
if (allsame)
return defval;
- break;
}
+ break;
+
+ default:
+ break;
}
return exp;
@@ -2175,6 +2193,9 @@ encode_units_mask (x)
case CC0:
case EQ_ATTR:
return x;
+
+ default:
+ break;
}
/* Compare the elements. If any pair of corresponding elements
@@ -2418,16 +2439,15 @@ simplify_cond (exp, insn_code, insn_index)
then build a new expression if they don't match EXP. */
rtx defval = XEXP (exp, 1);
rtx new_defval = XEXP (exp, 1);
-
int len = XVECLEN (exp, 0);
- rtx *tests = (rtx *) alloca (len * sizeof (rtx));
+ rtunion *tests = (rtunion *) alloca (len * sizeof (rtunion));
int allsame = 1;
char *first_spacer;
/* This lets us free all storage allocated below, if appropriate. */
first_spacer = (char *) obstack_finish (rtl_obstack);
- bcopy ((char *) &XVECEXP (exp, 0, 0), (char *) tests, len * sizeof (rtx));
+ bcopy ((char *) XVEC (exp, 0)->elem, (char *) tests, len * sizeof (rtunion));
/* See if default value needs simplification. */
if (GET_CODE (defval) == COND)
@@ -2440,10 +2460,10 @@ simplify_cond (exp, insn_code, insn_index)
rtx newtest, newval;
/* Simplify this test. */
- newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index);
- tests[i] = newtest;
+ newtest = SIMPLIFY_TEST_EXP (tests[i].rtx, insn_code, insn_index);
+ tests[i].rtx = newtest;
- newval = tests[i + 1];
+ newval = tests[i + 1].rtx;
/* See if this value may need simplification. */
if (GET_CODE (newval) == COND)
newval = simplify_cond (newval, insn_code, insn_index);
@@ -2454,7 +2474,7 @@ simplify_cond (exp, insn_code, insn_index)
/* If test is true, make this value the default
and discard this + any following tests. */
len = i;
- defval = tests[i + 1];
+ defval = tests[i + 1].rtx;
new_defval = newval;
}
@@ -2462,33 +2482,33 @@ simplify_cond (exp, insn_code, insn_index)
{
/* If test is false, discard it and its value. */
for (j = i; j < len - 2; j++)
- tests[j] = tests[j + 2];
+ tests[j].rtx = tests[j + 2].rtx;
len -= 2;
}
- else if (i > 0 && attr_equal_p (newval, tests[i - 1]))
+ else if (i > 0 && attr_equal_p (newval, tests[i - 1].rtx))
{
/* If this value and the value for the prev test are the same,
merge the tests. */
- tests[i - 2]
- = insert_right_side (IOR, tests[i - 2], newtest,
+ tests[i - 2].rtx
+ = insert_right_side (IOR, tests[i - 2].rtx, newtest,
insn_code, insn_index);
/* Delete this test/value. */
for (j = i; j < len - 2; j++)
- tests[j] = tests[j + 2];
+ tests[j].rtx = tests[j + 2].rtx;
len -= 2;
}
else
- tests[i + 1] = newval;
+ tests[i + 1].rtx = newval;
}
/* If the last test in a COND has the same value
as the default value, that test isn't needed. */
- while (len > 0 && attr_equal_p (tests[len - 1], new_defval))
+ while (len > 0 && attr_equal_p (tests[len - 1].rtx, new_defval))
len -= 2;
/* See if we changed anything. */
@@ -2496,7 +2516,7 @@ simplify_cond (exp, insn_code, insn_index)
allsame = 0;
else
for (i = 0; i < len; i++)
- if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i)))
+ if (! attr_equal_p (tests[i].rtx, XVECEXP (exp, 0, i)))
{
allsame = 0;
break;
@@ -2519,8 +2539,8 @@ simplify_cond (exp, insn_code, insn_index)
rtx newexp = rtx_alloc (COND);
XVEC (newexp, 0) = rtvec_alloc (len);
- bcopy ((char *) tests, (char *) &XVECEXP (newexp, 0, 0),
- len * sizeof (rtx));
+ bcopy ((char *) tests, (char *) XVEC (newexp, 0)->elem,
+ len * sizeof (rtunion));
XEXP (newexp, 1) = new_defval;
return newexp;
}
@@ -2728,7 +2748,7 @@ evaluate_eq_attr (exp, value, insn_code, insn_index)
For each possible COND value, call ourselves recursively.
The extra TRUE and FALSE expressions will be eliminated by another
- call to the simplification routine. */
+ call to the simplification routine. */
orexp = false_rtx;
andexp = true_rtx;
@@ -3089,7 +3109,7 @@ simplify_test_exp (exp, insn_code, insn_index)
fatal ("Invalid alternative specified for pattern number %d",
insn_index);
- /* If all alternatives are excluded, this is false. */
+ /* If all alternatives are excluded, this is false. */
i ^= insn_alternatives[insn_code];
if (i == 0)
return false_rtx;
@@ -3182,7 +3202,7 @@ simplify_test_exp (exp, insn_code, insn_index)
fatal ("Invalid alternative specified for pattern number %d",
insn_index);
- /* If all alternatives are included, this is true. */
+ /* If all alternatives are included, this is true. */
i ^= insn_alternatives[insn_code];
if (i == 0)
return true_rtx;
@@ -3269,6 +3289,10 @@ simplify_test_exp (exp, insn_code, insn_index)
for (ie = av->first_insn; ie; ie = ie->next)
if (ie->insn_code == insn_code)
return evaluate_eq_attr (exp, av->value, insn_code, insn_index);
+ break;
+
+ default:
+ break;
}
/* We have already simplified this expression. Simplifying it again
@@ -3621,9 +3645,10 @@ find_and_mark_used_attributes (exp, terms, nterms)
if (! find_and_mark_used_attributes (XEXP (exp, 1), terms, nterms))
return 0;
return 1;
- }
- return 0;
+ default:
+ return 0;
+ }
}
/* Clear the MEM_VOLATILE_P flag in all EQ_ATTR expressions on LIST and
@@ -3859,8 +3884,10 @@ simplify_with_current_value_aux (exp)
have been selected. */
}
return simplify_with_current_value_aux (XEXP (exp, 1));
+
+ default:
+ abort ();
}
- abort ();
}
/* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions. */
@@ -3893,6 +3920,9 @@ clear_struct_flag (x)
case EQ_ATTR:
case ATTR_FLAG:
return;
+
+ default:
+ break;
}
/* Compare the elements. If any pair of corresponding elements
@@ -3945,6 +3975,9 @@ count_sub_rtxs (x, max)
case EQ_ATTR:
case ATTR_FLAG:
return 1;
+
+ default:
+ break;
}
/* Compare the elements. If any pair of corresponding elements
@@ -4019,7 +4052,7 @@ gen_attr (exp)
if (! strcmp (attr->name, "length") && ! attr->is_numeric)
fatal ("`length' attribute must take numeric values");
- /* Set up the default value. */
+ /* Set up the default value. */
XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
}
@@ -4169,6 +4202,9 @@ gen_insn (exp)
id->vec_idx = 0;
got_define_asm_attributes = 1;
break;
+
+ default:
+ abort ();
}
}
@@ -4381,6 +4417,8 @@ write_test_expr (exp, in_comparison)
case ASHIFTRT:
printf (" >> ");
break;
+ default:
+ abort ();
}
write_test_expr (XEXP (exp, 1), in_comparison || comparison_operator);
@@ -4413,6 +4451,8 @@ write_test_expr (exp, in_comparison)
case NEG:
printf ("-");
break;
+ default:
+ abort ();
}
write_test_expr (XEXP (exp, 0), in_comparison);
@@ -4472,7 +4512,7 @@ write_test_expr (exp, in_comparison)
XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
break;
- /* Constant integer. */
+ /* Constant integer. */
case CONST_INT:
#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
printf ("%d", XWINT (exp, 0));
@@ -4481,14 +4521,15 @@ write_test_expr (exp, in_comparison)
#endif
break;
- /* A random C expression. */
+ /* A random C expression. */
case SYMBOL_REF:
printf ("%s", XSTR (exp, 0));
break;
/* The address of the branch target. */
case MATCH_DUP:
- printf ("insn_addresses[INSN_UID (operands[%d])]", XINT (exp, 0));
+ printf ("insn_addresses[INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])]",
+ XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
break;
/* The address of the current insn. It would be more consistent with
@@ -4603,6 +4644,9 @@ walk_attr_value (exp)
case ATTR_FLAG:
return;
+
+ default:
+ break;
}
for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++)
@@ -4630,7 +4674,7 @@ write_attr_get (attr)
struct attr_value *av, *common_av;
/* Find the most used attribute value. Handle that as the `default' of the
- switch we will generate. */
+ switch we will generate. */
common_av = find_most_used (attr);
/* Write out start of function, then all values with explicit `case' lines,
@@ -5457,6 +5501,9 @@ copy_rtx_unchanging (orig)
case SYMBOL_REF:
case CODE_LABEL:
return orig;
+
+ default:
+ break;
}
copy = rtx_alloc (code);
@@ -5472,6 +5519,7 @@ copy_rtx_unchanging (orig)
static void
fatal (s, a1, a2)
char *s;
+ char *a1, *a2;
{
fprintf (stderr, "genattrtab: ");
fprintf (stderr, s, a1, a2);
@@ -5540,17 +5588,17 @@ main (argc, argv)
rtx tem;
int i;
-#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 does not fail. */
+ /* Set the stack limit huge so that alloca does not fail. */
getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = rlim.rlim_max;
setrlimit (RLIMIT_STACK, &rlim);
}
-#endif /* RLIMIT_STACK defined */
+#endif
obstack_init (rtl_obstack);
obstack_init (hash_obstack);
@@ -5568,6 +5616,11 @@ main (argc, argv)
init_rtl ();
+ /* We don't use this, but it is referenced in rtlanal.c.
+ Set it up correctly just in case someone tries to use it someday. */
+ pc_rtx = rtx_alloc (PC);
+ PUT_MODE (pc_rtx, VOIDmode);
+
/* Set up true and false rtx's */
true_rtx = rtx_alloc (CONST_INT);
XWINT (true_rtx, 0) = 1;
@@ -5638,6 +5691,7 @@ from the machine description file `md'. */\n\n");
expand_units ();
printf ("#include \"config.h\"\n");
+ printf ("#include <stdio.h>\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"insn-config.h\"\n");
printf ("#include \"recog.h\"\n");
@@ -5675,7 +5729,7 @@ from the machine description file `md'. */\n\n");
/* Construct extra attributes for `length'. */
make_length_attrs ();
- /* Perform any possible optimizations to speed up compilation. */
+ /* Perform any possible optimizations to speed up compilation. */
optimize_attrs ();
/* Now write out all the `gen_attr_...' routines. Do these before the
diff --git a/gnu/usr.bin/gcc/genconfig.c b/gnu/usr.bin/gcc/genconfig.c
index 404534e120c..7bcf0f2b9cd 100644
--- a/gnu/usr.bin/gcc/genconfig.c
+++ b/gnu/usr.bin/gcc/genconfig.c
@@ -1,7 +1,6 @@
/* Generate from machine description:
-
- some #define configuration flags.
- Copyright (C) 1987, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -142,6 +141,9 @@ walk_insn_part (part, recog_p, non_pc_set_src)
case REG: case CONST_INT: case SYMBOL_REF:
case PC:
return;
+
+ default:
+ break;
}
format_ptr = GET_RTX_FORMAT (GET_CODE (part));
diff --git a/gnu/usr.bin/gcc/genemit.c b/gnu/usr.bin/gcc/genemit.c
index ebed4f30af5..dce0e1e7df2 100644
--- a/gnu/usr.bin/gcc/genemit.c
+++ b/gnu/usr.bin/gcc/genemit.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to emit insns as rtl.
- Copyright (C) 1987, 1988, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 94, 95, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -272,7 +272,7 @@ gen_insn (insn)
/* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
registers or MATCH_SCRATCHes. If so, store away the information for
- later. */
+ later. */
if (XVEC (insn, 1))
{
@@ -506,6 +506,7 @@ gen_expand (expand)
}
/* Like gen_expand, but generates a SEQUENCE. */
+
static void
gen_split (split)
rtx split;
@@ -742,9 +743,11 @@ main (argc, argv)
from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
+ printf ("#include <stdio.h>\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"expr.h\"\n");
printf ("#include \"real.h\"\n");
+ printf ("#include \"flags.h\"\n");
printf ("#include \"output.h\"\n");
printf ("#include \"insn-config.h\"\n\n");
printf ("#include \"insn-flags.h\"\n\n");
diff --git a/gnu/usr.bin/gcc/genextract.c b/gnu/usr.bin/gcc/genextract.c
index 3861bd558bc..b0c0b2751b9 100644
--- a/gnu/usr.bin/gcc/genextract.c
+++ b/gnu/usr.bin/gcc/genextract.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to extract operands from insn as rtl.
- Copyright (C) 1987, 1991, 1992, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991, 1992, 1993, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -140,7 +140,7 @@ gen_insn (insn)
link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
link->insn_code = insn_code_number;
- /* See if we find something that already had this extraction method. */
+ /* See if we find something that already had this extraction method. */
for (p = extractions; p; p = p->next)
{
@@ -275,6 +275,9 @@ walk_rtx (x, path)
case ADDRESS:
walk_rtx (XEXP (x, 0), path);
return;
+
+ default:
+ break;
}
newpath = (char *) alloca (depth + 2);
@@ -438,6 +441,7 @@ main (argc, argv)
from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
+ printf ("#include <stdio.h>\n");
printf ("#include \"rtl.h\"\n\n");
/* This variable exists only so it can be the "location"
@@ -455,6 +459,7 @@ from the machine description file `md'. */\n\n");
printf (" register rtx *ro = recog_operand;\n");
printf (" register rtx **ro_loc = recog_operand_loc;\n");
printf (" rtx pat = PATTERN (insn);\n");
+ printf (" int i;\n\n");
printf (" switch (INSN_CODE (insn))\n");
printf (" {\n");
printf (" case -1:\n");
@@ -502,11 +507,8 @@ from the machine description file `md'. */\n\n");
/* The vector in the insn says how many operands it has.
And all it contains are operands. In fact, the vector was
created just for the sake of this function. */
- printf ("#if __GNUC__ > 1 && !defined (bcopy)\n");
- printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n");
- printf ("#endif\n");
- printf (" bcopy (&XVECEXP (pat, 0, 0), ro,\n");
- printf (" sizeof (rtx) * XVECLEN (pat, 0));\n");
+ printf (" for (i = XVECLEN (pat, 0); i >= 0; i--)\n");
+ printf (" ro[i] = XVECEXP (pat, 0, i);\n");
printf (" break;\n\n");
}
diff --git a/gnu/usr.bin/gcc/genflags.c b/gnu/usr.bin/gcc/genflags.c
index e91b45d827b..f8b39833f65 100644
--- a/gnu/usr.bin/gcc/genflags.c
+++ b/gnu/usr.bin/gcc/genflags.c
@@ -50,6 +50,7 @@ static struct obstack call_obstack, normal_obstack;
static int max_id_len;
/* Count the number of match_operand's found. */
+
static int
num_operands (x)
rtx x;
@@ -87,6 +88,7 @@ num_operands (x)
}
/* Print out prototype information for a function. */
+
static void
gen_proto (insn)
rtx insn;
@@ -108,6 +110,7 @@ gen_proto (insn)
}
/* Print out a function declaration without a prototype. */
+
static void
gen_nonproto (insn)
rtx insn;
@@ -258,7 +261,7 @@ from the machine description file `md'. */\n\n");
}
/* Print out the prototypes now. */
- dummy = (rtx)0;
+ dummy = (rtx) 0;
obstack_grow (&call_obstack, &dummy, sizeof (rtx));
call_insns = (rtx *) obstack_finish (&call_obstack);
diff --git a/gnu/usr.bin/gcc/genmultilib b/gnu/usr.bin/gcc/genmultilib
index d4cc7ff7fe5..02206960400 100644
--- a/gnu/usr.bin/gcc/genmultilib
+++ b/gnu/usr.bin/gcc/genmultilib
@@ -1,6 +1,6 @@
#!/bin/sh
# Generates multilib.h.
-# Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
#This file is part of GNU CC.
@@ -42,6 +42,12 @@
# appear in the first argument, and the second should be a synonym for
# it. Question marks are replaced with equal signs in both options.
+# The optional fourth argument is a list of multilib directory
+# combinations that should not be built.
+
+# The optional fifth argument is a list of options that should be
+# used whenever building multilib libraries.
+
# The output looks like
# #define MULTILIB_MATCHES "\
# SUBDIRECTORY OPTIONS;\
@@ -59,16 +65,15 @@
# genmultilib "m68000/m68020 msoft-float" "m68000 m68020 msoft-float"
# "m68000=mc68000"
# This produces:
-# #define MULTILIB_SELECT "\
-# . !m68000 !mc68000 !m68020 !msoft-float;\
-# m68000 m68000 !m68020 !msoft-float;\
-# m68000 mc60000 !m68020 !msoft-float;\
-# m68020 !m68000 !mc68000 m68020 !msoft-float;\
-# msoft-float !m68000 !mc68000 !m68020 msoft-float;\
-# m68000/msoft-float m68000 !m68020 msoft-float;\
-# m68000/msoft-float mc68000 !m68020 msoft-float;\
-# m68020/msoft-float !m68000 !mc68000 m68020 msoft-float;\
-# "
+# ". !m68000 !mc68000 !m68020 !msoft-float;",
+# "m68000 m68000 !m68020 !msoft-float;",
+# "m68000 mc60000 !m68020 !msoft-float;",
+# "m68020 !m68000 !mc68000 m68020 !msoft-float;",
+# "msoft-float !m68000 !mc68000 !m68020 msoft-float;",
+# "m68000/msoft-float m68000 !m68020 msoft-float;",
+# "m68000/msoft-float mc68000 !m68020 msoft-float;",
+# "m68020/msoft-float !m68000 !mc68000 m68020 msoft-float;",
+#
# The effect is that `gcc -msoft-float' (for example) will append
# msoft-float to the directory name when searching for libraries or
# startup files, and `gcc -m68000 -msoft-float' (for example) will
@@ -78,6 +83,10 @@
options=$1
dirnames=$2
matches=$3
+exceptions=$4
+extra=$5
+
+echo "static char *multilib_raw[] = {"
# What we want to do is select all combinations of the sets in
# options. Each combination which includes a set of mutually
@@ -112,6 +121,33 @@ combinations=`initial=/ ./tmpmultilib ${options}`
rm -f tmpmultilib
+# If there exceptions, weed them out now
+if [ -n "${exceptions}" ]; then
+ rm -f tmpmultilib2
+ cat >tmpmultilib2 <<\EOF
+#!/bin/sh
+# This recursive script weeds out any combination of multilib
+# switches that should not be generated. The output looks like
+# a list of subdirectory names with leading and trailing slashes.
+
+ for opt in $@; do
+ case "$opt" in
+EOF
+
+ for except in ${exceptions}; do
+ echo " /${except}/) : ;;" >> tmpmultilib2
+ done
+
+cat >>tmpmultilib2 <<\EOF
+ *) echo ${opt};;
+ esac
+ done
+EOF
+ chmod +x tmpmultilib2
+ combinations=`./tmpmultilib2 ${combinations}`
+ rm -f ./tmpmultilib2
+fi
+
# Construct a sed pattern which will convert option names to directory
# names.
todirnames=
@@ -128,16 +164,6 @@ if [ -n "${dirnames}" ]; then
done
fi
-# Construct a sed pattern which will add negations based on the
-# matches. The semicolons are easier than getting the shell to accept
-# quoted spaces when expanding a variable.
-matchnegations=
-for i in ${matches}; do
- l=`echo $i | sed -e 's/=.*$//' -e 's/?/=/g'`
- r=`echo $i | sed -e 's/^.*=//' -e 's/?/=/g'`
- matchnegations="${matchnegations} -e s/;!${l};/;!${l};!${r};/"
-done
-
# We need another recursive shell script to correctly handle positive
# matches. If we are invoked as
# genmultilib "opt1 opt2" "" "opt1=nopt1 opt2=nopt2"
@@ -154,7 +180,7 @@ cat >tmpmultilib2 <<\EOF
# ${dirout} is the directory name and ${optout} is the current list of
# options.
if [ "$#" = "0" ]; then
- echo "${dirout} ${optout};\\"
+ echo "\"${dirout} ${optout};\","
else
first=$1
shift
@@ -169,9 +195,6 @@ fi
EOF
chmod +x tmpmultilib2
-# We are ready to start output.
-echo '#define MULTILIB_SELECT "\'
-
# Start with the current directory, which includes only negations.
optout=
for set in ${options}; do
@@ -180,10 +203,7 @@ for set in ${options}; do
done
done
optout=`echo ${optout} | sed -e 's/^ //'`
-if [ -n "${matchnegations}" ]; then
- optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'`
-fi
-echo ". ${optout};\\"
+echo "\". ${optout};\","
# Work over the list of combinations. We have to translate each one
# to use the directory names rather than the option names, we have to
@@ -214,18 +234,36 @@ for combo in ${combinations}; do
done
optout=`echo ${optout} | sed -e 's/^ //'`
- # Add any negations of matches.
- if [ -n "${matchnegations}" ]; then
- optout=`echo ";${optout};" | sed -e 's/ /;/g' ${matchnegations} -e 's/^;//' -e 's/;$//' -e 's/;/ /g'`
- fi
-
# Output the line with all appropriate matches.
- dirout="${dirout}" optout="${optout}" ./tmpmultilib2 ${matches}
+ dirout="${dirout}" optout="${optout}" ./tmpmultilib2
done
-rm -f tmpmultilib2
+# Terminate the list of string.
+echo "NULL"
+echo "};"
-# That's it.
-echo '"'
+# Output all of the matches now as option and that is the same as that, with
+# a semicolon trailer. Include all of the normal options as well.
+# Note, the format of the matches is reversed compared
+# to what we want, so switch them around.
+echo ""
+echo "static char *multilib_matches_raw[] = {"
+for match in ${matches}; do
+ l=`echo ${match} | sed -e 's/=.*$//' -e 's/?/=/g'`
+ r=`echo ${match} | sed -e 's/^.*=//' -e 's/?/=/g'`
+ echo "\"${r} ${l};\","
+done
+for set in ${options}; do
+ for opt in `echo ${set} | sed -e 's|/| |'g`; do
+ echo "\"${opt} ${opt};\","
+ done
+done
+echo "NULL"
+echo "};"
+
+# Output the default options now
+echo ""
+echo "static char *multilib_extra = \"${extra}\";"
+rm -f tmpmultilib2
exit 0
diff --git a/gnu/usr.bin/gcc/genopinit.c b/gnu/usr.bin/gcc/genopinit.c
index 39391263587..1d4c0a4b76f 100644
--- a/gnu/usr.bin/gcc/genopinit.c
+++ b/gnu/usr.bin/gcc/genopinit.c
@@ -1,5 +1,5 @@
/* Generate code to initialize optabs from machine description.
- Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -122,7 +122,8 @@ char *optabs[] =
"movcc_gen_code[(int) %A] = CODE_FOR_%(mov%acc%)",
"reload_in_optab[(int) %A] = CODE_FOR_%(reload_in%a%)",
"reload_out_optab[(int) %A] = CODE_FOR_%(reload_out%a%)",
- "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)" };
+ "movstr_optab[(int) %A] = CODE_FOR_%(movstr%a%)",
+ "clrstr_optab[(int) %A] = CODE_FOR_%(clrstr%a%)" };
/* Allow linking with print-rtl.c. */
char **insn_name_ptr;
@@ -184,9 +185,7 @@ gen_insn (insn)
/* We have to be concerned about matching "gt" and
missing "gtu", e.g., so verify we have reached the
- end of thing we are to match. We do not have this
- problem with modes since no mode is a prefix of
- another. */
+ end of thing we are to match. */
if (*p == 0 && *q == 0 && rtx_class[op] == '<')
break;
}
@@ -198,7 +197,11 @@ gen_insn (insn)
break;
case 'a':
case 'b':
- for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
+ /* This loop will stop at the first prefix match, so
+ look through the modes in reverse order, in case
+ EXTRA_CC_MODES was used and CC is a prefix of the
+ CC modes (as it should be). */
+ for (i = ((int) MAX_MACHINE_MODE) - 1; i >= 0; i--)
{
for (p = mode_name[i], q = np; *p; p++, q++)
if (tolower (*p) != *q)
@@ -210,7 +213,7 @@ gen_insn (insn)
break;
}
- if (i == (int) MAX_MACHINE_MODE)
+ if (i < 0)
matches = 0;
else if (*pp == 'a')
m1 = i, np += strlen (mode_name[i]);
@@ -351,6 +354,7 @@ main (argc, argv)
from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
+ printf ("#include <stdio.h>\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"flags.h\"\n");
printf ("#include \"insn-flags.h\"\n");
diff --git a/gnu/usr.bin/gcc/genoutput.c b/gnu/usr.bin/gcc/genoutput.c
index bbf620068b9..4520267c548 100644
--- a/gnu/usr.bin/gcc/genoutput.c
+++ b/gnu/usr.bin/gcc/genoutput.c
@@ -1,5 +1,5 @@
/* Generate code from to output assembler insns as recognized from rtl.
- Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 94, 95, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -180,6 +180,8 @@ output_prologue ()
from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
+ printf ("#include <stdio.h>\n");
+ printf ("#include \"flags.h\"\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"regs.h\"\n");
printf ("#include \"hard-reg-set.h\"\n");
@@ -191,7 +193,6 @@ from the machine description file `md'. */\n\n");
printf ("#include \"insn-codes.h\"\n\n");
printf ("#include \"recog.h\"\n\n");
- printf ("#include <stdio.h>\n");
printf ("#include \"output.h\"\n");
}
@@ -514,6 +515,9 @@ scan_operands (part, this_address_p, this_strict_low)
case STRICT_LOW_PART:
scan_operands (XEXP (part, 0), 0, 1);
return;
+
+ default:
+ break;
}
format_ptr = GET_RTX_FORMAT (GET_CODE (part));
@@ -522,6 +526,7 @@ scan_operands (part, this_address_p, this_strict_low)
switch (*format_ptr++)
{
case 'e':
+ case 'u':
scan_operands (XEXP (part, i), 0, 0);
break;
case 'E':
@@ -581,7 +586,10 @@ process_template (d, template)
printf (" \"");
while (*cp != '\n' && *cp != '\0')
- putchar (*cp++);
+ {
+ putchar (*cp);
+ cp++;
+ }
printf ("\",\n");
i++;
@@ -601,7 +609,11 @@ process_template (d, template)
VAX-11 "C" on VMS. It is the equivalent of:
printf ("%s\n", &template[1])); */
cp = &template[1];
- while (*cp) putchar (*cp++);
+ while (*cp)
+ {
+ putchar (*cp);
+ cp++;
+ }
putchar ('\n');
}
diff --git a/gnu/usr.bin/gcc/genpeep.c b/gnu/usr.bin/gcc/genpeep.c
index ba2328d1f3e..b20fd0d0220 100644
--- a/gnu/usr.bin/gcc/genpeep.c
+++ b/gnu/usr.bin/gcc/genpeep.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to perform peephole optimizations.
- Copyright (C) 1987, 1989, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1989, 1992, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -48,7 +48,6 @@ struct link
char *xmalloc ();
static void match_rtx ();
-static void gen_exp ();
static void fatal ();
void fancy_abort ();
@@ -264,6 +263,9 @@ match_rtx (x, path, fail_label)
case ADDRESS:
match_rtx (XEXP (x, 0), path, fail_label);
return;
+
+ default:
+ break;
}
printf (" x = ");
@@ -455,6 +457,7 @@ main (argc, argv)
from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
+ printf ("#include <stdio.h>\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"regs.h\"\n");
printf ("#include \"output.h\"\n");
diff --git a/gnu/usr.bin/gcc/genrecog.c b/gnu/usr.bin/gcc/genrecog.c
index 21f1c06c4fc..f75f1b4be8f 100644
--- a/gnu/usr.bin/gcc/genrecog.c
+++ b/gnu/usr.bin/gcc/genrecog.c
@@ -1,5 +1,5 @@
/* Generate code from machine description to recognize rtl as insns.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -120,7 +120,7 @@ static int next_number;
static int next_insn_code;
/* Similar, but counts all expressions in the MD file; used for
- error messages. */
+ error messages. */
static int next_index;
@@ -498,7 +498,7 @@ add_to_sequence (pattern, last, position)
if (GET_CODE (XEXP (pattern, 0)) == CC0)
break;
- /* ... fall through ... */
+ /* ... fall through ... */
case COMPARE:
/* Enforce the mode on the first operand to avoid ambiguous insns. */
@@ -508,6 +508,9 @@ add_to_sequence (pattern, last, position)
newpos[depth] = '1';
new = add_to_sequence (XEXP (pattern, 1), &new->success, newpos);
return new;
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -572,7 +575,7 @@ not_both_true (d1, d2, toplevel)
struct decision *p1, *p2;
/* If they are both to test modes and the modes are different, they aren't
- both true. Similarly for codes, integer elements, and vector lengths. */
+ both true. Similarly for codes, integer elements, and vector lengths. */
if ((d1->enforce_mode && d2->enforce_mode
&& d1->mode != VOIDmode && d2->mode != VOIDmode && d1->mode != d2->mode)
@@ -1139,7 +1142,7 @@ write_tree_1 (tree, prevpos, afterward, type)
seen any of the codes that are valid for the predicate, we
can write a series of "case" statement, one for each possible
code. Since we are already in a switch, these redundant tests
- are very cheap and will reduce the number of predicate called. */
+ are very cheap and will reduce the number of predicate called. */
if (p->pred >= 0)
{
@@ -1286,6 +1289,8 @@ write_tree_1 (tree, prevpos, afterward, type)
printf ("%sswitch (GET_MODE (x%d))\n", indents[indent], depth);
printf ("%s{\n", indents[indent + 2]);
indent += 4;
+ printf ("%sdefault:\n%sbreak;\n", indents[indent - 2],
+ indents[indent]);
printf ("%scase %smode:\n", indents[indent - 2],
GET_MODE_NAME (mode));
modemap[(int) mode] = 1;
@@ -1301,6 +1306,8 @@ write_tree_1 (tree, prevpos, afterward, type)
printf ("%sswitch (GET_CODE (x%d))\n", indents[indent], depth);
printf ("%s{\n", indents[indent + 2]);
indent += 4;
+ printf ("%sdefault:\n%sbreak;\n", indents[indent - 2],
+ indents[indent]);
printf ("%scase ", indents[indent - 2]);
print_code (p->code);
printf (":\n");
@@ -1309,7 +1316,7 @@ write_tree_1 (tree, prevpos, afterward, type)
}
/* Now that most mode and code tests have been done, we can write out
- a label for an inner node, if we haven't already. */
+ a label for an inner node, if we haven't already. */
if (p->label_needed)
printf ("%sL%d:\n", indents[indent - 2], p->number);
@@ -1736,6 +1743,7 @@ main (argc, argv)
from the machine description file `md'. */\n\n");
printf ("#include \"config.h\"\n");
+ printf ("#include <stdio.h>\n");
printf ("#include \"rtl.h\"\n");
printf ("#include \"insn-config.h\"\n");
printf ("#include \"recog.h\"\n");
diff --git a/gnu/usr.bin/gcc/getopt.c b/gnu/usr.bin/gcc/getopt.c
index beb7450dd9c..fc87ce67d69 100644
--- a/gnu/usr.bin/gcc/getopt.c
+++ b/gnu/usr.bin/gcc/getopt.c
@@ -3,9 +3,12 @@
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97
Free Software Foundation, Inc.
+ NOTE: The canonical source of this file is maintained with the GNU C Library.
+ Bugs can be reported to bug-glibc@prep.ai.mit.edu.
+
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
@@ -18,7 +21,8 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
@@ -48,7 +52,15 @@
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
/* This needs to come after some library #include
@@ -57,8 +69,16 @@
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
+#include <unistd.h>
#endif /* GNU C library. */
+#ifdef VMS
+#include <unixlib.h>
+#if HAVE_STRING_H - 0
+#include <string.h>
+#endif
+#endif
+
#ifndef _
/* This is for other GNU distributions with internationalized messages.
When compiling libc, the _ macro is predefined. */
@@ -100,14 +120,20 @@ char *optarg = NULL;
On entry to `getopt', zero means this is the first call; initialize.
- When `getopt' returns EOF, this is the index of the first of the
+ When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
-/* XXX 1003.2 says this must be 1 before any call. */
-int optind = 0;
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
@@ -156,7 +182,7 @@ int optopt = '?';
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
- `--' can cause `getopt' to return EOF with `optind' != ARGC. */
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
static enum
{
@@ -217,6 +243,46 @@ extern int strlen (const char *);
static int first_nonopt;
static int last_nonopt;
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# define SWAP_FLAGS(ch1, ch2) \
+ if (nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
@@ -226,6 +292,10 @@ static int last_nonopt;
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
+#if defined (__STDC__) && __STDC__
+static void exchange (char **);
+#endif
+
static void
exchange (argv)
char **argv;
@@ -240,6 +310,28 @@ exchange (argv)
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
+#ifdef _LIBC
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
@@ -254,6 +346,7 @@ exchange (argv)
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
@@ -270,6 +363,7 @@ exchange (argv)
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
@@ -284,15 +378,20 @@ exchange (argv)
/* Initialize the internal data when the first call is made. */
+#if defined (__STDC__) && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
static const char *
-_getopt_initialize (optstring)
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
const char *optstring;
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
- first_nonopt = last_nonopt = optind = 1;
+ first_nonopt = last_nonopt = optind;
nextchar = NULL;
@@ -315,6 +414,36 @@ _getopt_initialize (optstring)
else
ordering = PERMUTE;
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ if (nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len = strlen (orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', nonoption_flags_max_len - len);
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
return optstring;
}
@@ -331,7 +460,7 @@ _getopt_initialize (optstring)
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
- If there are no more option characters, `getopt' returns `EOF'.
+ If there are no more option characters, `getopt' returns -1.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
@@ -385,16 +514,37 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
{
optarg = NULL;
- if (optind == 0)
+ if (optind == 0 || !__getopt_initialized)
{
- optstring = _getopt_initialize (optstring);
- optind = 1; /* Don't scan ARGV[0], the program name. */
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring);
+ __getopt_initialized = 1;
}
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && __getopt_nonoption_flags[optind] == '1'))
+#else
+#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
if (nextchar == NULL || *nextchar == '\0')
{
/* Advance to the next ARGV-element. */
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
@@ -408,8 +558,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
- while (optind < argc
- && (argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ while (optind < argc && NONOPTION_P)
optind++;
last_nonopt = optind;
}
@@ -441,16 +590,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
- return EOF;
+ return -1;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
- if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
+ if (NONOPTION_P)
{
if (ordering == REQUIRE_ORDER)
- return EOF;
+ return -1;
optarg = argv[optind++];
return 1;
}
@@ -486,7 +635,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
- int indfound;
+ int indfound = -1;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
@@ -497,7 +646,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
- if (nameend - nextchar == strlen (p->name))
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
{
/* Exact match found. */
pfound = p;
@@ -523,6 +673,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
+ optopt = 0;
return '?';
}
@@ -551,6 +702,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
argv[0], argv[optind - 1][0], pfound->name);
nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
return '?';
}
}
@@ -565,6 +718,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
_("%s: option `%s' requires an argument\n"),
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
+ optopt = pfound->val;
return optstring[0] == ':' ? ':' : '?';
}
}
@@ -599,6 +753,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
}
nextchar = (char *) "";
optind++;
+ optopt = 0;
return '?';
}
}
@@ -628,6 +783,130 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only)
optopt = c;
return '?';
}
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (opterr)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (opterr)
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (opterr)
+ fprintf (stderr, _("\
+%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (opterr)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
if (temp[1] == ':')
{
if (temp[2] == ':')
@@ -690,7 +969,7 @@ getopt (argc, argv, optstring)
0);
}
-#endif /* _LIBC or not __GNU_LIBRARY__. */
+#endif /* Not ELIDE_CODE. */
#ifdef TEST
@@ -710,7 +989,7 @@ main (argc, argv)
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
- if (c == EOF)
+ if (c == -1)
break;
switch (c)
diff --git a/gnu/usr.bin/gcc/getopt.h b/gnu/usr.bin/gcc/getopt.h
index 4ac33b71824..c4adc30bbba 100644
--- a/gnu/usr.bin/gcc/getopt.h
+++ b/gnu/usr.bin/gcc/getopt.h
@@ -1,5 +1,8 @@
/* Declarations for getopt.
- Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the GNU C Library.
+ Bugs can be reported to bug-glibc@prep.ai.mit.edu.
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
@@ -13,7 +16,8 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
#ifndef _GETOPT_H
#define _GETOPT_H 1
@@ -36,7 +40,7 @@ extern char *optarg;
On entry to `getopt', zero means this is the first call; initialize.
- When `getopt' returns EOF, this is the index of the first of the
+ When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
@@ -126,4 +130,4 @@ extern int _getopt_internal ();
}
#endif
-#endif /* _GETOPT_H */
+#endif /* getopt.h */
diff --git a/gnu/usr.bin/gcc/getopt1.c b/gnu/usr.bin/gcc/getopt1.c
index 4580211cfac..af8e6819657 100644
--- a/gnu/usr.bin/gcc/getopt1.c
+++ b/gnu/usr.bin/gcc/getopt1.c
@@ -1,6 +1,8 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994
- Free Software Foundation, Inc.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+
+ NOTE: The canonical source of this file is maintained with the GNU C Library.
+ Bugs can be reported to bug-glibc@prep.ai.mit.edu.
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
@@ -14,7 +16,8 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -40,15 +43,21 @@
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
+#define GETOPT_INTERFACE_VERSION 2
+#if !defined (_LIBC) && defined (__GLIBC__) && __GLIBC__ >= 2
+#include <gnu-versions.h>
+#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION
+#define ELIDE_CODE
+#endif
+#endif
+
+#ifndef ELIDE_CODE
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
#include <stdlib.h>
-#else
-char *getenv ();
#endif
#ifndef NULL
@@ -83,7 +92,7 @@ getopt_long_only (argc, argv, options, long_options, opt_index)
}
-#endif /* _LIBC or not __GNU_LIBRARY__. */
+#endif /* Not ELIDE_CODE. */
#ifdef TEST
@@ -114,7 +123,7 @@ main (argc, argv)
c = getopt_long (argc, argv, "abc:d:0123456789",
long_options, &option_index);
- if (c == EOF)
+ if (c == -1)
break;
switch (c)
diff --git a/gnu/usr.bin/gcc/getpwd.c b/gnu/usr.bin/gcc/getpwd.c
index 3692e92bc58..28eb298ebf9 100644
--- a/gnu/usr.bin/gcc/getpwd.c
+++ b/gnu/usr.bin/gcc/getpwd.c
@@ -28,14 +28,11 @@ extern char *getcwd ();
/* We actually use this as a starting point, not a limit. */
#define GUESSPATHLEN 100
#endif /* (defined (USG) || defined (VMS)) */
-#ifdef _WIN32
-#include <direct.h>
-#endif
char *getenv ();
char *xmalloc ();
-#ifndef VMS
+#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN32__)))
/* Get the working directory. Use the PWD environment variable if it's
set correctly, since this is faster and gives more uniform answers
@@ -83,7 +80,7 @@ getpwd ()
return p;
}
-#else /* VMS */
+#else /* VMS || _WIN32 && !__CYGWIN32__ */
#ifndef MAXPATHLEN
#define MAXPATHLEN 255
@@ -94,8 +91,13 @@ getpwd ()
{
static char *pwd = 0;
- if (!pwd) pwd = getcwd (xmalloc (MAXPATHLEN+1), MAXPATHLEN+1);
+ if (!pwd)
+ pwd = getcwd (xmalloc (MAXPATHLEN + 1), MAXPATHLEN + 1
+#ifdef VMS
+ , 0
+#endif
+ );
return pwd;
}
-#endif /* VMS */
+#endif /* VMS || _WIN32 && !__CYGWIN32__ */
diff --git a/gnu/usr.bin/gcc/ginclude/va-alpha.h b/gnu/usr.bin/gcc/ginclude/va-alpha.h
index 33f6c2dec74..2a4ba60b532 100644
--- a/gnu/usr.bin/gcc/ginclude/va-alpha.h
+++ b/gnu/usr.bin/gcc/ginclude/va-alpha.h
@@ -10,10 +10,19 @@
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
+
+/* In VMS, __gnuc_va_list is simply char *; on OSF, it's a structure. */
+
+#ifdef __VMS__
+typedef char *__gnuc_va_list;
+#else
+
typedef struct {
char *__base; /* Pointer to first integer register. */
int __offset; /* Byte offset of args so far. */
} __gnuc_va_list;
+#endif
+
#endif /* not __GNUC_VA_LIST */
/* If this is for internal libc use, don't define anything but
@@ -29,7 +38,11 @@ typedef struct {
/* varargs support */
#define va_alist __builtin_va_alist
#define va_dcl int __builtin_va_alist;...
+#ifdef __VMS__
+#define va_start(pvar) ((pvar) = __builtin_saveregs ())
+#else
#define va_start(pvar) ((pvar) = * (__gnuc_va_list *) __builtin_saveregs ())
+#endif
#else /* STDARG.H */
@@ -37,9 +50,16 @@ typedef struct {
/* Call __builtin_next_arg even though we aren't using its value, so that
we can verify that firstarg is correct. */
+
+#ifdef __VMS__
+#define va_start(pvar, firstarg) \
+ (__builtin_next_arg (firstarg), \
+ (pvar) = __builtin_saveregs ())
+#else
#define va_start(pvar, firstarg) \
(__builtin_next_arg (firstarg), \
(pvar) = *(__gnuc_va_list *) __builtin_saveregs ())
+#endif
#endif /* _STDARG_H */
@@ -89,12 +109,23 @@ enum {
(((sizeof (__type) + __extension__ sizeof (long long) - 1) \
/ __extension__ sizeof (long long)) * __extension__ sizeof (long long))
+#ifdef __VMS__
+#define va_arg(__va, __type) \
+(*(((__va) += __va_tsize (__type)), \
+ (__type *)(void *)((__va) - __va_tsize (__type))))
+
+#else
+
#define va_arg(__va, __type) \
(*(((__va).__offset += __va_tsize (__type)), \
(__type *)(void *)((__va).__base + (__va).__offset \
- (((__builtin_classify_type (* (__type *) 0) \
== __real_type_class) && (__va).__offset <= (6 * 8)) \
? (6 * 8) + 8 : __va_tsize (__type)))))
+#endif
+
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-clipper.h b/gnu/usr.bin/gcc/ginclude/va-clipper.h
index 21ddc562885..38cc77f9c1a 100644
--- a/gnu/usr.bin/gcc/ginclude/va-clipper.h
+++ b/gnu/usr.bin/gcc/ginclude/va-clipper.h
@@ -54,4 +54,7 @@ typedef struct
#define va_end(AP) ((void) 0)
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-h8300.h b/gnu/usr.bin/gcc/ginclude/va-h8300.h
index 986e827f64d..9565696e9ad 100644
--- a/gnu/usr.bin/gcc/ginclude/va-h8300.h
+++ b/gnu/usr.bin/gcc/ginclude/va-h8300.h
@@ -44,10 +44,13 @@ typedef void *__gnuc_va_list;
#define va_arg(AP, TYPE) \
(AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
- *((TYPE *) (void *) ((char *) (AP) - ((sizeof (TYPE) < 4 \
- ? sizeof (TYPE) \
- : __va_rounded_size (TYPE))))))
+ *((TYPE *) (void *) ((char *) (AP) \
+ - ((sizeof (TYPE) < __va_rounded_size (int) \
+ ? sizeof (TYPE) : __va_rounded_size (TYPE))))))
#define va_end(AP) ((void) 0)
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-i860.h b/gnu/usr.bin/gcc/ginclude/va-i860.h
index 9b9908a0aa5..56d2c7fe1d3 100644
--- a/gnu/usr.bin/gcc/ginclude/va-i860.h
+++ b/gnu/usr.bin/gcc/ginclude/va-i860.h
@@ -207,5 +207,8 @@ __extension__ \
__rv; \
}))
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-i960.h b/gnu/usr.bin/gcc/ginclude/va-i960.h
index a30d5f542a4..ba0d08ba893 100644
--- a/gnu/usr.bin/gcc/ginclude/va-i960.h
+++ b/gnu/usr.bin/gcc/ginclude/va-i960.h
@@ -72,5 +72,8 @@ void va_end (__gnuc_va_list); /* Defined in libgcc.a */
#endif
#define va_end(AP) ((void *)0)
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-m88k.h b/gnu/usr.bin/gcc/ginclude/va-m88k.h
index 7f8974b9c49..0a20d84501c 100644
--- a/gnu/usr.bin/gcc/ginclude/va-m88k.h
+++ b/gnu/usr.bin/gcc/ginclude/va-m88k.h
@@ -81,4 +81,7 @@ typedef struct
#define va_end(AP) ((void)0)
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-mips.h b/gnu/usr.bin/gcc/ginclude/va-mips.h
index 3cf1c920af5..a622199388e 100644
--- a/gnu/usr.bin/gcc/ginclude/va-mips.h
+++ b/gnu/usr.bin/gcc/ginclude/va-mips.h
@@ -13,13 +13,54 @@
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
+#if defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)
+
+typedef struct {
+ /* Pointer to FP regs. */
+ char *__fp_regs;
+ /* Number of FP regs remaining. */
+ int __fp_left;
+ /* Pointer to GP regs followed by stack parameters. */
+ char *__gp_regs;
+} __gnuc_va_list;
+
+#else /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
+
typedef char * __gnuc_va_list;
+
+#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
#endif /* not __GNUC_VA_LIST */
/* If this is for internal libc use, don't define anything but
__gnuc_va_list. */
#if defined (_STDARG_H) || defined (_VARARGS_H)
+#ifndef _VA_MIPS_H_ENUM
+#define _VA_MIPS_H_ENUM
+enum {
+ __no_type_class = -1,
+ __void_type_class,
+ __integer_type_class,
+ __char_type_class,
+ __enumeral_type_class,
+ __boolean_type_class,
+ __pointer_type_class,
+ __reference_type_class,
+ __offset_type_class,
+ __real_type_class,
+ __complex_type_class,
+ __function_type_class,
+ __method_type_class,
+ __record_type_class,
+ __union_type_class,
+ __array_type_class,
+ __string_type_class,
+ __set_type_class,
+ __file_type_class,
+ __lang_type_class
+};
+#endif
+
/* In GCC version 2, we want an ellipsis at the end of the declaration
of the argument list. GCC version 1 can't parse it. */
@@ -37,16 +78,49 @@ typedef char * __gnuc_va_list;
(((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
#endif
+#ifdef __mips64
+#define __va_reg_size 8
+#else
+#define __va_reg_size 4
+#endif
+
/* Get definitions for _MIPS_SIM_ABI64 etc. */
#ifdef _MIPS_SIM
#include <sgidefs.h>
#endif
#ifdef _STDARG_H
+#if defined (__mips_eabi)
+#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
+#ifdef __mips64
+#define va_start(__AP, __LASTARG) \
+ (__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG) \
+ - (__builtin_args_info (2) < 8 \
+ ? (8 - __builtin_args_info (2)) * __va_reg_size \
+ : 0)), \
+ __AP.__fp_left = 8 - __builtin_args_info (3), \
+ __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size)
+#else /* ! defined (__mips64) */
+#define va_start(__AP, __LASTARG) \
+ (__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG) \
+ - (__builtin_args_info (2) < 8 \
+ ? (8 - __builtin_args_info (2)) * __va_reg_size \
+ : 0)), \
+ __AP.__fp_left = (8 - __builtin_args_info (3)) / 2, \
+ __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8, \
+ __AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8))
+#endif /* ! defined (__mips64) */
+#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */
+#define va_start(__AP, __LASTARG) \
+ (__AP = ((__gnuc_va_list) __builtin_next_arg (__LASTARG) \
+ - (__builtin_args_info (2) >= 8 ? 0 \
+ : (8 - __builtin_args_info (2)) * __va_reg_size)))
+#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */
+#else /* ! defined (__mips_eabi) */
#define va_start(__AP, __LASTARG) \
(__AP = (__gnuc_va_list) __builtin_next_arg (__LASTARG))
-
-#else
+#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
+#else /* ! _STDARG_H */
#define va_alist __builtin_va_alist
#ifdef __mips64
/* This assumes that `long long int' is always a 64 bit type. */
@@ -54,21 +128,109 @@ typedef char * __gnuc_va_list;
#else
#define va_dcl int __builtin_va_alist; __va_ellipsis
#endif
+#if defined (__mips_eabi)
+#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
+#ifdef __mips64
+#define va_start(__AP) \
+ (__AP.__gp_regs = ((char *) __builtin_next_arg () \
+ - (__builtin_args_info (2) < 8 \
+ ? (8 - __builtin_args_info (2)) * __va_reg_size \
+ : __va_reg_size)), \
+ __AP.__fp_left = 8 - __builtin_args_info (3), \
+ __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size)
+#else /* ! defined (__mips64) */
+#define va_start(__AP) \
+ (__AP.__gp_regs = ((char *) __builtin_next_arg () \
+ - (__builtin_args_info (2) < 8 \
+ ? (8 - __builtin_args_info (2)) * __va_reg_size \
+ : __va_reg_size)), \
+ __AP.__fp_left = (8 - __builtin_args_info (3)) / 2, \
+ __AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8, \
+ __AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8))
+#endif /* ! defined (__mips64) */
+#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
+#define va_start(__AP) \
+ (__AP = ((__gnuc_va_list) __builtin_next_arg () \
+ - (__builtin_args_info (2) >= 8 ? __va_reg_size \
+ : (8 - __builtin_args_info (2)) * __va_reg_size)))
+#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
/* Need alternate code for _MIPS_SIM_ABI64. */
-#if defined(_MIPS_SIM) && (_MIPS_SIM == _MIPS_SIM_ABI64)
+#elif defined(_MIPS_SIM) && (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)
#define va_start(__AP) \
(__AP = (__gnuc_va_list) __builtin_next_arg () \
+ (__builtin_args_info (2) >= 8 ? -8 : 0))
#else
#define va_start(__AP) __AP = (char *) &__builtin_va_alist
#endif
-#endif
+#endif /* ! _STDARG_H */
#ifndef va_end
void va_end (__gnuc_va_list); /* Defined in libgcc.a */
#endif
#define va_end(__AP) ((void)0)
+#if defined (__mips_eabi)
+
+#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
+#ifdef __mips64
+#define __va_next_addr(__AP, __type) \
+ ((__builtin_classify_type (*(__type *) 0) == __real_type_class \
+ && __AP.__fp_left > 0) \
+ ? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8) \
+ : (__AP.__gp_regs += __va_reg_size) - __va_reg_size)
+#else
+#define __va_next_addr(__AP, __type) \
+ ((__builtin_classify_type (*(__type *) 0) == __real_type_class \
+ && __AP.__fp_left > 0) \
+ ? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8) \
+ : (((__builtin_classify_type (* (__type *) 0) < __record_type_class \
+ && __alignof__ (__type) > 4) \
+ ? __AP.__gp_regs = (char *) (((int) __AP.__gp_regs + 8 - 1) & -8) \
+ : (char *) 0), \
+ (__builtin_classify_type (* (__type *) 0) >= __record_type_class \
+ ? (__AP.__gp_regs += __va_reg_size) - __va_reg_size \
+ : ((__AP.__gp_regs += __va_rounded_size (__type)) \
+ - __va_rounded_size (__type)))))
+#endif
+#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
+#ifdef __mips64
+#define __va_next_addr(__AP, __type) \
+ ((__AP += __va_reg_size) - __va_reg_size)
+#else
+#define __va_next_addr(__AP, __type) \
+ (((__builtin_classify_type (* (__type *) 0) < __record_type_class \
+ && __alignof__ (__type) > 4) \
+ ? __AP = (char *) (((int) __AP + 8 - 1) & -8) \
+ : (char *) 0), \
+ (__builtin_classify_type (* (__type *) 0) >= __record_type_class \
+ ? (__AP += __va_reg_size) - __va_reg_size \
+ : ((__AP += __va_rounded_size (__type)) \
+ - __va_rounded_size (__type))))
+#endif
+#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
+
+#ifdef __MIPSEB__
+#define va_arg(__AP, __type) \
+ ((__va_rounded_size (__type) <= __va_reg_size) \
+ ? *(__type *) (void *) (__va_next_addr (__AP, __type) \
+ + __va_reg_size \
+ - sizeof (__type)) \
+ : (__builtin_classify_type (*(__type *) 0) >= __record_type_class \
+ ? **(__type **) (void *) (__va_next_addr (__AP, __type) \
+ + __va_reg_size \
+ - sizeof (char *)) \
+ : *(__type *) (void *) __va_next_addr (__AP, __type)))
+#else
+#define va_arg(__AP, __type) \
+ ((__va_rounded_size (__type) <= __va_reg_size) \
+ ? *(__type *) (void *) __va_next_addr (__AP, __type) \
+ : (__builtin_classify_type (* (__type *) 0) >= __record_type_class \
+ ? **(__type **) (void *) __va_next_addr (__AP, __type) \
+ : *(__type *) (void *) __va_next_addr (__AP, __type)))
+#endif
+
+#else /* ! defined (__mips_eabi) */
+
/* We cast to void * and then to TYPE * because this avoids
a warning about increasing the alignment requirement. */
/* The __mips64 cases are reversed from the 32 bit cases, because the standard
@@ -106,5 +268,9 @@ void va_end (__gnuc_va_list); /* Defined in libgcc.a */
+ __va_rounded_size(__type))))[-1]
#endif
#endif
+#endif /* ! defined (__mips_eabi) */
+
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-pa.h b/gnu/usr.bin/gcc/ginclude/va-pa.h
index b6b81dd0925..4865f6bfac0 100644
--- a/gnu/usr.bin/gcc/ginclude/va-pa.h
+++ b/gnu/usr.bin/gcc/ginclude/va-pa.h
@@ -4,7 +4,7 @@
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
-typedef double *__gnuc_va_list;
+typedef void *__gnuc_va_list;
#endif /* not __GNUC_VA_LIST */
/* If this is for internal libc use, don't define anything but
@@ -46,4 +46,7 @@ void va_end (__gnuc_va_list); /* Defined in libgcc.a */
#endif
#define va_end(AP) ((void)0)
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-ppc.h b/gnu/usr.bin/gcc/ginclude/va-ppc.h
index 09f11e0d298..3d9d3f04228 100644
--- a/gnu/usr.bin/gcc/ginclude/va-ppc.h
+++ b/gnu/usr.bin/gcc/ginclude/va-ppc.h
@@ -1,13 +1,22 @@
-/* GNU C varargs support for the PowerPC with V.4 calling sequence */
+/* GNU C varargs support for the PowerPC with either the V.4 or Windows NT calling sequences */
+#ifndef _WIN32
+/* System V.4 support */
/* Define __gnuc_va_list. */
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
+#ifndef _SYS_VA_LIST_H
+#define _SYS_VA_LIST_H /* Solaris sys/va_list.h */
+
+/* Solaris decided to rename overflow_arg_area to input_arg_area,
+ so handle it via a macro. */
+#define __va_overflow(AP) (AP)->overflow_arg_area
+
/* Note that the names in this structure are in the user's namespace, but
that the V.4 abi explicitly states that these names should be used. */
-typedef struct {
+typedef struct __va_list_tag {
char gpr; /* index into the array of 8 GPRs stored in the
register save area gpr=0 corresponds to r3,
gpr=1 to r4, etc. */
@@ -17,7 +26,14 @@ typedef struct {
char *overflow_arg_area; /* location on stack that holds the next
overflow argument */
char *reg_save_area; /* where r3:r10 and f1:f8, if saved are stored */
-} __gnuc_va_list[1];
+} __va_list[1], __gnuc_va_list[1];
+
+#else /* _SYS_VA_LIST */
+
+typedef __va_list __gnuc_va_list;
+#define __va_overflow(AP) (AP)->input_arg_area
+
+#endif /* not _SYS_VA_LIST */
#endif /* not __GNUC_VA_LIST */
/* If this is for internal libc use, don't define anything but
@@ -25,6 +41,8 @@ typedef struct {
#if defined (_STDARG_H) || defined (_VARARGS_H)
/* Register save area located below the frame pointer */
+#ifndef __VA_PPC_H__
+#define __VA_PPC_H__
typedef struct {
long __gp_save[8]; /* save area for GP registers */
double __fp_save[8]; /* save area for FP registers */
@@ -64,9 +82,9 @@ __extension__ ({ \
(AP)->fpr = __va_fregno - 33; \
(AP)->reg_save_area = (((char *) __builtin_frame_address (0)) \
+ __va_varargs_offset); \
- (AP)->overflow_arg_area = ((char *)__builtin_saveregs () \
- + (((__words >= 8) ? __words - 8 : 0) \
- * sizeof (long))); \
+ __va_overflow(AP) = ((char *)__builtin_saveregs () \
+ + (((__words >= 8) ? __words - 8 : 0) \
+ * sizeof (long))); \
(void)0; \
})
@@ -91,6 +109,9 @@ __extension__ ({ \
#define __va_float_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == 8)
#endif
+#define __va_longlong_p(TYPE) \
+ ((__builtin_classify_type(*(TYPE *)0) == 1) && (sizeof(TYPE) == 8))
+
#define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12)
#define __va_size(TYPE) ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long))
@@ -111,8 +132,13 @@ __extension__ (*({ \
} \
\
else if (!__va_float_p (TYPE) && !__va_aggregate_p (TYPE) \
- && (AP)->gpr + __va_size(TYPE) <= 8) \
+ && (AP)->gpr + __va_size(TYPE) <= 8 \
+ && (!__va_longlong_p(TYPE) \
+ || (AP)->gpr + __va_size(TYPE) <= 7)) \
{ \
+ if (__va_longlong_p(TYPE) && ((AP)->gpr & 1) != 0) \
+ (AP)->gpr++; \
+ \
__ptr = __VA_GP_REGSAVE (AP, TYPE); \
(AP)->gpr += __va_size (TYPE); \
} \
@@ -121,19 +147,22 @@ __extension__ (*({ \
&& (AP)->gpr < 8) \
{ \
(AP)->gpr = 8; \
- __ptr = (TYPE *) (void *) ((AP)->overflow_arg_area); \
- (AP)->overflow_arg_area += __va_size (TYPE) * sizeof (long); \
+ __ptr = (TYPE *) (void *) (__va_overflow(AP)); \
+ __va_overflow(AP) += __va_size (TYPE) * sizeof (long); \
} \
\
else if (__va_aggregate_p (TYPE)) \
{ \
- __ptr = * (TYPE **) (void *) ((AP)->overflow_arg_area); \
- (AP)->overflow_arg_area += sizeof (TYPE *); \
+ __ptr = * (TYPE **) (void *) (__va_overflow(AP)); \
+ __va_overflow(AP) += sizeof (TYPE *); \
} \
else \
{ \
- __ptr = (TYPE *) (void *) ((AP)->overflow_arg_area); \
- (AP)->overflow_arg_area += __va_size (TYPE) * sizeof (long); \
+ if (__va_longlong_p(TYPE) && ((long)__va_overflow(AP) & 4) != 0) \
+ __va_overflow(AP) += 4; \
+ \
+ __ptr = (TYPE *) (void *) (__va_overflow(AP)); \
+ __va_overflow(AP) += __va_size (TYPE) * sizeof (long); \
} \
\
__ptr; \
@@ -141,4 +170,64 @@ __extension__ (*({ \
#define va_end(AP) ((void)0)
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) *(dest) = *(src)
+
+#endif /* __VA_PPC_H__ */
+#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
+
+
+#else
+/* Windows NT */
+/* Define __gnuc_va_list. */
+
+#ifndef __GNUC_VA_LIST
+#define __GNUC_VA_LIST
+typedef char *__gnuc_va_list;
+#endif /* not __GNUC_VA_LIST */
+
+/* If this is for internal libc use, don't define anything but
+ __gnuc_va_list. */
+#if defined (_STDARG_H) || defined (_VARARGS_H)
+
+#define __va_start_common(AP, LASTARG, FAKE) \
+ ((__builtin_saveregs ()), ((AP) = ((char *) &LASTARG) + __va_rounded_size (AP)), 0)
+
+#ifdef _STDARG_H /* stdarg.h support */
+
+/* Calling __builtin_next_arg gives the proper error message if LASTARG is
+ not indeed the last argument. */
+#define va_start(AP,LASTARG) \
+ (__builtin_saveregs (), \
+ (AP) = __builtin_next_arg (LASTARG), \
+ 0)
+
+#else /* varargs.h support */
+
+#define va_start(AP) \
+ (__builtin_saveregs (), \
+ (AP) = __builtin_next_arg (__va_1st_arg) - sizeof (int), \
+ 0)
+
+#define va_alist __va_1st_arg
+#define va_dcl register int __va_1st_arg; ...
+
+#endif /* _STDARG_H */
+
+#define __va_rounded_size(TYPE) ((sizeof (TYPE) + 3) & ~3)
+#define __va_align(AP, TYPE) \
+ ((((unsigned long)(AP)) + ((sizeof (TYPE) >= 8) ? 7 : 3)) \
+ & ~((sizeof (TYPE) >= 8) ? 7 : 3))
+
+#define va_arg(AP,TYPE) \
+( *(TYPE *)((AP = (char *) (__va_align(AP, TYPE) \
+ + __va_rounded_size(TYPE))) \
+ - __va_rounded_size(TYPE)))
+
+#define va_end(AP) ((void)0)
+
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
+#endif /* Windows NT */
diff --git a/gnu/usr.bin/gcc/ginclude/va-sparc.h b/gnu/usr.bin/gcc/ginclude/va-sparc.h
index 40a24044033..73c9de1cd9a 100644
--- a/gnu/usr.bin/gcc/ginclude/va-sparc.h
+++ b/gnu/usr.bin/gcc/ginclude/va-sparc.h
@@ -5,19 +5,7 @@
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
-
-#ifdef __sparc_v9__
-typedef long long __va_greg;
-typedef double __va_freg;
-typedef struct {
- __va_greg * __va_next_o; /* next available %o* register */
- __va_greg * __va_next_o_limit; /* past last available %o* register */
- __va_freg * __va_next_fp; /* next available %f* register */
- __va_freg * __va_next_fp_limit; /* last available %f* register */
- __va_greg * __va_next_stack; /* next extended word on stack */
-} __gnuc_va_list;
-#else
-#ifndef __svr4__
+#if ! defined (__svr4__) && ! defined (__linux__) && ! defined (__arch64__)
/* This has to be a char * to be compatible with Sun.
i.e., we have to pass a `va_list' to vsprintf. */
typedef char * __gnuc_va_list;
@@ -26,7 +14,6 @@ typedef char * __gnuc_va_list;
i.e., we have to pass a `va_list' to vsprintf. */
typedef void * __gnuc_va_list;
#endif
-#endif /* not __sparc_v9__ */
#endif /* not __GNUC_VA_LIST */
/* If this is for internal libc use, don't define anything but
@@ -35,56 +22,27 @@ typedef void * __gnuc_va_list;
#ifdef _STDARG_H
-#ifdef __sparc_v9__
-#define va_start(AP, LASTARG) \
-__extension__ \
- ({ \
- AP.__va_next_o = (__va_greg *) __builtin_saveregs (); \
- AP.__va_next_o_limit = (AP.__va_next_o + \
- (__builtin_args_info (0) < 6 ? 6 - __builtin_args_info (0) : 0)); \
- AP.__va_next_fp = (__va_freg *) AP.__va_next_o_limit; \
- AP.__va_next_fp_limit = (AP.__va_next_fp + \
- (__builtin_args_info (1) < 16 ? (16 - __builtin_args_info (1) + 1) / 2 : 0)); \
- AP.__va_next_stack = (__va_greg *) __builtin_next_arg (LASTARG); \
- })
-#else
/* Call __builtin_next_arg even though we aren't using its value, so that
we can verify that LASTARG is correct. */
-#ifdef __GCC_NEW_VARARGS__
+#if defined (__GCC_NEW_VARARGS__) || defined (__arch64__)
#define va_start(AP, LASTARG) \
(__builtin_next_arg (LASTARG), AP = (char *) __builtin_saveregs ())
#else
#define va_start(AP, LASTARG) \
(__builtin_saveregs (), AP = ((char *) __builtin_next_arg (LASTARG)))
#endif
-#endif /* not __sparc_v9__ */
#else
#define va_alist __builtin_va_alist
#define va_dcl int __builtin_va_alist;...
-#ifdef __sparc_v9__
-#define va_start(AP) \
-__extension__ \
- ({ \
- AP.__va_next_o = (__va_greg *) __builtin_saveregs (); \
- AP.__va_next_o_limit = (AP.__va_next_o + \
- (__builtin_args_info (0) < 6 ? 6 - __builtin_args_info (0) : 0)); \
- AP.__va_next_fp = (__va_freg *) AP.__va_next_o_limit; \
- AP.__va_next_fp_limit = (AP.__va_next_fp + \
- (__builtin_args_info (1) < 16 ? (16 - __builtin_args_info (1) + 1) / 2 : 0)); \
- AP.__va_next_stack = (__va_greg *) __builtin_next_arg (__builtin_va_alist) \
- - (__builtin_args_info (0) >= 6 || __builtin_args_info (1) >= 16 ? 1 : 0); \
- })
-#else
-#ifdef __GCC_NEW_VARARGS__
-#define va_start(AP) ((AP) = (char *) __builtin_saveregs ())
+#if defined (__GCC_NEW_VARARGS__) || defined (__arch64__)
+#define va_start(AP) ((AP) = (char *) __builtin_saveregs ())
#else
-#define va_start(AP) \
- (__builtin_saveregs (), (AP) = ((char *) &__builtin_va_alist))
+#define va_start(AP) \
+ (__builtin_saveregs (), (AP) = ((char *) &__builtin_va_alist))
#endif
-#endif /* not __sparc_v9__ */
#endif
@@ -129,51 +87,51 @@ enum __va_type_classes {
in the stack are made to be word-aligned; for an aggregate that is
not word-aligned, we advance the pointer to the first non-reg slot. */
-#ifdef __sparc_v9__
+#ifdef __arch64__
-#define va_arg(pvar,TYPE) \
+typedef unsigned int __ptrint __attribute__ ((__mode__ (__DI__)));
+
+/* ??? TODO: little endian support */
+
+#define va_arg(pvar, TYPE) \
__extension__ \
(*({int __type = __builtin_classify_type (* (TYPE *) 0); \
- void * __result; \
+ char * __result; \
if (__type == __real_type_class) /* float? */ \
{ \
- __va_freg *__r; \
- /* see PASS_IN_REG_P in gcc's sparc.h */ \
- if (pvar.__va_next_fp < pvar.__va_next_fp_limit \
- && ((__r = (__va_freg *) (((__va_greg) pvar.__va_next_fp + sizeof (TYPE) - 1) & ~(__va_greg) (sizeof (TYPE) - 1))) \
- < pvar.__va_next_fp_limit)) \
- { \
- pvar.__va_next_fp = __r + (sizeof (TYPE) + 7) / 8; \
- } \
- else \
- { \
- __r = (__va_freg *) pvar.__va_next_stack; \
- pvar.__va_next_stack += (sizeof (TYPE) + 7) / 8; \
- } \
- __result = __r; \
+ if (__alignof__ (TYPE) == 16) \
+ (pvar) = (void *) (((__ptrint) (pvar) + 15) & -16); \
+ __result = (pvar); \
+ (pvar) = (char *) (pvar) + sizeof (TYPE); \
} \
else if (__type < __record_type_class) /* integer? */ \
{ \
- __va_greg *__r; \
- if (pvar.__va_next_o < pvar.__va_next_o_limit) \
- __r = pvar.__va_next_o++; \
- else \
- __r = pvar.__va_next_stack++; \
- /* adjust for 4 byte ints */ \
- __result = (char *) __r + 8 - sizeof (TYPE); \
+ (pvar) = (char *) (pvar) + 8; \
+ __result = (char *) (pvar) - sizeof (TYPE); \
} \
else /* aggregate object */ \
{ \
- void **__r; \
- if (pvar.__va_next_o < pvar.__va_next_o_limit) \
- __r = (void **) pvar.__va_next_o++; \
+ if (sizeof (TYPE) <= 8) \
+ { \
+ __result = (pvar); \
+ (pvar) = (char *) (pvar) + 8; \
+ } \
+ else if (sizeof (TYPE) <= 16) \
+ { \
+ if (__alignof__ (TYPE) == 16) \
+ (pvar) = (void *) (((__ptrint) (pvar) + 15) & -16); \
+ __result = (pvar); \
+ (pvar) = (char *) (pvar) + 16; \
+ } \
else \
- __r = (void **) pvar.__va_next_stack++; \
- __result = *__r; \
+ { \
+ __result = * (void **) (pvar); \
+ (pvar) = (char *) (pvar) + 8; \
+ } \
} \
(TYPE *) __result;}))
-#else /* not __sparc_v9__ */
+#else /* not __arch64__ */
#define __va_rounded_size(TYPE) \
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
@@ -198,6 +156,10 @@ __extension__ \
(TYPE *) (void *) __u.__d; }) \
: ((pvar) = (char *)(pvar) + __va_rounded_size (TYPE), \
((TYPE *) (void *) ((char *)(pvar) - __va_rounded_size (TYPE)))));}))
-#endif /* not __sparc_v9__ */
+
+#endif /* not __arch64__ */
+
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
diff --git a/gnu/usr.bin/gcc/ginclude/va-spur.h b/gnu/usr.bin/gcc/ginclude/va-spur.h
index 68cbc5ced64..7457ceb9fcd 100644
--- a/gnu/usr.bin/gcc/ginclude/va-spur.h
+++ b/gnu/usr.bin/gcc/ginclude/va-spur.h
@@ -59,3 +59,6 @@ __extension__ \
(pvar).__pnt += (sizeof(type) + 3) & ~3; \
} \
__va_result; }))
+
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
diff --git a/gnu/usr.bin/gcc/ginclude/varargs.h b/gnu/usr.bin/gcc/ginclude/varargs.h
index 691759e99ac..410d06aac69 100644
--- a/gnu/usr.bin/gcc/ginclude/varargs.h
+++ b/gnu/usr.bin/gcc/ginclude/varargs.h
@@ -4,40 +4,58 @@
#define _VARARGS_H
#ifdef __sparc__
-#include <va-sparc.h>
+#include "va-sparc.h"
#else
#ifdef __spur__
-#include <va-spur.h>
+#include "va-spur.h"
#else
#ifdef __mips__
-#include <va-mips.h>
+#include "va-mips.h"
#else
#ifdef __i860__
-#include <va-i860.h>
+#include "va-i860.h"
#else
#ifdef __pyr__
-#include <va-pyr.h>
+#include "va-pyr.h"
#else
#ifdef __clipper__
-#include <va-clipper.h>
+#include "va-clipper.h"
#else
#ifdef __m88k__
-#include <va-m88k.h>
+#include "va-m88k.h"
#else
#if defined(__hppa__) || defined(hp800)
-#include <va-pa.h>
+#include "va-pa.h"
#else
#ifdef __i960__
-#include <va-i960.h>
+#include "va-i960.h"
#else
#ifdef __alpha__
-#include <va-alpha.h>
+#include "va-alpha.h"
#else
-#if defined (__H8300__) || defined (__H8300H__)
-#include <va-h8300.h>
+#if defined (__H8300__) || defined (__H8300H__) || defined (__H8300S__)
+#include "va-h8300.h"
#else
-#if defined (__PPC__) && defined (_CALL_SYSV)
-#include <va-ppc.h>
+#if defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32))
+#include "va-ppc.h"
+#else
+#ifdef __arc__
+#include "va-arc.h"
+#else
+#ifdef __M32R__
+#include "va-m32r.h"
+#else
+#ifdef __sh__
+#include "va-sh.h"
+#else
+#ifdef __mn10300__
+#include "va-mn10300.h"
+#else
+#ifdef __mn10200__
+#include "va-mn10200.h"
+#else
+#ifdef __v850__
+#include "va-v850.h"
#else
#ifdef __NeXT__
@@ -97,7 +115,7 @@ typedef void *__gnuc_va_list;
(((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
#endif
-#if defined (__arm__) || defined (__i386__) || defined (__i860__) || defined (__ns32000__) || defined (__vax__)
+#if (defined (__arm__) && ! defined (__ARMEB__)) || defined (__i386__) || defined (__i860__) || defined (__ns32000__) || defined (__vax__)
/* This is for little-endian machines; small args are padded upward. */
#define va_arg(AP, TYPE) \
(AP = (__gnuc_va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \
@@ -111,6 +129,15 @@ typedef void *__gnuc_va_list;
? sizeof (TYPE) : __va_rounded_size (TYPE))))))
#endif /* big-endian */
+/* Copy __gnuc_va_list into another variable of this type. */
+#define __va_copy(dest, src) (dest) = (src)
+
+#endif /* not v850 */
+#endif /* not mn10200 */
+#endif /* not mn10300 */
+#endif /* not sh */
+#endif /* not m32r */
+#endif /* not arc */
#endif /* not powerpc with V.4 calling sequence */
#endif /* not h8300 */
#endif /* not alpha */
@@ -131,7 +158,7 @@ typedef void *__gnuc_va_list;
#undef _VA_LIST
#endif
-#ifdef __svr4__
+#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST))
/* SVR4.2 uses _VA_LIST for an internal alias for va_list,
so we must avoid testing it and setting it here.
SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
@@ -144,9 +171,12 @@ typedef void *__gnuc_va_list;
#endif
#endif /* __i860__ */
typedef __gnuc_va_list va_list;
+#ifdef _SCO_DS
+#define __VA_LIST
+#endif
#endif /* _VA_LIST_ */
-#else /* not __svr4__ */
+#else /* not __svr4__ || _SCO_DS */
/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
But on BSD NET2 we must not test or define or undef it.
diff --git a/gnu/usr.bin/gcc/global.c b/gnu/usr.bin/gcc/global.c
index e9941e6d30f..3ab4d708af6 100644
--- a/gnu/usr.bin/gcc/global.c
+++ b/gnu/usr.bin/gcc/global.c
@@ -1,5 +1,5 @@
/* Allocate registers for pseudo-registers that span basic blocks.
- Copyright (C) 1987, 1988, 1991, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 94, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,8 +19,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "flags.h"
#include "basic-block.h"
@@ -75,7 +75,7 @@ static int max_allocno;
/* Indexed by (pseudo) reg number, gives the allocno, or -1
for pseudo registers already allocated by local_allocate. */
-static int *reg_allocno;
+int *reg_allocno;
/* Indexed by allocno, gives the reg number. */
@@ -251,7 +251,7 @@ static int n_regs_set;
static HARD_REG_SET eliminable_regset;
-static int allocno_compare PROTO((int *, int *));
+static int allocno_compare PROTO((const GENERIC_PTR, const GENERIC_PTR));
static void global_conflicts PROTO((void));
static void expand_preferences PROTO((void));
static void prune_preferences PROTO((void));
@@ -277,6 +277,7 @@ int
global_alloc (file)
FILE *file;
{
+ int retval;
#ifdef ELIMINABLE_REGS
static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
@@ -385,17 +386,17 @@ global_alloc (file)
/* Note that reg_live_length[i] < 0 indicates a "constant" reg
that we are supposed to refrain from putting in a hard reg.
-2 means do make an allocno but don't allocate it. */
- if (reg_n_refs[i] != 0 && reg_renumber[i] < 0 && reg_live_length[i] != -1
+ if (REG_N_REFS (i) != 0 && reg_renumber[i] < 0 && REG_LIVE_LENGTH (i) != -1
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
&& (! current_function_has_nonlocal_label
- || reg_n_calls_crossed[i] == 0))
+ || REG_N_CALLS_CROSSED (i) == 0))
{
if (reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
reg_allocno[i] = reg_allocno[reg_may_share[i]];
else
reg_allocno[i] = max_allocno++;
- if (reg_live_length[i] == 0)
+ if (REG_LIVE_LENGTH (i) == 0)
abort ();
}
else
@@ -417,10 +418,10 @@ global_alloc (file)
int allocno = reg_allocno[i];
allocno_reg[allocno] = i;
allocno_size[allocno] = PSEUDO_REGNO_SIZE (i);
- allocno_calls_crossed[allocno] += reg_n_calls_crossed[i];
- allocno_n_refs[allocno] += reg_n_refs[i];
- if (allocno_live_length[allocno] < reg_live_length[i])
- allocno_live_length[allocno] = reg_live_length[i];
+ allocno_calls_crossed[allocno] += REG_N_CALLS_CROSSED (i);
+ allocno_n_refs[allocno] += REG_N_REFS (i);
+ if (allocno_live_length[allocno] < REG_LIVE_LENGTH (i))
+ allocno_live_length[allocno] = REG_LIVE_LENGTH (i);
}
/* Calculate amount of usage of each hard reg by pseudos
@@ -437,8 +438,8 @@ global_alloc (file)
for (j = regno; j < endregno; j++)
{
- local_reg_n_refs[j] += reg_n_refs[i];
- local_reg_live_length[j] += reg_live_length[i];
+ local_reg_n_refs[j] += REG_N_REFS (i);
+ local_reg_live_length[j] += REG_LIVE_LENGTH (i);
}
}
@@ -486,8 +487,11 @@ global_alloc (file)
allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
- conflicts = (INT_TYPE *) alloca (max_allocno * allocno_row_words
- * sizeof (INT_TYPE));
+ /* We used to use alloca here, but the size of what it would try to
+ allocate would occasionally cause it to exceed the stack limit and
+ cause unpredictable core dumps. Some examples were > 2Mb in size. */
+ conflicts = (INT_TYPE *) xmalloc (max_allocno * allocno_row_words
+ * sizeof (INT_TYPE));
bzero ((char *) conflicts,
max_allocno * allocno_row_words * sizeof (INT_TYPE));
@@ -554,7 +558,7 @@ global_alloc (file)
except for parameters marked with reg_live_length[regno] == -2. */
for (i = 0; i < max_allocno; i++)
- if (reg_live_length[allocno_reg[allocno_order[i]]] >= 0)
+ if (REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0)
{
/* If we have more than one register class,
first try allocating in the class that is cheapest
@@ -577,34 +581,39 @@ global_alloc (file)
for the sake of debugging information. */
if (n_basic_blocks > 0)
#endif
- return reload (get_insns (), 1, file);
+ retval = reload (get_insns (), 1, file);
+
+ free (conflicts);
+ return retval;
}
/* Sort predicate for ordering the allocnos.
Returns -1 (1) if *v1 should be allocated before (after) *v2. */
static int
-allocno_compare (v1, v2)
- int *v1, *v2;
+allocno_compare (v1p, v2p)
+ const GENERIC_PTR v1p;
+ const GENERIC_PTR v2p;
{
+ int v1 = *(int *)v1p, v2 = *(int *)v2p;
/* Note that the quotient will never be bigger than
the value of floor_log2 times the maximum number of
times a register can occur in one insn (surely less than 100).
Multiplying this by 10000 can't overflow. */
register int pri1
- = (((double) (floor_log2 (allocno_n_refs[*v1]) * allocno_n_refs[*v1])
- / allocno_live_length[*v1])
- * 10000 * allocno_size[*v1]);
+ = (((double) (floor_log2 (allocno_n_refs[v1]) * allocno_n_refs[v1])
+ / allocno_live_length[v1])
+ * 10000 * allocno_size[v1]);
register int pri2
- = (((double) (floor_log2 (allocno_n_refs[*v2]) * allocno_n_refs[*v2])
- / allocno_live_length[*v2])
- * 10000 * allocno_size[*v2]);
+ = (((double) (floor_log2 (allocno_n_refs[v2]) * allocno_n_refs[v2])
+ / allocno_live_length[v2])
+ * 10000 * allocno_size[v2]);
if (pri2 - pri1)
return pri2 - pri1;
/* If regs are equally good, sort by allocno,
so that the results of qsort leave nothing to chance. */
- return *v1 - *v2;
+ return v1 - v2;
}
/* Scan the rtl code and record all conflicts and register preferences in the
@@ -640,36 +649,22 @@ global_conflicts ()
are explicitly marked in basic_block_live_at_start. */
{
- register int offset;
- REGSET_ELT_TYPE bit;
register regset old = basic_block_live_at_start[b];
int ax = 0;
-#ifdef HARD_REG_SET
- hard_regs_live = old[0];
-#else
- COPY_HARD_REG_SET (hard_regs_live, old);
-#endif
- for (offset = 0, i = 0; offset < regset_size; offset++)
- if (old[offset] == 0)
- i += REGSET_ELT_BITS;
- else
- for (bit = 1; bit; bit <<= 1, i++)
- {
- if (i >= max_regno)
- break;
- if (old[offset] & bit)
- {
- register int a = reg_allocno[i];
- if (a >= 0)
- {
- SET_ALLOCNO_LIVE (a);
- block_start_allocnos[ax++] = a;
- }
- else if ((a = reg_renumber[i]) >= 0)
- mark_reg_live_nc (a, PSEUDO_REGNO_MODE (i));
- }
- }
+ REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
+ EXECUTE_IF_SET_IN_REG_SET (old, FIRST_PSEUDO_REGISTER, i,
+ {
+ register int a = reg_allocno[i];
+ if (a >= 0)
+ {
+ SET_ALLOCNO_LIVE (a);
+ block_start_allocnos[ax++] = a;
+ }
+ else if ((a = reg_renumber[i]) >= 0)
+ mark_reg_live_nc
+ (a, PSEUDO_REGNO_MODE (i));
+ });
/* Record that each allocno now live conflicts with each other
allocno now live, and with each hard reg now live. */
@@ -869,7 +864,8 @@ prune_preferences ()
we want to give the lower-priority allocno the first chance for
these registers). */
for (j = i + 1; j < max_allocno; j++)
- if (CONFLICTP (allocno, allocno_order[j]))
+ if (CONFLICTP (allocno, allocno_order[j])
+ || CONFLICTP (allocno_order[j], allocno))
{
COPY_HARD_REG_SET (temp,
hard_reg_full_preferences[allocno_order[j]]);
@@ -937,7 +933,7 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
IOR_HARD_REG_SET (used1, hard_reg_conflicts[allocno]);
#ifdef CLASS_CANNOT_CHANGE_SIZE
- if (reg_changes_size[allocno_reg[allocno]])
+ if (REG_CHANGES_SIZE (allocno_reg[allocno]))
IOR_HARD_REG_SET (used1,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
#endif
@@ -1085,7 +1081,14 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
&& CALLER_SAVE_PROFITABLE (allocno_n_refs[allocno],
allocno_calls_crossed[allocno]))
{
- find_reg (allocno, losers, alt_regs_p, 1, retrying);
+ HARD_REG_SET new_losers;
+ if (! losers)
+ CLEAR_HARD_REG_SET (new_losers);
+ else
+ COPY_HARD_REG_SET (new_losers, losers);
+
+ IOR_HARD_REG_SET(new_losers, losing_caller_save_reg_set);
+ find_reg (allocno, new_losers, alt_regs_p, 1, retrying);
if (reg_renumber[allocno_reg[allocno]] >= 0)
{
caller_save_needed = 1;
@@ -1117,7 +1120,7 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
&& ! TEST_HARD_REG_BIT (used2, regno)
&& HARD_REGNO_MODE_OK (regno, mode)
#ifdef CLASS_CANNOT_CHANGE_SIZE
- && ! (reg_changes_size[allocno_reg[allocno]]
+ && ! (REG_CHANGES_SIZE (allocno_reg[allocno])
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
regno)))
@@ -1630,13 +1633,10 @@ mark_elimination (from, to)
int i;
for (i = 0; i < n_basic_blocks; i++)
- if ((basic_block_live_at_start[i][from / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (from % REGSET_ELT_BITS))) != 0)
+ if (REGNO_REG_SET_P (basic_block_live_at_start[i], from))
{
- basic_block_live_at_start[i][from / REGSET_ELT_BITS]
- &= ~ ((REGSET_ELT_TYPE) 1 << (from % REGSET_ELT_BITS));
- basic_block_live_at_start[i][to / REGSET_ELT_BITS]
- |= ((REGSET_ELT_TYPE) 1 << (to % REGSET_ELT_BITS));
+ CLEAR_REGNO_REG_SET (basic_block_live_at_start[i], from);
+ SET_REGNO_REG_SET (basic_block_live_at_start[i], to);
}
}
diff --git a/gnu/usr.bin/gcc/gmon.c b/gnu/usr.bin/gcc/gmon.c
index bda7d96e745..6cebb382b69 100644
--- a/gnu/usr.bin/gcc/gmon.c
+++ b/gnu/usr.bin/gcc/gmon.c
@@ -84,10 +84,10 @@ monstartup(lowpc, highpc)
* so the rest of the scaling (here and in gprof) stays in ints.
*/
lowpc = (char *)
- ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
+ ROUNDDOWN((unsigned) lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_lowpc = lowpc;
highpc = (char *)
- ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
+ ROUNDUP((unsigned) highpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_highpc = highpc;
s_textsize = highpc - lowpc;
monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
@@ -220,12 +220,12 @@ mcount()
* 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) {
+ frompcindex = (unsigned short *) ((long) frompcindex - (long) s_lowpc);
+ if ((unsigned long) frompcindex > s_textsize) {
goto done;
}
frompcindex =
- &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
+ &froms[((long) frompcindex) / (HASHFRACTION * sizeof(*froms))];
toindex = *frompcindex;
if (toindex == 0) {
/*
@@ -308,11 +308,10 @@ overflow:
goto out;
}
-/*
- * Control profiling
- * profiling is what mcount checks to see if
- * all the data structures are ready.
- */
+/* Control profiling
+ profiling is what mcount checks to see if
+ all the data structures are ready. */
+
moncontrol(mode)
int mode;
{
@@ -323,7 +322,7 @@ moncontrol(mode)
profiling = 0;
} else {
/* stop */
- profil((char *)0, 0, 0, 0);
+ profil((char *) 0, 0, 0, 0);
profiling = 3;
}
}
diff --git a/gnu/usr.bin/gcc/gsyms.h b/gnu/usr.bin/gcc/gsyms.h
index a2054bb135e..03bde938604 100644
--- a/gnu/usr.bin/gcc/gsyms.h
+++ b/gnu/usr.bin/gcc/gsyms.h
@@ -54,6 +54,9 @@ enum sdb_type
T_USHORT = 13,
T_UINT = 14,
T_ULONG = 15
+#ifdef EXTENDED_SDB_BASIC_TYPES
+ , T_LNGDBL = 16
+#endif
};
enum sdb_type_class
@@ -66,11 +69,18 @@ enum sdb_type_class
enum sdb_masks
{
+#ifdef EXTENDED_SDB_BASIC_TYPES
+ N_BTMASK = 0x1f,
+ N_TMASK = 0x60,
+ N_TMASK1 = 0x300,
+ N_TMASK2 = 0x360,
+ N_BTSHFT = 5,
+#else
N_BTMASK = 017,
N_TMASK = 060,
N_TMASK1 = 0300,
N_TMASK2 = 0360,
N_BTSHFT = 4,
+#endif
N_TSHIFT = 2
};
-
diff --git a/gnu/usr.bin/gcc/halfpic.c b/gnu/usr.bin/gcc/halfpic.c
index d4ae36eea4d..a853a12fbf4 100644
--- a/gnu/usr.bin/gcc/halfpic.c
+++ b/gnu/usr.bin/gcc/halfpic.c
@@ -1,5 +1,5 @@
/* OSF/rose half-pic support functions.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -32,9 +32,9 @@ Boston, MA 02111-1307, USA. */
#ifdef HALF_PIC_INIT
+#include <stdio.h>
#include "tree.h"
#include "rtl.h"
-#include <stdio.h>
#include "obstack.h"
#define obstack_chunk_alloc xmalloc
@@ -135,7 +135,7 @@ half_pic_hash (name, len, create_p)
/* name not in hash table. */
if (!create_p)
- return (struct all_refs *)0;
+ return (struct all_refs *) 0;
ptr = (struct all_refs *) obstack_alloc (&half_pic_obstack, sizeof (struct all_refs));
*ptr = zero_all_refs;
@@ -144,7 +144,7 @@ half_pic_hash (name, len, create_p)
ptr->real_len = len;
/* Update circular links. */
- if (first == (struct all_refs *)0)
+ if (first == (struct all_refs *) 0)
ptr->hash_next = ptr;
else
@@ -342,7 +342,7 @@ half_pic_address_p (addr)
return FALSE;
ptr = half_pic_hash (name, len, FALSE);
- if (ptr == (struct all_refs *)0)
+ if (ptr == (struct all_refs *) 0)
return FALSE;
if (ptr->external_p)
@@ -376,7 +376,7 @@ half_pic_ptr (operand)
name = XSTR (operand, 0);
len = strlen (name);
p = half_pic_hash (name, len, FALSE);
- if (p == (struct all_refs *)0 || !p->external_p)
+ if (p == (struct all_refs *) 0 || !p->external_p)
return operand;
if (!p->pointer_p)
diff --git a/gnu/usr.bin/gcc/halfpic.h b/gnu/usr.bin/gcc/halfpic.h
index 10f6972bb8f..f9c1a695517 100644
--- a/gnu/usr.bin/gcc/halfpic.h
+++ b/gnu/usr.bin/gcc/halfpic.h
@@ -1,5 +1,5 @@
/* OSF/rose half-pic support definitions.
- Copyright (C) 1992 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,22 +20,7 @@ Boston, MA 02111-1307, USA. */
#ifndef NO_HALF_PIC
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
-#if !defined(STDIO_PROTO) && !defined(NO_STDIO_H)
-#ifndef BUFSIZ
-#include <stdio.h>
-#endif
-
-#define STDIO_PROTO(ARGS) PROTO(ARGS)
-#endif
+#include "gansidecl.h"
#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
union tree_node; /* forward reference */
@@ -62,9 +47,8 @@ extern void half_pic_external PROTO((char *)); /* declare object external */
extern void half_pic_init PROTO((void)); /* half_pic initialization */
extern int half_pic_address_p PROTO((struct rtx_def *)); /* true if an address is half-pic */
extern struct rtx_def *half_pic_ptr PROTO((struct rtx_def *)); /* return RTX for half-pic pointer */
-#ifdef STDIO_PROTO
-extern void half_pic_finish STDIO_PROTO((FILE *)); /* half_pic termination */
-#endif
+/* Can't use prototype since FILE isn't defined yet. */
+extern void half_pic_finish (/* FILE * */); /* half_pic termination */
/* Macros to provide access to the half-pic stuff (so they can easily
be stubbed out. */
diff --git a/gnu/usr.bin/gcc/hard-reg-set.h b/gnu/usr.bin/gcc/hard-reg-set.h
index 084785e0e51..5064dbcc041 100644
--- a/gnu/usr.bin/gcc/hard-reg-set.h
+++ b/gnu/usr.bin/gcc/hard-reg-set.h
@@ -123,6 +123,199 @@ typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS];
((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \
& (HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)))
+#if FIRST_PSEUDO_REGISTER <= 2*HOST_BITS_PER_WIDE_INT
+#define CLEAR_HARD_REG_SET(TO) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO); \
+ scan_tp_[0] = 0; \
+ scan_tp_[1] = 0; } while (0)
+
+#define SET_HARD_REG_SET(TO) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO); \
+ scan_tp_[0] = -1; \
+ scan_tp_[1] = -1; } while (0)
+
+#define COPY_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] = scan_fp_[0]; \
+ scan_tp_[1] = scan_fp_[1]; } while (0)
+
+#define COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] = ~ scan_fp_[0]; \
+ scan_tp_[1] = ~ scan_fp_[1]; } while (0)
+
+#define AND_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] &= scan_fp_[0]; \
+ scan_tp_[1] &= scan_fp_[1]; } while (0)
+
+#define AND_COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] &= ~ scan_fp_[0]; \
+ scan_tp_[1] &= ~ scan_fp_[1]; } while (0)
+
+#define IOR_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] |= scan_fp_[0]; \
+ scan_tp_[1] |= scan_fp_[1]; } while (0)
+
+#define IOR_COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] |= ~ scan_fp_[0]; \
+ scan_tp_[1] |= ~ scan_fp_[1]; } while (0)
+
+#define GO_IF_HARD_REG_SUBSET(X,Y,TO) \
+do { register HARD_REG_ELT_TYPE *scan_xp_ = (X), *scan_yp_ = (Y); \
+ if ((0 == (scan_xp_[0] & ~ scan_yp_[0])) \
+ && (0 == (scan_xp_[1] & ~ scan_yp_[1]))) \
+ goto TO; } while (0)
+
+#define GO_IF_HARD_REG_EQUAL(X,Y,TO) \
+do { register HARD_REG_ELT_TYPE *scan_xp_ = (X), *scan_yp_ = (Y); \
+ if ((scan_xp_[0] == scan_yp_[0]) \
+ && (scan_xp_[1] == scan_yp_[1])) \
+ goto TO; } while (0)
+
+#else
+#if FIRST_PSEUDO_REGISTER <= 3*HOST_BITS_PER_WIDE_INT
+#define CLEAR_HARD_REG_SET(TO) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO); \
+ scan_tp_[0] = 0; \
+ scan_tp_[1] = 0; \
+ scan_tp_[2] = 0; } while (0)
+
+#define SET_HARD_REG_SET(TO) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO); \
+ scan_tp_[0] = -1; \
+ scan_tp_[1] = -1; \
+ scan_tp_[2] = -1; } while (0)
+
+#define COPY_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] = scan_fp_[0]; \
+ scan_tp_[1] = scan_fp_[1]; \
+ scan_tp_[2] = scan_fp_[2]; } while (0)
+
+#define COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] = ~ scan_fp_[0]; \
+ scan_tp_[1] = ~ scan_fp_[1]; \
+ scan_tp_[2] = ~ scan_fp_[2]; } while (0)
+
+#define AND_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] &= scan_fp_[0]; \
+ scan_tp_[1] &= scan_fp_[1]; \
+ scan_tp_[2] &= scan_fp_[2]; } while (0)
+
+#define AND_COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] &= ~ scan_fp_[0]; \
+ scan_tp_[1] &= ~ scan_fp_[1]; \
+ scan_tp_[2] &= ~ scan_fp_[2]; } while (0)
+
+#define IOR_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] |= scan_fp_[0]; \
+ scan_tp_[1] |= scan_fp_[1]; \
+ scan_tp_[2] |= scan_fp_[2]; } while (0)
+
+#define IOR_COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] |= ~ scan_fp_[0]; \
+ scan_tp_[1] |= ~ scan_fp_[1]; \
+ scan_tp_[2] |= ~ scan_fp_[2]; } while (0)
+
+#define GO_IF_HARD_REG_SUBSET(X,Y,TO) \
+do { register HARD_REG_ELT_TYPE *scan_xp_ = (X), *scan_yp_ = (Y); \
+ if ((0 == (scan_xp_[0] & ~ scan_yp_[0])) \
+ && (0 == (scan_xp_[1] & ~ scan_yp_[1])) \
+ && (0 == (scan_xp_[2] & ~ scan_yp_[2]))) \
+ goto TO; } while (0)
+
+#define GO_IF_HARD_REG_EQUAL(X,Y,TO) \
+do { register HARD_REG_ELT_TYPE *scan_xp_ = (X), *scan_yp_ = (Y); \
+ if ((scan_xp_[0] == scan_yp_[0]) \
+ && (scan_xp_[1] == scan_yp_[1]) \
+ && (scan_xp_[2] == scan_yp_[2])) \
+ goto TO; } while (0)
+
+#else
+#if FIRST_PSEUDO_REGISTER <= 4*HOST_BITS_PER_WIDE_INT
+#define CLEAR_HARD_REG_SET(TO) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO); \
+ scan_tp_[0] = 0; \
+ scan_tp_[1] = 0; \
+ scan_tp_[2] = 0; \
+ scan_tp_[3] = 0; } while (0)
+
+#define SET_HARD_REG_SET(TO) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO); \
+ scan_tp_[0] = -1; \
+ scan_tp_[1] = -1; \
+ scan_tp_[2] = -1; \
+ scan_tp_[3] = -1; } while (0)
+
+#define COPY_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] = scan_fp_[0]; \
+ scan_tp_[1] = scan_fp_[1]; \
+ scan_tp_[2] = scan_fp_[2]; \
+ scan_tp_[3] = scan_fp_[3]; } while (0)
+
+#define COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] = ~ scan_fp_[0]; \
+ scan_tp_[1] = ~ scan_fp_[1]; \
+ scan_tp_[2] = ~ scan_fp_[2]; \
+ scan_tp_[3] = ~ scan_fp_[3]; } while (0)
+
+#define AND_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] &= scan_fp_[0]; \
+ scan_tp_[1] &= scan_fp_[1]; \
+ scan_tp_[2] &= scan_fp_[2]; \
+ scan_tp_[3] &= scan_fp_[3]; } while (0)
+
+#define AND_COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] &= ~ scan_fp_[0]; \
+ scan_tp_[1] &= ~ scan_fp_[1]; \
+ scan_tp_[2] &= ~ scan_fp_[2]; \
+ scan_tp_[3] &= ~ scan_fp_[3]; } while (0)
+
+#define IOR_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] |= scan_fp_[0]; \
+ scan_tp_[1] |= scan_fp_[1]; \
+ scan_tp_[2] |= scan_fp_[2]; \
+ scan_tp_[3] |= scan_fp_[3]; } while (0)
+
+#define IOR_COMPL_HARD_REG_SET(TO, FROM) \
+do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO), *scan_fp_ = (FROM); \
+ scan_tp_[0] |= ~ scan_fp_[0]; \
+ scan_tp_[1] |= ~ scan_fp_[1]; \
+ scan_tp_[2] |= ~ scan_fp_[2]; \
+ scan_tp_[3] |= ~ scan_fp_[3]; } while (0)
+
+#define GO_IF_HARD_REG_SUBSET(X,Y,TO) \
+do { register HARD_REG_ELT_TYPE *scan_xp_ = (X), *scan_yp_ = (Y); \
+ if ((0 == (scan_xp_[0] & ~ scan_yp_[0])) \
+ && (0 == (scan_xp_[1] & ~ scan_yp_[1])) \
+ && (0 == (scan_xp_[2] & ~ scan_yp_[2])) \
+ && (0 == (scan_xp_[3] & ~ scan_yp_[3]))) \
+ goto TO; } while (0)
+
+#define GO_IF_HARD_REG_EQUAL(X,Y,TO) \
+do { register HARD_REG_ELT_TYPE *scan_xp_ = (X), *scan_yp_ = (Y); \
+ if ((scan_xp_[0] == scan_yp_[0]) \
+ && (scan_xp_[1] == scan_yp_[1]) \
+ && (scan_xp_[2] == scan_yp_[2]) \
+ && (scan_xp_[3] == scan_yp_[3])) \
+ goto TO; } while (0)
+
+#else /* FIRST_PSEUDO_REGISTER > 3*HOST_BITS_PER_WIDE_INT */
+
#define CLEAR_HARD_REG_SET(TO) \
do { register HARD_REG_ELT_TYPE *scan_tp_ = (TO); \
register int i; \
@@ -186,6 +379,9 @@ do { register HARD_REG_ELT_TYPE *scan_xp_ = (X), *scan_yp_ = (Y); \
if (i == HARD_REG_SET_LONGS) goto TO; } while (0)
#endif
+#endif
+#endif
+#endif
/* Define some standard sets of registers. */
@@ -211,6 +407,9 @@ extern char call_used_regs[FIRST_PSEUDO_REGISTER];
extern HARD_REG_SET call_used_reg_set;
+/* Registers that we don't want to caller save. */
+extern HARD_REG_SET losing_caller_save_reg_set;
+
/* Indexed by hard register number, contains 1 for registers that are
fixed use -- i.e. in fixed_regs -- or a function value return register
or STRUCT_VALUE_REGNUM or STATIC_CHAIN_REGNUM. These are the
diff --git a/gnu/usr.bin/gcc/input.h b/gnu/usr.bin/gcc/input.h
index 7c71c24d46b..7bcde83f975 100644
--- a/gnu/usr.bin/gcc/input.h
+++ b/gnu/usr.bin/gcc/input.h
@@ -1,7 +1,6 @@
/* Declarations for variables relating to reading the source file.
Used by parsers, lexical analyzers, and error message routines.
-
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -37,6 +36,7 @@ struct file_stack
char *name;
struct file_stack *next;
int line;
+ int indent_level;
};
/* Stack of currently pending input files.
diff --git a/gnu/usr.bin/gcc/integrate.c b/gnu/usr.bin/gcc/integrate.c
index fcd242c9823..0400085f61f 100644
--- a/gnu/usr.bin/gcc/integrate.c
+++ b/gnu/usr.bin/gcc/integrate.c
@@ -1,5 +1,5 @@
/* Procedure integration for GNU CC.
- Copyright (C) 1988, 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 91, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -20,18 +20,20 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
-
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "tree.h"
+#include "regs.h"
#include "flags.h"
#include "insn-config.h"
#include "insn-flags.h"
#include "expr.h"
#include "output.h"
+#include "recog.h"
#include "integrate.h"
#include "real.h"
+#include "except.h"
#include "function.h"
#include "bytecode.h"
@@ -66,6 +68,7 @@ static void note_modified_parmregs PROTO((rtx, rtx));
static rtx copy_for_inline PROTO((rtx));
static void integrate_parm_decls PROTO((tree, struct inline_remap *, rtvec));
static void integrate_decl_tree PROTO((tree, int, struct inline_remap *));
+static void save_constants_in_decl_trees PROTO ((tree));
static void subst_constants PROTO((rtx *, rtx, struct inline_remap *));
static void restore_constants PROTO((rtx *));
static void set_block_origin_self PROTO((tree));
@@ -88,6 +91,7 @@ function_cannot_inline_p (fndecl)
int max_insns = INTEGRATE_THRESHOLD (fndecl);
register int ninsns = 0;
register tree parms;
+ rtx result;
/* No inlines with varargs. `grokdeclarator' gives a warning
message about that if `inline' is specified. This code
@@ -107,14 +111,6 @@ function_cannot_inline_p (fndecl)
return "function too large to be inline";
#if 0
- /* Large stacks are OK now that inlined functions can share them. */
- /* Don't inline functions with large stack usage,
- since they can make other recursive functions burn up stack. */
- if (!DECL_INLINE (fndecl) && get_frame_size () > 100)
- return "function stack frame for inlining";
-#endif
-
-#if 0
/* Don't inline functions which do not specify a function prototype and
have BLKmode argument or take the address of a parameter. */
for (parms = DECL_ARGUMENTS (fndecl); parms; parms = TREE_CHAIN (parms))
@@ -152,12 +148,11 @@ function_cannot_inline_p (fndecl)
if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns)
{
- for (ninsns = 0, insn = get_first_nonparm_insn (); insn && ninsns < max_insns;
+ for (ninsns = 0, insn = get_first_nonparm_insn ();
+ insn && ninsns < max_insns;
insn = NEXT_INSN (insn))
- {
- if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
- ninsns++;
- }
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ ninsns++;
if (ninsns >= max_insns)
return "function too large to be inline";
@@ -177,6 +172,24 @@ function_cannot_inline_p (fndecl)
if (current_function_has_nonlocal_goto)
return "function with nonlocal goto cannot be inline";
+ /* This is a hack, until the inliner is taught about eh regions at
+ the start of the function. */
+ for (insn = get_insns ();
+ insn
+ && ! (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG);
+ insn = NEXT_INSN (insn))
+ {
+ if (insn && GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+ return "function with complex parameters cannot be inline";
+ }
+
+ /* We can't inline functions that return a PARALLEL rtx. */
+ result = DECL_RTL (DECL_RESULT (fndecl));
+ if (result && GET_CODE (result) == PARALLEL)
+ return "inline functions not supported for this return value type";
+
return 0;
}
@@ -205,7 +218,8 @@ static rtx *insn_map;
static tree *parmdecl_map;
/* Keep track of first pseudo-register beyond those that are parms. */
-static int max_parm_reg;
+extern int max_parm_reg;
+extern rtx *parm_reg_stack_loc;
/* When an insn is being copied by copy_for_inline,
this is nonzero if we have copied an ASM_OPERANDS.
@@ -262,6 +276,13 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
{
rtx p = DECL_RTL (parms);
+ /* If we have (mem (addressof (mem ...))), use the inner MEM since
+ otherwise the copy_rtx call below will not unshare the MEM since
+ it shares ADDRESSOF. */
+ if (GET_CODE (p) == MEM && GET_CODE (XEXP (p, 0)) == ADDRESSOF
+ && GET_CODE (XEXP (XEXP (p, 0), 0)) == MEM)
+ p = XEXP (XEXP (p, 0), 0);
+
if (GET_CODE (p) == MEM && copy)
{
/* Copy the rtl so that modifications of the addresses
@@ -316,10 +337,12 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
the size of the incoming stack area for parameters,
the number of bytes popped on return,
the stack slot list,
+ the labels that are forced to exist,
some flags that are used to restore compiler globals,
the value of current_function_outgoing_args_size,
the original argument vector,
- and the original DECL_INITIAL. */
+ the original DECL_INITIAL,
+ and pointers to the table of pseudo regs, pointer flags, and alignment. */
return gen_inline_header_rtx (NULL_RTX, NULL_RTX, min_labelno, max_labelno,
max_parm_reg, max_reg,
@@ -327,7 +350,10 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
current_function_pops_args,
stack_slot_list, forced_labels, function_flags,
current_function_outgoing_args_size,
- arg_vector, (rtx) DECL_INITIAL (fndecl));
+ arg_vector, (rtx) DECL_INITIAL (fndecl),
+ (rtvec) regno_reg_rtx, regno_pointer_flag,
+ regno_pointer_align,
+ (rtvec) parm_reg_stack_loc);
}
/* Subroutine for `save_for_inline{copying,nocopy}'. Finishes up the
@@ -339,7 +365,7 @@ finish_inline (fndecl, head)
tree fndecl;
rtx head;
{
- NEXT_INSN (head) = get_first_nonparm_insn ();
+ FIRST_FUNCTION_INSN (head) = get_first_nonparm_insn ();
FIRST_PARM_INSN (head) = get_insns ();
DECL_SAVED_INSNS (fndecl) = head;
DECL_FRAME_SIZE (fndecl) = get_frame_size ();
@@ -395,9 +421,11 @@ save_for_inline_copying (fndecl)
int max_reg;
int max_uid;
rtx first_nonparm_insn;
+ char *new, *new1;
+ rtx *new_parm_reg_stack_loc;
/* Make and emit a return-label if we have not already done so.
- Do this before recording the bounds on label numbers. */
+ Do this before recording the bounds on label numbers. */
if (return_label == 0)
{
@@ -417,7 +445,6 @@ save_for_inline_copying (fndecl)
for the parms, prior to elimination of virtual registers.
These values are needed for substituting parms properly. */
- max_parm_reg = max_parm_reg_num ();
parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
head = initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, 1);
@@ -434,6 +461,10 @@ save_for_inline_copying (fndecl)
save_constants (&REG_NOTES (insn));
}
+ /* Also scan all decls, and replace any constant pool references with the
+ actual constant. */
+ save_constants_in_decl_trees (DECL_INITIAL (fndecl));
+
/* Clear out the constant pool so that we can recreate it with the
copied constants below. */
init_const_rtx_hash_table ();
@@ -473,25 +504,38 @@ save_for_inline_copying (fndecl)
Make these new rtx's now, and install them in regno_reg_rtx, so they
will be the official pseudo-reg rtx's for the rest of compilation. */
- reg_map = (rtx *) alloca ((max_reg + 1) * sizeof (rtx));
+ reg_map = (rtx *) savealloc (regno_pointer_flag_length * sizeof (rtx));
len = sizeof (struct rtx_def) + (GET_RTX_LENGTH (REG) - 1) * sizeof (rtunion);
for (i = max_reg - 1; i > LAST_VIRTUAL_REGISTER; i--)
reg_map[i] = (rtx)obstack_copy (function_maybepermanent_obstack,
regno_reg_rtx[i], len);
- bcopy ((char *) (reg_map + LAST_VIRTUAL_REGISTER + 1),
- (char *) (regno_reg_rtx + LAST_VIRTUAL_REGISTER + 1),
- (max_reg - (LAST_VIRTUAL_REGISTER + 1)) * sizeof (rtx));
+ regno_reg_rtx = reg_map;
+
+ /* Put copies of all the virtual register rtx into the new regno_reg_rtx. */
+ regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
+ regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx;
+ regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx;
+ regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx;
/* Likewise each label rtx must have a unique rtx as its copy. */
- label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
- label_map -= min_labelno;
+ /* We used to use alloca here, but the size of what it would try to
+ allocate would occasionally cause it to exceed the stack limit and
+ cause unpredictable core dumps. Some examples were > 2Mb in size. */
+ label_map = (rtx *) xmalloc ((max_labelno) * sizeof (rtx));
for (i = min_labelno; i < max_labelno; i++)
label_map[i] = gen_label_rtx ();
+ /* Likewise for parm_reg_stack_slot. */
+ new_parm_reg_stack_loc = (rtx *) savealloc (max_parm_reg * sizeof (rtx));
+ for (i = 0; i < max_parm_reg; i++)
+ new_parm_reg_stack_loc[i] = copy_for_inline (parm_reg_stack_loc[i]);
+
+ parm_reg_stack_loc = new_parm_reg_stack_loc;
+
/* Record the mapping of old insns to copied insns. */
insn_map = (rtx *) alloca (max_uid * sizeof (rtx));
@@ -560,6 +604,16 @@ save_for_inline_copying (fndecl)
NOTE_SOURCE_FILE (insn) = (char *) copy;
NOTE_SOURCE_FILE (copy) = 0;
}
+ if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
+ || NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END)
+ {
+ /* We have to forward these both to match the new exception
+ region. */
+ NOTE_BLOCK_NUMBER (copy)
+ = CODE_LABEL_NUMBER (label_map[NOTE_BLOCK_NUMBER (copy)]);
+
+ }
+ RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
break;
case INSN:
@@ -568,8 +622,8 @@ save_for_inline_copying (fndecl)
copy = rtx_alloc (GET_CODE (insn));
if (GET_CODE (insn) == CALL_INSN)
- CALL_INSN_FUNCTION_USAGE (copy) =
- copy_for_inline (CALL_INSN_FUNCTION_USAGE (insn));
+ CALL_INSN_FUNCTION_USAGE (copy)
+ = copy_for_inline (CALL_INSN_FUNCTION_USAGE (insn));
PATTERN (copy) = copy_for_inline (PATTERN (insn));
INSN_CODE (copy) = -1;
@@ -609,7 +663,19 @@ save_for_inline_copying (fndecl)
finish_inline (fndecl, head);
+ /* Make new versions of the register tables. */
+ new = (char *) savealloc (regno_pointer_flag_length);
+ bcopy (regno_pointer_flag, new, regno_pointer_flag_length);
+ new1 = (char *) savealloc (regno_pointer_flag_length);
+ bcopy (regno_pointer_align, new1, regno_pointer_flag_length);
+
+ regno_pointer_flag = new;
+ regno_pointer_align = new1;
+
set_new_first_and_last_insn (first_insn, last_insn);
+
+ if (label_map)
+ free (label_map);
}
/* Return a copy of a chain of nodes, chained through the TREE_CHAIN field.
@@ -726,7 +792,6 @@ save_for_inline_nocopy (fndecl)
for the parms, prior to elimination of virtual registers.
These values are needed for substituting parms properly. */
- max_parm_reg = max_parm_reg_num ();
parmdecl_map = (tree *) alloca (max_parm_reg * sizeof (tree));
/* Make and emit a return-label if we have not already done so. */
@@ -780,6 +845,10 @@ save_for_inline_nocopy (fndecl)
}
}
+ /* Also scan all decls, and replace any constant pool references with the
+ actual constant. */
+ save_constants_in_decl_trees (DECL_INITIAL (fndecl));
+
/* We have now allocated all that needs to be allocated permanently
on the rtx obstack. Set our high-water mark, so that we
can free the rest of this when the time comes. */
@@ -793,8 +862,8 @@ save_for_inline_nocopy (fndecl)
pool. Replace each with a CONST that has the mode of the original
constant, contains the constant, and has RTX_INTEGRATED_P set.
Similarly, constant pool addresses not enclosed in a MEM are replaced
- with an ADDRESS rtx which also gives the constant, mode, and has
- RTX_INTEGRATED_P set. */
+ with an ADDRESS and CONST rtx which also gives the constant, its
+ mode, the mode of the address, and has RTX_INTEGRATED_P set. */
static void
save_constants (px)
@@ -833,7 +902,9 @@ save_constants (px)
else if (GET_CODE (x) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x))
{
- *px = gen_rtx (ADDRESS, get_pool_mode (x), get_pool_constant (x));
+ *px = gen_rtx (ADDRESS, GET_MODE (x),
+ gen_rtx (CONST, get_pool_mode (x),
+ get_pool_constant (x)));
save_constants (&XEXP (*px, 0));
RTX_INTEGRATED_P (*px) = 1;
}
@@ -900,6 +971,7 @@ copy_for_inline (orig)
rtx orig;
{
register rtx x = orig;
+ register rtx new;
register int i;
register enum rtx_code code;
register char *format_ptr;
@@ -945,9 +1017,8 @@ copy_for_inline (orig)
/* Get constant pool entry, but access in different mode. */
if (RTX_INTEGRATED_P (x))
{
- rtx new
- = force_const_mem (GET_MODE (SUBREG_REG (x)),
- copy_for_inline (XEXP (SUBREG_REG (x), 0)));
+ new = force_const_mem (GET_MODE (SUBREG_REG (x)),
+ copy_for_inline (XEXP (SUBREG_REG (x), 0)));
PUT_MODE (new, GET_MODE (x));
return validize_mem (new);
@@ -960,8 +1031,16 @@ copy_for_inline (orig)
if (! RTX_INTEGRATED_P (x))
abort ();
- return XEXP (force_const_mem (GET_MODE (x),
- copy_for_inline (XEXP (x, 0))), 0);
+ new = force_const_mem (GET_MODE (XEXP (x, 0)),
+ copy_for_inline (XEXP (XEXP (x, 0), 0)));
+ new = XEXP (new, 0);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (new) != GET_MODE (x))
+ new = convert_memory_address (GET_MODE (x), new);
+#endif
+
+ return new;
case ASM_OPERANDS:
/* If a single asm insn contains multiple output operands
@@ -1070,6 +1149,8 @@ copy_for_inline (orig)
}
break;
#endif
+ default:
+ break;
}
/* Replace this rtx with a copy of itself. */
@@ -1105,7 +1186,7 @@ copy_for_inline (orig)
{
register int j;
- XVEC (x, i) = gen_rtvec_v (XVECLEN (x, i), &XVECEXP (x, i, 0));
+ XVEC (x, i) = gen_rtvec_vv (XVECLEN (x, i), XVEC (x, i)->elem);
for (j = 0; j < XVECLEN (x, i); j++)
XVECEXP (x, i, j)
= copy_for_inline (XVECEXP (x, i, j));
@@ -1151,7 +1232,8 @@ int global_const_equiv_map_size;
else an rtx for where the value is stored. */
rtx
-expand_inline_function (fndecl, parms, target, ignore, type, structure_value_addr)
+expand_inline_function (fndecl, parms, target, ignore, type,
+ structure_value_addr)
tree fndecl, parms;
rtx target;
int ignore;
@@ -1179,6 +1261,10 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
rtvec arg_vector = ORIGINAL_ARG_VECTOR (header);
rtx static_chain_value = 0;
+ /* The pointer used to track the true location of the memory used
+ for MAP->LABEL_MAP. */
+ rtx *real_label_map = 0;
+
/* Allow for equivalences of the pseudos we make for virtual fp and ap. */
max_regno = MAX_REGNUM (header) + 3;
if (max_regno < FIRST_PSEUDO_REGISTER)
@@ -1190,11 +1276,9 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
passed. Since the appropriate conversions or default promotions have
already been applied, the machine modes should match exactly. */
- for (formal = DECL_ARGUMENTS (fndecl),
- actual = parms;
+ for (formal = DECL_ARGUMENTS (fndecl), actual = parms;
formal;
- formal = TREE_CHAIN (formal),
- actual = TREE_CHAIN (actual))
+ formal = TREE_CHAIN (formal), actual = TREE_CHAIN (actual))
{
tree arg;
enum machine_mode mode;
@@ -1203,13 +1287,15 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
return (rtx) (HOST_WIDE_INT) -1;
arg = TREE_VALUE (actual);
- mode= TYPE_MODE (DECL_ARG_TYPE (formal));
+ mode = TYPE_MODE (DECL_ARG_TYPE (formal));
if (mode != TYPE_MODE (TREE_TYPE (arg))
/* If they are block mode, the types should match exactly.
They don't match exactly if TREE_TYPE (FORMAL) == ERROR_MARK_NODE,
which could happen if the parameter has incomplete type. */
- || (mode == BLKmode && TREE_TYPE (arg) != TREE_TYPE (formal)))
+ || (mode == BLKmode
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (arg))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (formal)))))
return (rtx) (HOST_WIDE_INT) -1;
}
@@ -1224,10 +1310,6 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
parameter declarations. */
pushlevel (0);
- /* Make a fresh binding contour that we can easily remove. */
- pushlevel (0);
- expand_start_bindings (0);
-
/* Expand the function arguments. Do this first so that any
new registers get created before we allocate the maps. */
@@ -1303,6 +1385,12 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
handle SUBREGs in addresses. */
|| (GET_CODE (arg_vals[i]) == SUBREG)))
arg_vals[i] = copy_to_mode_reg (GET_MODE (loc), arg_vals[i]);
+
+ if (arg_vals[i] != 0 && GET_CODE (arg_vals[i]) == REG
+ && TREE_CODE (TREE_TYPE (formal)) == POINTER_TYPE)
+ mark_reg_pointer (arg_vals[i],
+ (TYPE_ALIGN (TREE_TYPE (TREE_TYPE (formal)))
+ / BITS_PER_UNIT));
}
/* Allocate the structures we use to remap things. */
@@ -1313,8 +1401,12 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
map->reg_map = (rtx *) alloca (max_regno * sizeof (rtx));
bzero ((char *) map->reg_map, max_regno * sizeof (rtx));
- map->label_map = (rtx *)alloca ((max_labelno - min_labelno) * sizeof (rtx));
- map->label_map -= min_labelno;
+ /* We used to use alloca here, but the size of what it would try to
+ allocate would occasionally cause it to exceed the stack limit and
+ cause unpredictable core dumps. */
+ real_label_map
+ = (rtx *) xmalloc ((max_labelno) * sizeof (rtx));
+ map->label_map = real_label_map;
map->insn_map = (rtx *) alloca (INSN_UID (header) * sizeof (rtx));
bzero ((char *) map->insn_map, INSN_UID (header) * sizeof (rtx));
@@ -1350,8 +1442,14 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
map->const_age = 0;
/* Record the current insn in case we have to set up pointers to frame
- and argument memory blocks. */
+ and argument memory blocks. If there are no insns yet, add a dummy
+ insn that can be used as an insertion point. */
map->insns_at_start = get_last_insn ();
+ if (map->insns_at_start == 0)
+ map->insns_at_start = emit_note (NULL_PTR, NOTE_INSN_DELETED);
+
+ map->regno_pointer_flag = INLINE_REGNO_POINTER_FLAG (header);
+ map->regno_pointer_align = INLINE_REGNO_POINTER_ALIGN (header);
/* Update the outgoing argument size to allow for those in the inlined
function. */
@@ -1437,7 +1535,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
that flag set if it is a register.
Also, don't allow hard registers here; they might not be valid
- when substituted into insns. */
+ when substituted into insns. */
if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
|| (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
@@ -1468,7 +1566,7 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
that flag set if it is a register.
Also, don't allow hard registers here; they might not be valid
- when substituted into insns. */
+ when substituted into insns. */
rtx locreal = gen_realpart (GET_MODE (XEXP (loc, 0)), loc);
rtx locimag = gen_imagpart (GET_MODE (XEXP (loc, 0)), loc);
rtx copyreal = gen_realpart (GET_MODE (locreal), copy);
@@ -1570,9 +1668,11 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
if (GET_CODE (XEXP (loc, 0)) == REG)
{
- temp = force_reg (Pmode, structure_value_addr);
+ temp = force_reg (Pmode,
+ force_operand (structure_value_addr, NULL_RTX));
map->reg_map[REGNO (XEXP (loc, 0))] = temp;
if ((CONSTANT_P (structure_value_addr)
+ || GET_CODE (structure_value_addr) == ADDRESSOF
|| (GET_CODE (structure_value_addr) == PLUS
&& XEXP (structure_value_addr, 0) == virtual_stack_vars_rtx
&& GET_CODE (XEXP (structure_value_addr, 1)) == CONST_INT))
@@ -1603,9 +1703,11 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
/* Machine mode function was declared to return. */
enum machine_mode departing_mode = TYPE_MODE (type);
/* (Possibly wider) machine mode it actually computes
- (for the sake of callers that fail to declare it right). */
+ (for the sake of callers that fail to declare it right).
+ We have to use the mode of the result's RTL, rather than
+ its type, since expand_function_start may have promoted it. */
enum machine_mode arriving_mode
- = TYPE_MODE (TREE_TYPE (DECL_RESULT (fndecl)));
+ = GET_MODE (DECL_RTL (DECL_RESULT (fndecl)));
rtx reg_to_map;
/* Don't use MEMs as direct targets because on some machines
@@ -1619,7 +1721,21 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
avoid machine mode mismatch when we substitute INLINE_TARGET.
But TARGET is what we will return to the caller. */
if (arriving_mode != departing_mode)
- reg_to_map = gen_rtx (SUBREG, arriving_mode, target, 0);
+ {
+ /* Avoid creating a paradoxical subreg wider than
+ BITS_PER_WORD, since that is illegal. */
+ if (GET_MODE_BITSIZE (arriving_mode) > BITS_PER_WORD)
+ {
+ if (!TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (departing_mode),
+ GET_MODE_BITSIZE (arriving_mode)))
+ /* Maybe could be handled by using convert_move () ? */
+ abort ();
+ reg_to_map = gen_reg_rtx (arriving_mode);
+ target = gen_lowpart (departing_mode, reg_to_map);
+ }
+ else
+ reg_to_map = gen_rtx (SUBREG, arriving_mode, target, 0);
+ }
else
reg_to_map = target;
@@ -1630,6 +1746,13 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
else
map->reg_map[REGNO (loc)] = reg_to_map;
}
+ else
+ abort ();
+
+ /* Make a fresh binding contour that we can easily remove. Do this after
+ expanding our arguments so cleanups are properly scoped. */
+ pushlevel (0);
+ expand_start_bindings (0);
/* Make new label equivalences for the labels in the called function. */
for (i = min_labelno; i < max_labelno; i++)
@@ -1761,7 +1884,9 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
break;
case JUMP_INSN:
- if (GET_CODE (PATTERN (insn)) == RETURN)
+ if (GET_CODE (PATTERN (insn)) == RETURN
+ || (GET_CODE (PATTERN (insn)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == RETURN))
{
if (local_return_label == 0)
local_return_label = gen_label_rtx ();
@@ -1808,8 +1933,8 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
/* Because the USAGE information potentially contains objects other
than hard registers, we need to copy it. */
- CALL_INSN_FUNCTION_USAGE (copy) =
- copy_rtx_and_substitute (CALL_INSN_FUNCTION_USAGE (insn), map);
+ CALL_INSN_FUNCTION_USAGE (copy)
+ = copy_rtx_and_substitute (CALL_INSN_FUNCTION_USAGE (insn), map);
#ifdef HAVE_cc0
if (cc0_insn)
@@ -1842,7 +1967,18 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
- copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
+ {
+ copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
+ if (copy && (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
+ || NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END))
+ {
+ rtx label = map->label_map[NOTE_BLOCK_NUMBER (copy)];
+
+ /* We have to forward these both to match the new exception
+ region. */
+ NOTE_BLOCK_NUMBER (copy) = CODE_LABEL_NUMBER (label);
+ }
+ }
else
copy = 0;
break;
@@ -1900,6 +2036,16 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
BLOCK_ABSTRACT_ORIGIN (block) = (DECL_ABSTRACT_ORIGIN (fndecl) == NULL
? fndecl : DECL_ABSTRACT_ORIGIN (fndecl));
poplevel (0, 0, 0);
+
+ /* Must mark the line number note after inlined functions as a repeat, so
+ that the test coverage code can avoid counting the call twice. This
+ just tells the code to ignore the immediately following line note, since
+ there already exists a copy of this note before the expanded inline call.
+ This line number note is still needed for debugging though, so we can't
+ delete it. */
+ if (flag_test_coverage)
+ emit_note (0, NOTE_REPEATED_LINE_NUMBER);
+
emit_line_note (input_filename, lineno);
if (structure_value_addr)
@@ -1908,6 +2054,11 @@ expand_inline_function (fndecl, parms, target, ignore, type, structure_value_add
memory_address (TYPE_MODE (type), structure_value_addr));
MEM_IN_STRUCT_P (target) = 1;
}
+
+ /* Make sure we free the things we explicitly allocated with xmalloc. */
+ if (real_label_map)
+ free (real_label_map);
+
return target;
}
@@ -1973,7 +2124,6 @@ integrate_decl_tree (let, level, map)
for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
{
tree d;
- tree newd;
push_obstacks_nochange ();
saveable_allocation ();
@@ -1992,28 +2142,13 @@ integrate_decl_tree (let, level, map)
}
/* These args would always appear unused, if not for this. */
TREE_USED (d) = 1;
+ /* Prevent warning for shadowing with these. */
+ DECL_ABSTRACT_ORIGIN (d) = t;
if (DECL_LANG_SPECIFIC (d))
copy_lang_decl (d);
- /* Must set DECL_ABSTRACT_ORIGIN here for local variables, to ensure
- that we don't get -Wshadow warnings. But don't set it here if
- pushdecl might return a duplicate decl, as that will result in
- incorrect DWARF debug info. */
- if (! DECL_EXTERNAL (d) || ! TREE_PUBLIC (d))
- /* Prevent warning for shadowing with these. */
- DECL_ABSTRACT_ORIGIN (d) = t;
-
- newd = pushdecl (d);
-
- /* If we didn't set DECL_ABSTRACT_ORIGIN above, then set it now.
- Simpler to just set it always rather than checking.
- If the decl we get back is the copy of 't' that we started with,
- then set the DECL_ABSTRACT_ORIGIN. Otherwise, we must have a
- duplicate decl, and we got the older one back. In that case, setting
- DECL_ABSTRACT_ORIGIN is not appropriate. */
- if (newd == d)
- DECL_ABSTRACT_ORIGIN (d) = t;
+ pushdecl (d);
}
for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
@@ -2029,6 +2164,23 @@ integrate_decl_tree (let, level, map)
}
}
}
+
+/* Given a BLOCK node LET, search for all DECL_RTL fields, and pass them
+ through save_constants. */
+
+static void
+save_constants_in_decl_trees (let)
+ tree let;
+{
+ tree t;
+
+ for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
+ if (DECL_RTL (t) != 0)
+ save_constants (&DECL_RTL (t));
+
+ for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
+ save_constants_in_decl_trees (t);
+}
/* Create a new copy of an rtx.
Recursively copies the operands of the rtx,
@@ -2086,22 +2238,31 @@ copy_rtx_and_substitute (orig, map)
{
rtx loc, seq;
int size = DECL_FRAME_SIZE (map->fndecl);
- int rounded;
+#ifdef FRAME_GROWS_DOWNWARD
+ /* In this case, virtual_stack_vars_rtx points to one byte
+ higher than the top of the frame area. So make sure we
+ allocate a big enough chunk to keep the frame pointer
+ aligned like a real one. */
+ size = CEIL_ROUND (size, BIGGEST_ALIGNMENT / BITS_PER_UNIT);
+#endif
start_sequence ();
loc = assign_stack_temp (BLKmode, size, 1);
loc = XEXP (loc, 0);
#ifdef FRAME_GROWS_DOWNWARD
/* In this case, virtual_stack_vars_rtx points to one byte
higher than the top of the frame area. So compute the offset
- to one byte higher than our substitute frame.
- Keep the fake frame pointer aligned like a real one. */
- rounded = CEIL_ROUND (size, BIGGEST_ALIGNMENT / BITS_PER_UNIT);
- loc = plus_constant (loc, rounded);
+ to one byte higher than our substitute frame. */
+ loc = plus_constant (loc, size);
#endif
map->reg_map[regno] = temp
= force_reg (Pmode, force_operand (loc, NULL_RTX));
+#ifdef STACK_BOUNDARY
+ mark_reg_pointer (map->reg_map[regno],
+ STACK_BOUNDARY / BITS_PER_UNIT);
+#endif
+
if (REGNO (temp) < map->const_equiv_map_size)
{
map->const_equiv_map[REGNO (temp)] = loc;
@@ -2116,7 +2277,7 @@ copy_rtx_and_substitute (orig, map)
else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
{
/* Do the same for a block to contain any arguments referenced
- in memory. */
+ in memory. */
rtx loc, seq;
int size = FUNCTION_ARGS_SIZE (DECL_SAVED_INSNS (map->fndecl));
@@ -2125,13 +2286,18 @@ copy_rtx_and_substitute (orig, map)
loc = XEXP (loc, 0);
/* When arguments grow downward, the virtual incoming
args pointer points to the top of the argument block,
- so the remapped location better do the same. */
+ so the remapped location better do the same. */
#ifdef ARGS_GROW_DOWNWARD
loc = plus_constant (loc, size);
#endif
map->reg_map[regno] = temp
= force_reg (Pmode, force_operand (loc, NULL_RTX));
+#ifdef STACK_BOUNDARY
+ mark_reg_pointer (map->reg_map[regno],
+ STACK_BOUNDARY / BITS_PER_UNIT);
+#endif
+
if (REGNO (temp) < map->const_equiv_map_size)
{
map->const_equiv_map[REGNO (temp)] = loc;
@@ -2166,6 +2332,10 @@ copy_rtx_and_substitute (orig, map)
REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (orig);
RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (orig);
/* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
+
+ if (map->regno_pointer_flag[regno])
+ mark_reg_pointer (map->reg_map[regno],
+ map->regno_pointer_align[regno]);
}
return map->reg_map[regno];
@@ -2181,6 +2351,30 @@ copy_rtx_and_substitute (orig, map)
return gen_rtx (SUBREG, GET_MODE (orig), copy,
SUBREG_WORD (orig));
+ case ADDRESSOF:
+ copy = gen_rtx (ADDRESSOF, mode,
+ copy_rtx_and_substitute (XEXP (orig, 0), map));
+ SET_ADDRESSOF_DECL (copy, ADDRESSOF_DECL (orig));
+ regno = ADDRESSOF_REGNO (orig);
+ if (map->reg_map[regno])
+ regno = REGNO (map->reg_map[regno]);
+ else if (regno > LAST_VIRTUAL_REGISTER)
+ {
+ temp = XEXP (orig, 0);
+ map->reg_map[regno] = gen_reg_rtx (GET_MODE (temp));
+ REG_USERVAR_P (map->reg_map[regno]) = REG_USERVAR_P (temp);
+ REG_LOOP_TEST_P (map->reg_map[regno]) = REG_LOOP_TEST_P (temp);
+ RTX_UNCHANGING_P (map->reg_map[regno]) = RTX_UNCHANGING_P (temp);
+ /* A reg with REG_FUNCTION_VALUE_P true will never reach here. */
+
+ if (map->regno_pointer_flag[regno])
+ mark_reg_pointer (map->reg_map[regno],
+ map->regno_pointer_align[regno]);
+ regno = REGNO (map->reg_map[regno]);
+ }
+ ADDRESSOF_REGNO (copy) = regno;
+ return copy;
+
case USE:
case CLOBBER:
/* USE and CLOBBER are ordinary, but we convert (use (subreg foo))
@@ -2233,7 +2427,7 @@ copy_rtx_and_substitute (orig, map)
{
rtx constant = get_pool_constant (orig);
if (GET_CODE (constant) == LABEL_REF)
- return XEXP (force_const_mem (Pmode,
+ return XEXP (force_const_mem (GET_MODE (orig),
copy_rtx_and_substitute (constant,
map)),
0);
@@ -2280,8 +2474,10 @@ copy_rtx_and_substitute (orig, map)
if (! RTX_INTEGRATED_P (orig))
abort ();
- temp = force_const_mem (GET_MODE (orig),
- copy_rtx_and_substitute (XEXP (orig, 0), map));
+ temp
+ = force_const_mem (GET_MODE (XEXP (orig, 0)),
+ copy_rtx_and_substitute (XEXP (XEXP (orig, 0), 0),
+ map));
#if 0
/* Legitimizing the address here is incorrect.
@@ -2300,13 +2496,20 @@ copy_rtx_and_substitute (orig, map)
will not have valid reg_map entries. This can cause try_constants()
to fail because assumes that all registers in the rtx have valid
reg_map entries, and it may end up replacing one of these new
- registers with junk. */
+ registers with junk. */
if (! memory_address_p (GET_MODE (temp), XEXP (temp, 0)))
temp = change_address (temp, GET_MODE (temp), XEXP (temp, 0));
#endif
- return XEXP (temp, 0);
+ temp = XEXP (temp, 0);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (temp) != GET_MODE (orig))
+ temp = convert_memory_address (GET_MODE (orig), temp);
+#endif
+
+ return temp;
case ASM_OPERANDS:
/* If a single asm insn contains multiple output operands
@@ -2349,13 +2552,26 @@ copy_rtx_and_substitute (orig, map)
case SET:
/* If this is setting fp or ap, it means that we have a nonlocal goto.
- Don't alter that.
+ Adjust the setting by the offset of the area we made.
If the nonlocal goto is into the current function,
this will result in unnecessarily bad code, but should work. */
if (SET_DEST (orig) == virtual_stack_vars_rtx
|| SET_DEST (orig) == virtual_incoming_args_rtx)
- return gen_rtx (SET, VOIDmode, SET_DEST (orig),
- copy_rtx_and_substitute (SET_SRC (orig), map));
+ {
+ /* In case a translation hasn't occurred already, make one now. */
+ rtx junk = copy_rtx_and_substitute (SET_DEST (orig), map);
+ rtx equiv_reg = map->reg_map[REGNO (SET_DEST (orig))];
+ rtx equiv_loc = map->const_equiv_map[REGNO (equiv_reg)];
+ HOST_WIDE_INT loc_offset
+ = GET_CODE (equiv_loc) == REG ? 0 : INTVAL (XEXP (equiv_loc, 1));
+
+ return gen_rtx (SET, VOIDmode, SET_DEST (orig),
+ force_operand
+ (plus_constant
+ (copy_rtx_and_substitute (SET_SRC (orig), map),
+ - loc_offset),
+ NULL_RTX));
+ }
break;
case MEM:
@@ -2374,6 +2590,9 @@ copy_rtx_and_substitute (orig, map)
RTX_UNCHANGING_P (copy) = RTX_UNCHANGING_P (orig);
return copy;
+
+ default:
+ break;
}
copy = rtx_alloc (code);
@@ -2389,6 +2608,7 @@ copy_rtx_and_substitute (orig, map)
switch (*format_ptr++)
{
case '0':
+ XEXP (copy, i) = XEXP (orig, i);
break;
case 'e':
@@ -2580,6 +2800,7 @@ subst_constants (loc, insn, map)
new = operand_subword (inner, SUBREG_WORD (x), 0,
GET_MODE (SUBREG_REG (x)));
+ cancel_changes (num_changes);
if (new == 0 && subreg_lowpart_p (x))
new = gen_lowpart_common (GET_MODE (x), inner);
@@ -2612,8 +2833,6 @@ subst_constants (loc, insn, map)
src = SET_SRC (x);
while (GET_CODE (*dest_loc) == ZERO_EXTRACT
- /* By convention, we always use ZERO_EXTRACT in the dest. */
-/* || GET_CODE (*dest_loc) == SIGN_EXTRACT */
|| GET_CODE (*dest_loc) == SUBREG
|| GET_CODE (*dest_loc) == STRICT_LOW_PART)
{
@@ -2667,9 +2886,11 @@ subst_constants (loc, insn, map)
map->equiv_sets[map->num_sets].equiv = copy_rtx (src);
map->equiv_sets[map->num_sets++].dest = dest;
}
-
- return;
}
+ return;
+
+ default:
+ break;
}
format_ptr = GET_RTX_FORMAT (code);
@@ -2789,9 +3010,13 @@ mark_stores (dest, x)
: regno + HARD_REGNO_NREGS (regno, mode) - 1);
int i;
- for (i = regno; i <= last_reg; i++)
- if (i < global_const_equiv_map_size)
- global_const_equiv_map[i] = 0;
+ /* Ignore virtual stack var or virtual arg register since those
+ are handled separately. */
+ if (regno != VIRTUAL_INCOMING_ARGS_REGNUM
+ && regno != VIRTUAL_STACK_VARS_REGNUM)
+ for (i = regno; i <= last_reg; i++)
+ if (i < global_const_equiv_map_size)
+ global_const_equiv_map[i] = 0;
}
}
@@ -2846,8 +3071,16 @@ restore_constants (px)
}
else if (RTX_INTEGRATED_P (x) && GET_CODE (x) == ADDRESS)
{
- restore_constants (&XEXP (x, 0));
- *px = XEXP (force_const_mem (GET_MODE (x), XEXP (x, 0)), 0);
+ rtx new = XEXP (force_const_mem (GET_MODE (XEXP (x, 0)),
+ XEXP (XEXP (x, 0), 0)),
+ 0);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+ if (GET_MODE (new) != GET_MODE (x))
+ new = convert_memory_address (GET_MODE (x), new);
+#endif
+
+ *px = new;
}
else
{
@@ -2948,25 +3181,20 @@ set_block_abstract_flags (stmt, setting)
register tree stmt;
register int setting;
{
- BLOCK_ABSTRACT (stmt) = setting;
-
- {
- register tree local_decl;
+ register tree local_decl;
+ register tree subblock;
- for (local_decl = BLOCK_VARS (stmt);
- local_decl != NULL_TREE;
- local_decl = TREE_CHAIN (local_decl))
- set_decl_abstract_flags (local_decl, setting);
- }
+ BLOCK_ABSTRACT (stmt) = setting;
- {
- register tree subblock;
+ for (local_decl = BLOCK_VARS (stmt);
+ local_decl != NULL_TREE;
+ local_decl = TREE_CHAIN (local_decl))
+ set_decl_abstract_flags (local_decl, setting);
- for (subblock = BLOCK_SUBBLOCKS (stmt);
- subblock != NULL_TREE;
- subblock = BLOCK_CHAIN (subblock))
- set_block_abstract_flags (subblock, setting);
- }
+ for (subblock = BLOCK_SUBBLOCKS (stmt);
+ subblock != NULL_TREE;
+ subblock = BLOCK_CHAIN (subblock))
+ set_block_abstract_flags (subblock, setting);
}
/* Given a pointer to some ..._DECL node, and a boolean value to set the
@@ -3028,8 +3256,15 @@ output_inline_function (fndecl)
/* Set stack frame size. */
assign_stack_local (BLKmode, DECL_FRAME_SIZE (fndecl), 0);
- restore_reg_data (FIRST_PARM_INSN (head));
-
+ /* The first is a bit of a lie (the array may be larger), but doesn't
+ matter too much and it isn't worth saving the actual bound. */
+ reg_rtx_no = regno_pointer_flag_length = MAX_REGNUM (head);
+ regno_reg_rtx = (rtx *) INLINE_REGNO_REG_RTX (head);
+ regno_pointer_flag = INLINE_REGNO_POINTER_FLAG (head);
+ regno_pointer_align = INLINE_REGNO_POINTER_ALIGN (head);
+ max_parm_reg = MAX_PARMREG (head);
+ parm_reg_stack_loc = (rtx *) PARMREG_STACK_LOC (head);
+
stack_slot_list = STACK_SLOT_LIST (head);
forced_labels = FORCED_LABELS (head);
diff --git a/gnu/usr.bin/gcc/integrate.h b/gnu/usr.bin/gcc/integrate.h
index 2b14f88d67d..b2acf5e5c1d 100644
--- a/gnu/usr.bin/gcc/integrate.h
+++ b/gnu/usr.bin/gcc/integrate.h
@@ -1,5 +1,5 @@
/* Function integration definitions for GNU C-Compiler
- Copyright (C) 1990 Free Software Foundation, Inc.
+ Copyright (C) 1990, 1995 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -93,6 +93,10 @@ struct inline_remap
/* Likewise, this is the copied constraints vector. */
rtvec copy_asm_constraints_vector;
+ /* Indications for regs being pointers and their alignment. */
+ char *regno_pointer_flag;
+ char *regno_pointer_align;
+
/* The next few fields are used for subst_constants to record the SETs
that it saw. */
int num_sets;
diff --git a/gnu/usr.bin/gcc/jump.c b/gnu/usr.bin/gcc/jump.c
index 88a6c3aad1c..5377eb3e284 100644
--- a/gnu/usr.bin/gcc/jump.c
+++ b/gnu/usr.bin/gcc/jump.c
@@ -1,5 +1,5 @@
/* Optimize jump instructions, for GNU compiler.
- Copyright (C) 1987, 88, 89, 91-94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 91-97, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -52,14 +52,17 @@ Boston, MA 02111-1307, USA. */
from other passes as well. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "flags.h"
#include "hard-reg-set.h"
#include "regs.h"
#include "insn-config.h"
#include "insn-flags.h"
+#include "recog.h"
#include "expr.h"
#include "real.h"
+#include "except.h"
/* ??? Eventually must record somehow the labels used by jumps
from nested functions. */
@@ -100,7 +103,7 @@ int can_reach_end;
Normally they are not significant, because of A and B jump to C,
and R dies in A, it must die in B. But this might not be true after
stack register conversion, and we must compare death notes in that
- case. */
+ case. */
static int cross_jump_death_matters = 0;
@@ -114,6 +117,7 @@ static void delete_computation PROTO((rtx));
static void delete_from_jump_chain PROTO((rtx));
static int delete_labelref_insn PROTO((rtx, rtx, int));
static void redirect_tablejump PROTO((rtx, rtx));
+static rtx find_insert_position PROTO((rtx, rtx));
/* Delete no-op jumps and optimize jumps to jumps
and jumps around jumps.
@@ -234,6 +238,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
for (insn = forced_labels; insn; insn = XEXP (insn, 1))
LABEL_NUSES (XEXP (insn, 0))++;
+ check_exception_handler_labels ();
+
+ /* Keep track of labels used for marking handlers for exception
+ regions; they cannot usually be deleted. */
+
+ for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
+ LABEL_NUSES (XEXP (insn, 0))++;
+
+ exception_optimize ();
+
/* Delete all labels already not referenced.
Also find the last insn. */
@@ -438,28 +452,40 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
sreg, NULL_PTR, dreg,
GET_MODE (SET_SRC (body)));
-#ifdef PRESERVE_DEATH_INFO_REGNO_P
- /* Deleting insn could lose a death-note for SREG or DREG
- so don't do it if final needs accurate death-notes. */
- if (! PRESERVE_DEATH_INFO_REGNO_P (sreg)
- && ! PRESERVE_DEATH_INFO_REGNO_P (dreg))
-#endif
+ if (tem != 0
+ && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
{
/* DREG may have been the target of a REG_DEAD note in
the insn which makes INSN redundant. If so, reorg
would still think it is dead. So search for such a
note and delete it if we find it. */
- for (trial = prev_nonnote_insn (insn);
- trial && GET_CODE (trial) != CODE_LABEL;
- trial = prev_nonnote_insn (trial))
- if (find_regno_note (trial, REG_DEAD, dreg))
- {
- remove_death (dreg, trial);
- break;
- }
-
- if (tem != 0
- && GET_MODE (tem) == GET_MODE (SET_DEST (body)))
+ if (! find_regno_note (insn, REG_UNUSED, dreg))
+ for (trial = prev_nonnote_insn (insn);
+ trial && GET_CODE (trial) != CODE_LABEL;
+ trial = prev_nonnote_insn (trial))
+ if (find_regno_note (trial, REG_DEAD, dreg))
+ {
+ remove_death (dreg, trial);
+ break;
+ }
+#ifdef PRESERVE_DEATH_INFO_REGNO_P
+ /* Deleting insn could lose a death-note for SREG
+ so don't do it if final needs accurate
+ death-notes. */
+ if (PRESERVE_DEATH_INFO_REGNO_P (sreg)
+ && (trial = find_regno_note (insn, REG_DEAD, sreg)))
+ {
+ /* Change this into a USE so that we won't emit
+ code for it, but still can keep the note. */
+ PATTERN (insn)
+ = gen_rtx (USE, VOIDmode, XEXP (trial, 0));
+ INSN_CODE (insn) = -1;
+ /* Remove all reg notes but the REG_DEAD one. */
+ REG_NOTES (insn) = trial;
+ XEXP (trial, 1) = NULL_RTX;
+ }
+ else
+#endif
delete_insn (insn);
}
}
@@ -499,7 +525,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
else if (GET_CODE (body) == PARALLEL)
{
/* If each part is a set between two identical registers or
- a USE or CLOBBER, delete the insn. */
+ a USE or CLOBBER, delete the insn. */
int i, sreg, dreg;
rtx tem;
@@ -547,11 +573,11 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
if (set && GET_CODE (SET_DEST (set)) == REG
&& REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
- && regno_first_uid[REGNO (SET_DEST (set))] == INSN_UID (insn)
+ && REGNO_FIRST_UID (REGNO (SET_DEST (set))) == INSN_UID (insn)
/* We use regno_last_note_uid so as not to delete the setting
of a reg that's used in notes. A subsequent optimization
might arrange to use that reg for real. */
- && regno_last_note_uid[REGNO (SET_DEST (set))] == INSN_UID (insn)
+ && REGNO_LAST_NOTE_UID (REGNO (SET_DEST (set))) == INSN_UID (insn)
&& ! side_effects_p (SET_SRC (set))
&& ! find_reg_note (insn, REG_RETVAL, 0))
delete_insn (insn);
@@ -682,7 +708,15 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& (temp1 = prev_nonnote_insn (JUMP_LABEL (insn))) != 0
&& (GET_CODE (temp1) == BARRIER
|| (GET_CODE (temp1) == INSN
- && rtx_equal_p (PATTERN (temp), PATTERN (temp1)))))
+ && rtx_equal_p (PATTERN (temp), PATTERN (temp1))))
+ /* Don't do this optimization if we have a loop containing only
+ the USE instruction, and the loop start label has a usage
+ count of 1. This is because we will redo this optimization
+ everytime through the outer loop, and jump opt will never
+ exit. */
+ && ! ((temp2 = prev_nonnote_insn (temp)) != 0
+ && temp2 == JUMP_LABEL (insn)
+ && LABEL_NUSES (temp2) == 1))
{
if (GET_CODE (temp1) == BARRIER)
{
@@ -729,9 +763,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& GET_CODE (temp3) == INSN
&& (temp4 = single_set (temp3)) != 0
&& GET_CODE (temp1 = SET_DEST (temp4)) == REG
-#ifdef SMALL_REGISTER_CLASSES
- && REGNO (temp1) >= FIRST_PSEUDO_REGISTER
-#endif
+ && (! SMALL_REGISTER_CLASSES
+ || REGNO (temp1) >= FIRST_PSEUDO_REGISTER)
&& (temp2 = next_active_insn (insn)) != 0
&& GET_CODE (temp2) == INSN
&& (temp4 = single_set (temp2)) != 0
@@ -833,6 +866,96 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
}
}
+ /* Simplify if (...) { x = a; goto l; } x = b; by converting it
+ to x = a; if (...) goto l; x = b;
+ if A is sufficiently simple, the test doesn't involve X,
+ and nothing in the test modifies A or X.
+
+ If we have small register classes, we also can't do this if X
+ is a hard register.
+
+ If the "x = a;" insn has any REG_NOTES, we don't do this because
+ of the possibility that we are running after CSE and there is a
+ REG_EQUAL note that is only valid if the branch has already been
+ taken. If we move the insn with the REG_EQUAL note, we may
+ fold the comparison to always be false in a later CSE pass.
+ (We could also delete the REG_NOTES when moving the insn, but it
+ seems simpler to not move it.) An exception is that we can move
+ the insn if the only note is a REG_EQUAL or REG_EQUIV whose
+ value is the same as "a".
+
+ INSN is the goto.
+
+ We set:
+
+ TEMP to the jump insn preceding "x = a;"
+ TEMP1 to X
+ TEMP2 to the insn that sets "x = b;"
+ TEMP3 to the insn that sets "x = a;"
+ TEMP4 to the set of "x = a"; */
+
+ if (this_is_simplejump
+ && (temp2 = next_active_insn (insn)) != 0
+ && GET_CODE (temp2) == INSN
+ && (temp4 = single_set (temp2)) != 0
+ && GET_CODE (temp1 = SET_DEST (temp4)) == REG
+ && (! SMALL_REGISTER_CLASSES
+ || REGNO (temp1) >= FIRST_PSEUDO_REGISTER)
+ && (temp3 = prev_active_insn (insn)) != 0
+ && GET_CODE (temp3) == INSN
+ && (temp4 = single_set (temp3)) != 0
+ && rtx_equal_p (SET_DEST (temp4), temp1)
+ && (GET_CODE (SET_SRC (temp4)) == REG
+ || GET_CODE (SET_SRC (temp4)) == SUBREG
+ || CONSTANT_P (SET_SRC (temp4)))
+ && (REG_NOTES (temp3) == 0
+ || ((REG_NOTE_KIND (REG_NOTES (temp3)) == REG_EQUAL
+ || REG_NOTE_KIND (REG_NOTES (temp3)) == REG_EQUIV)
+ && XEXP (REG_NOTES (temp3), 1) == 0
+ && rtx_equal_p (XEXP (REG_NOTES (temp3), 0),
+ SET_SRC (temp4))))
+ && (temp = prev_active_insn (temp3)) != 0
+ && condjump_p (temp) && ! simplejump_p (temp)
+ /* TEMP must skip over the "x = a;" insn */
+ && prev_real_insn (JUMP_LABEL (temp)) == insn
+ && no_labels_between_p (temp, insn))
+ {
+ rtx prev_label = JUMP_LABEL (temp);
+ rtx insert_after = prev_nonnote_insn (temp);
+
+#ifdef HAVE_cc0
+ /* We cannot insert anything between a set of cc and its use. */
+ if (insert_after && GET_RTX_CLASS (GET_CODE (insert_after)) == 'i'
+ && sets_cc0_p (PATTERN (insert_after)))
+ insert_after = prev_nonnote_insn (insert_after);
+#endif
+ ++LABEL_NUSES (prev_label);
+
+ if (insert_after
+ && no_labels_between_p (insert_after, temp)
+ && ! reg_referenced_between_p (temp1, insert_after, temp3)
+ && ! reg_referenced_between_p (temp1, temp3,
+ NEXT_INSN (temp2))
+ && ! reg_set_between_p (temp1, insert_after, temp)
+ && (GET_CODE (SET_SRC (temp4)) == CONST_INT
+ || ! reg_set_between_p (SET_SRC (temp4),
+ insert_after, temp))
+ && invert_jump (temp, JUMP_LABEL (insn)))
+ {
+ emit_insn_after_with_line_notes (PATTERN (temp3),
+ insert_after, temp3);
+ delete_insn (temp3);
+ delete_insn (insn);
+ /* Set NEXT to an insn that we know won't go away. */
+ next = temp2;
+ changed = 1;
+ }
+ if (prev_label && --LABEL_NUSES (prev_label) == 0)
+ delete_insn (prev_label);
+ if (changed)
+ continue;
+ }
+
#ifndef HAVE_cc0
/* If we have if (...) x = exp; and branches are expensive,
EXP is a single insn, does not have any side effects, cannot
@@ -863,9 +986,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& (temp1 = single_set (temp)) != 0
&& (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG)
&& GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT
-#ifdef SMALL_REGISTER_CLASSES
- && REGNO (temp2) >= FIRST_PSEUDO_REGISTER
-#endif
+ && (! SMALL_REGISTER_CLASSES
+ || REGNO (temp2) >= FIRST_PSEUDO_REGISTER)
&& GET_CODE (SET_SRC (temp1)) != REG
&& GET_CODE (SET_SRC (temp1)) != SUBREG
&& GET_CODE (SET_SRC (temp1)) != CONST_INT
@@ -875,11 +997,12 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
{
rtx new = gen_reg_rtx (GET_MODE (temp2));
- if (validate_change (temp, &SET_DEST (temp1), new, 0))
+ if ((temp3 = find_insert_position (insn, temp))
+ && validate_change (temp, &SET_DEST (temp1), new, 0))
{
next = emit_insn_after (gen_move_insn (temp2, new), insn);
emit_insn_after_with_line_notes (PATTERN (temp),
- PREV_INSN (insn), temp);
+ PREV_INSN (temp3), temp);
delete_insn (temp);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
}
@@ -905,9 +1028,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& (temp1 = single_set (temp)) != 0
&& (temp2 = SET_DEST (temp1), GET_CODE (temp2) == REG)
&& GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT
-#ifdef SMALL_REGISTER_CLASSES
- && REGNO (temp2) >= FIRST_PSEUDO_REGISTER
-#endif
+ && (! SMALL_REGISTER_CLASSES
+ || REGNO (temp2) >= FIRST_PSEUDO_REGISTER)
&& ! side_effects_p (SET_SRC (temp1))
&& ! may_trap_p (SET_SRC (temp1))
&& rtx_cost (SET_SRC (temp1), SET) < 10
@@ -919,14 +1041,19 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
{
rtx new = gen_reg_rtx (GET_MODE (temp2));
- if (validate_change (temp, &SET_DEST (temp1), new, 0))
+ if ((temp5 = find_insert_position (insn, temp))
+ && (temp6 = find_insert_position (insn, temp3))
+ && validate_change (temp, &SET_DEST (temp1), new, 0))
{
+ /* Use the earliest of temp5 and temp6. */
+ if (temp5 != insn)
+ temp6 = temp5;
next = emit_insn_after (gen_move_insn (temp2, new), insn);
emit_insn_after_with_line_notes (PATTERN (temp),
- PREV_INSN (insn), temp);
+ PREV_INSN (temp6), temp);
emit_insn_after_with_line_notes
(replace_rtx (PATTERN (temp3), temp2, new),
- PREV_INSN (insn), temp3);
+ PREV_INSN (temp6), temp3);
delete_insn (temp);
delete_insn (temp3);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
@@ -935,7 +1062,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
/* Finally, handle the case where two insns are used to
compute EXP but a temporary register is used. Here we must
- ensure that the temporary register is not used anywhere else. */
+ ensure that the temporary register is not used anywhere else. */
if (! reload_completed
&& after_regscan
@@ -958,17 +1085,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& (temp5 = SUBREG_REG (temp5),
GET_CODE (temp5) == REG))))
&& REGNO (temp5) >= FIRST_PSEUDO_REGISTER
- && regno_first_uid[REGNO (temp5)] == INSN_UID (temp)
- && regno_last_uid[REGNO (temp5)] == INSN_UID (temp3)
+ && REGNO_FIRST_UID (REGNO (temp5)) == INSN_UID (temp)
+ && REGNO_LAST_UID (REGNO (temp5)) == INSN_UID (temp3)
&& ! side_effects_p (SET_SRC (temp1))
&& ! may_trap_p (SET_SRC (temp1))
&& rtx_cost (SET_SRC (temp1), SET) < 10
&& (temp4 = single_set (temp3)) != 0
&& (temp2 = SET_DEST (temp4), GET_CODE (temp2) == REG)
&& GET_MODE_CLASS (GET_MODE (temp2)) == MODE_INT
-#ifdef SMALL_REGISTER_CLASSES
- && REGNO (temp2) >= FIRST_PSEUDO_REGISTER
-#endif
+ && (! SMALL_REGISTER_CLASSES
+ || REGNO (temp2) >= FIRST_PSEUDO_REGISTER)
&& rtx_equal_p (SET_DEST (temp4), temp2)
&& ! side_effects_p (SET_SRC (temp4))
&& ! may_trap_p (SET_SRC (temp4))
@@ -976,13 +1102,18 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
{
rtx new = gen_reg_rtx (GET_MODE (temp2));
- if (validate_change (temp3, &SET_DEST (temp4), new, 0))
+ if ((temp5 = find_insert_position (insn, temp))
+ && (temp6 = find_insert_position (insn, temp3))
+ && validate_change (temp3, &SET_DEST (temp4), new, 0))
{
+ /* Use the earliest of temp5 and temp6. */
+ if (temp5 != insn)
+ temp6 = temp5;
next = emit_insn_after (gen_move_insn (temp2, new), insn);
emit_insn_after_with_line_notes (PATTERN (temp),
- PREV_INSN (insn), temp);
+ PREV_INSN (temp6), temp);
emit_insn_after_with_line_notes (PATTERN (temp3),
- PREV_INSN (insn), temp3);
+ PREV_INSN (temp6), temp3);
delete_insn (temp);
delete_insn (temp3);
reallabelprev = prev_active_insn (JUMP_LABEL (insn));
@@ -1019,9 +1150,8 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& GET_CODE (temp) == INSN
&& GET_CODE (PATTERN (temp)) == SET
&& GET_CODE (temp1 = SET_DEST (PATTERN (temp))) == REG
-#ifdef SMALL_REGISTER_CLASSES
- && REGNO (temp1) >= FIRST_PSEUDO_REGISTER
-#endif
+ && (! SMALL_REGISTER_CLASSES
+ || REGNO (temp1) >= FIRST_PSEUDO_REGISTER)
&& (GET_CODE (temp2 = SET_SRC (PATTERN (temp))) == REG
|| GET_CODE (temp2) == SUBREG
/* ??? How about floating point constants? */
@@ -1030,8 +1160,11 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
There is no point in using the old value of TEMP1 if
it is a register, since cse will alias them. It can
lose if the old value were a hard register since CSE
- won't replace hard registers. */
- && (((temp3 = reg_set_last (temp1, insn)) != 0)
+ won't replace hard registers. Avoid using TEMP3 if
+ small register classes and it is a hard register. */
+ && (((temp3 = reg_set_last (temp1, insn)) != 0
+ && ! (SMALL_REGISTER_CLASSES && GET_CODE (temp3) == REG
+ && REGNO (temp3) < FIRST_PSEUDO_REGISTER))
/* Make the latter case look like x = x; if (...) x = b; */
|| (temp3 = temp1, 1))
/* INSN must either branch to the insn after TEMP or the insn
@@ -1045,13 +1178,9 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
We could handle BLKmode if (1) emit_store_flag could
and (2) we could find the size reliably. */
&& GET_MODE (XEXP (temp4, 0)) != BLKmode
- /* No point in doing any of this if branches are cheap or we
- don't have conditional moves. */
- && (BRANCH_COST >= 2
-#ifdef HAVE_conditional_move
- || 1
-#endif
- )
+ /* Even if branches are cheap, the store_flag optimization
+ can win when the operation to be performed can be
+ expressed directly. */
#ifdef HAVE_cc0
/* If the previous insn sets CC0 and something else, we can't
do this since we are going to delete that insn. */
@@ -1121,7 +1250,9 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
end_sequence ();
emit_insns_before (seq1, temp5);
- emit_insns_before (seq2, insn);
+ /* Insert conditional move after insn, to be sure that
+ the jump and a possible compare won't be separated */
+ emit_insns_after (seq2, insn);
/* ??? We can also delete the insn that sets X to A.
Flow will do it too though. */
@@ -1160,8 +1291,19 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
can reverse the condition. See if (3) applies possibly
by reversing the condition. Prefer reversing to (4) when
branches are very expensive. */
- && ((reversep = 0, temp2 == const0_rtx)
- || (temp3 == const0_rtx
+ && (((BRANCH_COST >= 2
+ || STORE_FLAG_VALUE == -1
+ || (STORE_FLAG_VALUE == 1
+ /* Check that the mask is a power of two,
+ so that it can probably be generated
+ with a shift. */
+ && exact_log2 (INTVAL (temp3)) >= 0))
+ && (reversep = 0, temp2 == const0_rtx))
+ || ((BRANCH_COST >= 2
+ || STORE_FLAG_VALUE == -1
+ || (STORE_FLAG_VALUE == 1
+ && exact_log2 (INTVAL (temp2)) >= 0))
+ && temp3 == const0_rtx
&& (reversep = can_reverse_comparison_p (temp4, insn)))
|| (BRANCH_COST >= 2
&& GET_CODE (temp2) == CONST_INT
@@ -1362,6 +1504,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
into our sequence. */
if ((temp5 = prev_active_insn (insn)) != 0
+ && no_labels_between_p (temp5, insn)
&& GET_CODE (temp5) == INSN
&& (temp6 = single_set (temp5)) != 0
&& rtx_equal_p (temp2, SET_DEST (temp6))
@@ -1505,7 +1648,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
else if (ultimate && GET_CODE (ultimate) != RETURN)
ultimate = XEXP (ultimate, 0);
- if (ultimate)
+ if (ultimate && JUMP_LABEL(insn) != ultimate)
changed |= redirect_jump (insn, ultimate);
}
}
@@ -1730,9 +1873,21 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
&& (next_active_insn (JUMP_LABEL (insn))
== next_active_insn (JUMP_LABEL (temp))))
{
- delete_jump (insn);
- changed = 1;
- continue;
+ rtx tem = temp;
+
+ /* ??? Optional. Disables some optimizations, but makes
+ gcov output more accurate with -O. */
+ if (flag_test_coverage && !reload_completed)
+ for (tem = insn; tem != temp; tem = NEXT_INSN (tem))
+ if (GET_CODE (tem) == NOTE && NOTE_LINE_NUMBER (tem) > 0)
+ break;
+
+ if (tem == temp)
+ {
+ delete_jump (insn);
+ changed = 1;
+ continue;
+ }
}
/* Detect a conditional jump jumping over an unconditional jump. */
@@ -1916,7 +2071,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
/* Now that the jump has been tensioned,
try cross jumping: check for identical code
- before the jump and before its target label. */
+ before the jump and before its target label. */
/* First, cross jumping of conditional jumps: */
@@ -1951,7 +2106,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
INSN_CODE (insn) = -1;
emit_barrier_after (insn);
/* Add to jump_chain unless this is a new label
- whose UID is too large. */
+ whose UID is too large. */
if (INSN_UID (JUMP_LABEL (insn)) < max_jump_chain)
{
jump_chain[INSN_UID (insn)]
@@ -2184,6 +2339,8 @@ duplicate_loop_exit_test (loop_start)
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX))
return 0;
break;
+ default:
+ break;
}
}
@@ -2202,10 +2359,10 @@ duplicate_loop_exit_test (loop_start)
|| (GET_CODE (reg) == SUBREG
&& (reg = SUBREG_REG (reg), GET_CODE (reg) == REG)))
&& REGNO (reg) >= FIRST_PSEUDO_REGISTER
- && regno_first_uid[REGNO (reg)] == INSN_UID (insn))
+ && REGNO_FIRST_UID (REGNO (reg)) == INSN_UID (insn))
{
for (p = NEXT_INSN (insn); p != lastexit; p = NEXT_INSN (p))
- if (regno_last_uid[REGNO (reg)] == INSN_UID (p))
+ if (REGNO_LAST_UID (REGNO (reg)) == INSN_UID (p))
break;
if (p != lastexit)
@@ -2433,13 +2590,13 @@ find_cross_jump (e1, e2, minimum, f1, f2)
#ifdef STACK_REGS
/* If cross_jump_death_matters is not 0, the insn's mode
indicates whether or not the insn contains any stack-like
- regs. */
+ regs. */
if (!lose && cross_jump_death_matters && GET_MODE (i1) == QImode)
{
/* If register stack conversion has already been done, then
death notes must also be compared before it is certain that
- the two instruction streams match. */
+ the two instruction streams match. */
rtx note;
HARD_REG_SET i1_regset, i2_regset;
@@ -2466,7 +2623,19 @@ find_cross_jump (e1, e2, minimum, f1, f2)
}
#endif
- if (lose || GET_CODE (p1) != GET_CODE (p2)
+ /* Don't allow old-style asm or volatile extended asms to be accepted
+ for cross jumping purposes. It is conceptually correct to allow
+ them, since cross-jumping preserves the dynamic instruction order
+ even though it is changing the static instruction order. However,
+ if an asm is being used to emit an assembler pseudo-op, such as
+ the MIPS `.set reorder' pseudo-op, then the static instruction order
+ matters and it must be preserved. */
+ if (GET_CODE (p1) == ASM_INPUT || GET_CODE (p2) == ASM_INPUT
+ || (GET_CODE (p1) == ASM_OPERANDS && MEM_VOLATILE_P (p1))
+ || (GET_CODE (p2) == ASM_OPERANDS && MEM_VOLATILE_P (p2)))
+ lose = 1;
+
+ if (lose || GET_CODE (p1) != GET_CODE (p2)
|| ! rtx_renumbered_equal_p (p1, p2))
{
/* The following code helps take care of G++ cleanups. */
@@ -2922,6 +3091,9 @@ comparison_dominates_p (code1, code2)
if (code2 == GEU || code2 == NE)
return 1;
break;
+
+ default:
+ break;
}
return 0;
@@ -3054,7 +3226,8 @@ follow_jumps (label)
(depth < 10
&& (insn = next_active_insn (value)) != 0
&& GET_CODE (insn) == JUMP_INSN
- && (JUMP_LABEL (insn) != 0 || GET_CODE (PATTERN (insn)) == RETURN)
+ && ((JUMP_LABEL (insn) != 0 && simplejump_p (insn))
+ || GET_CODE (PATTERN (insn)) == RETURN)
&& (next = NEXT_INSN (insn))
&& GET_CODE (next) == BARRIER);
depth++)
@@ -3067,7 +3240,10 @@ follow_jumps (label)
if (!reload_completed)
for (tem = value; tem != insn; tem = NEXT_INSN (tem))
if (GET_CODE (tem) == NOTE
- && NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG)
+ && (NOTE_LINE_NUMBER (tem) == NOTE_INSN_LOOP_BEG
+ /* ??? Optional. Disables some optimizations, but makes
+ gcov output more accurate with -O. */
+ || (flag_test_coverage && NOTE_LINE_NUMBER (tem) > 0)))
return value;
/* If we have found a cycle, make the insn jump to itself. */
@@ -3188,7 +3364,10 @@ mark_jump_label (x, insn, cross_jump)
break;
else if (! cross_jump
&& (NOTE_LINE_NUMBER (next) == NOTE_INSN_LOOP_BEG
- || NOTE_LINE_NUMBER (next) == NOTE_INSN_FUNCTION_END))
+ || NOTE_LINE_NUMBER (next) == NOTE_INSN_FUNCTION_END
+ /* ??? Optional. Disables some optimizations, but
+ makes gcov output more accurate with -O. */
+ || (flag_test_coverage && NOTE_LINE_NUMBER (next) > 0)))
break;
}
@@ -3235,8 +3414,11 @@ mark_jump_label (x, insn, cross_jump)
for (i = 0; i < XVECLEN (x, eltnum); i++)
mark_jump_label (XVECEXP (x, eltnum, i), NULL_RTX, cross_jump);
- return;
}
+ return;
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -3603,7 +3785,21 @@ invert_jump (jump, nlabel)
return 0;
if (redirect_jump (jump, nlabel))
- return 1;
+ {
+ if (flag_branch_probabilities)
+ {
+ rtx note = find_reg_note (jump, REG_BR_PROB, 0);
+
+ /* An inverted jump means that a probability taken becomes a
+ probability not taken. Subtract the branch probability from the
+ probability base to convert it back to a taken probability.
+ (We don't flip the probability on a branch that's never taken. */
+ if (note && XINT (XEXP (note, 0), 0) >= 0)
+ XINT (XEXP (note, 0), 0) = REG_BR_PROB_BASE - XINT (XEXP (note, 0), 0);
+ }
+
+ return 1;
+ }
if (! invert_exp (PATTERN (jump), jump))
/* This should just be putting it back the way it was. */
@@ -3990,6 +4186,9 @@ rtx_renumbered_equal_p (x, y)
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);
+
+ default:
+ break;
}
/* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
@@ -4279,7 +4478,10 @@ thread_jumps (f, max_reg, flag_before_loop)
if (rtx_equal_for_thread_p (b1op0, b2op0, b2)
&& rtx_equal_for_thread_p (b1op1, b2op1, b2)
&& (comparison_dominates_p (code1, code2)
- || comparison_dominates_p (code1, reverse_condition (code2))))
+ || (comparison_dominates_p (code1, reverse_condition (code2))
+ && can_reverse_comparison_p (XEXP (SET_SRC (PATTERN (b1)),
+ 0),
+ b1))))
{
t1 = prev_nonnote_insn (b1);
t2 = prev_nonnote_insn (b2);
@@ -4366,6 +4568,13 @@ rtx_equal_for_thread_p (x, y, yinsn)
if (GET_MODE (x) != GET_MODE (y))
return 0;
+ /* For floating-point, consider everything unequal. This is a bit
+ pessimistic, but this pass would only rarely do anything for FP
+ anyway. */
+ if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
+ && FLOAT_MODE_P (GET_MODE (x)) && ! flag_fast_math)
+ return 0;
+
/* For commutative operations, the RTX match if the operand match in any
order. Also handle the simple binary and unary cases without a loop. */
if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
@@ -4401,7 +4610,7 @@ rtx_equal_for_thread_p (x, y, yinsn)
/* If this is the first time we are seeing a register on the `Y'
side, see if it is the last use. If not, we can't thread the
jump, so mark it as not equivalent. */
- if (regno_last_uid[REGNO (y)] != INSN_UID (yinsn))
+ if (REGNO_LAST_UID (REGNO (y)) != INSN_UID (yinsn))
return 0;
return 1;
@@ -4413,7 +4622,7 @@ rtx_equal_for_thread_p (x, y, yinsn)
case MEM:
/* If memory modified or either volatile, not equivalent.
- Else, check address. */
+ Else, check address. */
if (modified_mem || MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
return 0;
@@ -4450,6 +4659,9 @@ rtx_equal_for_thread_p (x, y, yinsn)
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);
+
+ default:
+ break;
}
if (x == y)
@@ -4511,3 +4723,45 @@ rtx_equal_for_thread_p (x, y, yinsn)
}
return 1;
}
+
+
+/* Return the insn that NEW can be safely inserted in front of starting at
+ the jump insn INSN. Return 0 if it is not safe to do this jump
+ optimization. Note that NEW must contain a single set. */
+
+static rtx
+find_insert_position (insn, new)
+ rtx insn;
+ rtx new;
+{
+ int i;
+ rtx prev;
+
+ /* If NEW does not clobber, it is safe to insert NEW before INSN. */
+ if (GET_CODE (PATTERN (new)) != PARALLEL)
+ return insn;
+
+ for (i = XVECLEN (PATTERN (new), 0) - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (PATTERN (new), 0, i)) == CLOBBER
+ && reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (new), 0, i), 0),
+ insn))
+ break;
+
+ if (i < 0)
+ return insn;
+
+ /* There is a good chance that the previous insn PREV sets the thing
+ being clobbered (often the CC in a hard reg). If PREV does not
+ use what NEW sets, we can insert NEW before PREV. */
+
+ prev = prev_active_insn (insn);
+ for (i = XVECLEN (PATTERN (new), 0) - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (PATTERN (new), 0, i)) == CLOBBER
+ && reg_overlap_mentioned_p (XEXP (XVECEXP (PATTERN (new), 0, i), 0),
+ insn)
+ && ! modified_in_p (XEXP (XVECEXP (PATTERN (new), 0, i), 0),
+ prev))
+ return 0;
+
+ return reg_mentioned_p (SET_DEST (single_set (new)), prev) ? 0 : prev;
+}
diff --git a/gnu/usr.bin/gcc/libgcc1-test.c b/gnu/usr.bin/gcc/libgcc1-test.c
index 392d4fc7e9c..977b9c76188 100644
--- a/gnu/usr.bin/gcc/libgcc1-test.c
+++ b/gnu/usr.bin/gcc/libgcc1-test.c
@@ -95,6 +95,9 @@ dfoo ()
message saying the start address is defaulted. */
extern void start() __asm__("start");
extern void _start() __asm__("_start");
+extern void __start() __asm__("__start");
void start() {}
void _start() {}
+void __start() {}
+void mainCRTStartup() {}
diff --git a/gnu/usr.bin/gcc/libgcc2.c b/gnu/usr.bin/gcc/libgcc2.c
index 1e01e913986..001ee1c6c04 100644
--- a/gnu/usr.bin/gcc/libgcc2.c
+++ b/gnu/usr.bin/gcc/libgcc2.c
@@ -1,6 +1,6 @@
/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -42,10 +42,17 @@ Boston, MA 02111-1307, USA. */
#undef abort
#endif
-#if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF)
+#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
#define WEAK_ALIAS
#endif
+/* In a cross-compilation situation, default to inhibiting compilation
+ of routines that use libc. */
+
+#ifdef CROSS_COMPILE
+#define inhibit_libc
+#endif
+
/* Permit the tm.h file to select the endianness to use just for this
file. This is used when the endianness is determined when the
compiler is run. */
@@ -138,8 +145,7 @@ extern DItype __fixunstfdi (TFtype a);
static inline
#endif
DItype
-__negdi2 (u)
- DItype u;
+__negdi2 (DItype u)
{
DIunion w;
DIunion uu;
@@ -153,11 +159,11 @@ __negdi2 (u)
}
#endif
+/* Unless shift functions are defined whith full ANSI prototypes,
+ parameter b will be promoted to int if word_type is smaller than an int. */
#ifdef L_lshrdi3
DItype
-__lshrdi3 (u, b)
- DItype u;
- word_type b;
+__lshrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
@@ -187,9 +193,7 @@ __lshrdi3 (u, b)
#ifdef L_ashldi3
DItype
-__ashldi3 (u, b)
- DItype u;
- word_type b;
+__ashldi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
@@ -219,9 +223,7 @@ __ashldi3 (u, b)
#ifdef L_ashrdi3
DItype
-__ashrdi3 (u, b)
- DItype u;
- word_type b;
+__ashrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
@@ -252,8 +254,7 @@ __ashrdi3 (u, b)
#ifdef L_ffsdi2
DItype
-__ffsdi2 (u)
- DItype u;
+__ffsdi2 (DItype u)
{
DIunion uu, w;
uu.ll = u;
@@ -273,8 +274,7 @@ __ffsdi2 (u)
#ifdef L_muldi3
DItype
-__muldi3 (u, v)
- DItype u, v;
+__muldi3 (DItype u, DItype v)
{
DIunion w;
DIunion uu, vv;
@@ -293,8 +293,7 @@ __muldi3 (u, v)
#ifdef L_udiv_w_sdiv
#if defined (sdiv_qrnnd)
USItype
-__udiv_w_sdiv (rp, a1, a0, d)
- USItype *rp, a1, a0, d;
+__udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
{
USItype q, r;
USItype c0, c1, b1;
@@ -392,8 +391,7 @@ __udiv_w_sdiv (rp, a1, a0, d)
#else
/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
USItype
-__udiv_w_sdiv (rp, a1, a0, d)
- USItype *rp, a1, a0, d;
+__udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
{}
#endif
#endif
@@ -421,9 +419,7 @@ static const UQItype __clz_tab[] =
static inline
#endif
UDItype
-__udivmoddi4 (n, d, rp)
- UDItype n, d;
- UDItype *rp;
+__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
{
DIunion ww;
DIunion nn, dd;
@@ -533,7 +529,7 @@ __udivmoddi4 (n, d, rp)
udiv_qrnnd (q1, n1, n2, n1, d0);
}
- /* n1 != d0... */
+ /* n1 != d0... */
udiv_qrnnd (q0, n0, n1, n0, d0);
@@ -644,8 +640,7 @@ __udivmoddi4 (n, d, rp)
UDItype __udivmoddi4 ();
DItype
-__divdi3 (u, v)
- DItype u, v;
+__divdi3 (DItype u, DItype v)
{
word_type c = 0;
DIunion uu, vv;
@@ -672,8 +667,7 @@ __divdi3 (u, v)
#ifdef L_moddi3
UDItype __udivmoddi4 ();
DItype
-__moddi3 (u, v)
- DItype u, v;
+__moddi3 (DItype u, DItype v)
{
word_type c = 0;
DIunion uu, vv;
@@ -699,8 +693,7 @@ __moddi3 (u, v)
#ifdef L_umoddi3
UDItype __udivmoddi4 ();
UDItype
-__umoddi3 (u, v)
- UDItype u, v;
+__umoddi3 (UDItype u, UDItype v)
{
UDItype w;
@@ -713,8 +706,7 @@ __umoddi3 (u, v)
#ifdef L_udivdi3
UDItype __udivmoddi4 ();
UDItype
-__udivdi3 (n, d)
- UDItype n, d;
+__udivdi3 (UDItype n, UDItype d)
{
return __udivmoddi4 (n, d, (UDItype *) 0);
}
@@ -722,8 +714,7 @@ __udivdi3 (n, d)
#ifdef L_cmpdi2
word_type
-__cmpdi2 (a, b)
- DItype a, b;
+__cmpdi2 (DItype a, DItype b)
{
DIunion au, bu;
@@ -743,8 +734,7 @@ __cmpdi2 (a, b)
#ifdef L_ucmpdi2
word_type
-__ucmpdi2 (a, b)
- DItype a, b;
+__ucmpdi2 (DItype a, DItype b)
{
DIunion au, bu;
@@ -767,8 +757,7 @@ __ucmpdi2 (a, b)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
-__fixunstfdi (a)
- TFtype a;
+__fixunstfdi (TFtype a)
{
TFtype b;
UDItype v;
@@ -797,8 +786,7 @@ __fixunstfdi (a)
#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
DItype
-__fixtfdi (a)
- TFtype a;
+__fixtfdi (TFtype a)
{
if (a < 0)
return - __fixunstfdi (-a);
@@ -811,8 +799,7 @@ __fixtfdi (a)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
-__fixunsxfdi (a)
- XFtype a;
+__fixunsxfdi (XFtype a)
{
XFtype b;
UDItype v;
@@ -841,8 +828,7 @@ __fixunsxfdi (a)
#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
DItype
-__fixxfdi (a)
- XFtype a;
+__fixxfdi (XFtype a)
{
if (a < 0)
return - __fixunsxfdi (-a);
@@ -855,8 +841,7 @@ __fixxfdi (a)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
-__fixunsdfdi (a)
- DFtype a;
+__fixunsdfdi (DFtype a)
{
DFtype b;
UDItype v;
@@ -885,8 +870,7 @@ __fixunsdfdi (a)
#ifdef L_fixdfdi
DItype
-__fixdfdi (a)
- DFtype a;
+__fixdfdi (DFtype a)
{
if (a < 0)
return - __fixunsdfdi (-a);
@@ -946,8 +930,7 @@ __fixsfdi (SFtype a)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
XFtype
-__floatdixf (u)
- DItype u;
+__floatdixf (DItype u)
{
XFtype d;
SItype negate = 0;
@@ -970,8 +953,7 @@ __floatdixf (u)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
TFtype
-__floatditf (u)
- DItype u;
+__floatditf (DItype u)
{
TFtype d;
SItype negate = 0;
@@ -994,8 +976,7 @@ __floatditf (u)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DFtype
-__floatdidf (u)
- DItype u;
+__floatdidf (DItype u)
{
DFtype d;
SItype negate = 0;
@@ -1047,8 +1028,7 @@ __floatdidf (u)
#endif
SFtype
-__floatdisf (u)
- DItype u;
+__floatdisf (DItype u)
{
/* Do the calculation in DFmode
so that we don't lose any of the precision of the high word
@@ -1098,8 +1078,7 @@ __floatdisf (u)
#include <limits.h>
USItype
-__fixunsxfsi (a)
- XFtype a;
+__fixunsxfsi (XFtype a)
{
if (a >= - (DFtype) LONG_MIN)
return (SItype) (a + LONG_MIN) - LONG_MIN;
@@ -1121,8 +1100,7 @@ __fixunsxfsi (a)
#include <limits.h>
USItype
-__fixunsdfsi (a)
- DFtype a;
+__fixunsdfsi (DFtype a)
{
if (a >= - (DFtype) LONG_MIN)
return (SItype) (a + LONG_MIN) - LONG_MIN;
@@ -1176,9 +1154,7 @@ __fixunssfsi (SFtype a)
positive if S1 is greater, 0 if S1 and S2 are equal. */
int
-__gcc_bcmp (s1, s2, size)
- unsigned char *s1, *s2;
- size_t size;
+__gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
{
while (size > 0)
{
@@ -1192,6 +1168,11 @@ __gcc_bcmp (s1, s2, size)
#endif
+#ifdef L__dummy
+void
+__dummy () {}
+#endif
+
#ifdef L_varargs
#ifdef __i860__
#if defined(__svr4__) || defined(__alliant__)
@@ -1399,7 +1380,7 @@ asm ("___builtin_saveregs:");
asm (" sw $7,12($30)");
asm (" j $31");
asm (" .end __builtin_saveregs");
-#else /* not __mips__, etc. */
+#else /* not __mips__, etc. */
void *
__builtin_saveregs ()
@@ -1419,11 +1400,8 @@ __builtin_saveregs ()
#include <stdio.h>
/* This is used by the `assert' macro. */
void
-__eprintf (string, expression, line, filename)
- const char *string;
- const char *expression;
- int line;
- const char *filename;
+__eprintf (const char *string, const char *expression,
+ int line, const char *filename)
{
fprintf (stderr, string, expression, line, filename);
fflush (stderr);
@@ -1450,6 +1428,7 @@ struct bb
const char **functions;
const long *line_nums;
const char **filenames;
+ char *flags;
};
#ifdef BLOCK_PROFILER_CODE
@@ -1465,19 +1444,8 @@ BLOCK_PROFILER_CODE
#include <stdio.h>
char *ctime ();
-#ifdef HAVE_ATEXIT
-#ifdef WINNT
-extern int atexit (void (*) (void));
-#else
-extern void atexit (void (*) (void));
-#endif
-#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
-#else
-#ifdef sun
-extern void on_exit (void*, void*);
-#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
-#endif
-#endif
+#include "gbl-ctors.h"
+#include "gcov-io.h"
static struct bb *bb_head;
@@ -1501,8 +1469,118 @@ static struct bb *bb_head;
void
__bb_exit_func (void)
{
- FILE *file = fopen ("bb.out", "a");
+ FILE *da_file, *file;
long time_value;
+ int i;
+
+ if (bb_head == 0)
+ return;
+
+ i = strlen (bb_head->filename) - 3;
+
+ if (!strcmp (bb_head->filename+i, ".da"))
+ {
+ /* Must be -fprofile-arcs not -a.
+ Dump data in a form that gcov expects. */
+
+ struct bb *ptr;
+
+ for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+ {
+ /* If the file exists, and the number of counts in it is the same,
+ then merge them in. */
+
+ if ((da_file = fopen (ptr->filename, "r")) != 0)
+ {
+ long n_counts = 0;
+ unsigned char tmp;
+ int i;
+ int ret = 0;
+
+
+ if (__read_long (&n_counts, da_file, 8) != 0)
+ {
+ fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+ ptr->filename);
+ continue;
+ }
+
+ if (n_counts == ptr->ncounts)
+ {
+ int i;
+
+ for (i = 0; i < n_counts; i++)
+ {
+ long v = 0;
+ unsigned char tmp;
+ int j;
+ int ret = 0;
+
+ if (__read_long (&v, da_file, 8) != 0)
+ {
+ fprintf (stderr, "arc profiling: Can't read output file %s.\n",
+ ptr->filename);
+ break;
+ }
+ ptr->counts[i] += v;
+ }
+ }
+
+ if (fclose (da_file) == EOF)
+ fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+ ptr->filename);
+ }
+ if ((da_file = fopen (ptr->filename, "w")) == 0)
+ {
+ fprintf (stderr, "arc profiling: Can't open output file %s.\n",
+ ptr->filename);
+ continue;
+ }
+
+ /* ??? Should first write a header to the file. Preferably, a 4 byte
+ magic number, 4 bytes containing the time the program was
+ compiled, 4 bytes containing the last modification time of the
+ source file, and 4 bytes indicating the compiler options used.
+
+ That way we can easily verify that the proper source/executable/
+ data file combination is being used from gcov. */
+
+ if (__write_long (ptr->ncounts, da_file, 8) != 0)
+ {
+
+ fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
+ }
+ else
+ {
+ int j;
+ long *count_ptr = ptr->counts;
+ int ret = 0;
+ for (j = ptr->ncounts; j > 0; j--)
+ {
+ if (__write_long (*count_ptr, da_file, 8) != 0)
+ {
+ ret=1;
+ break;
+ }
+ count_ptr++;
+ }
+ if (ret)
+ fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+ ptr->filename);
+ }
+
+ if (fclose (da_file) == EOF)
+ fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+ ptr->filename);
+ }
+
+ return;
+ }
+
+ /* Must be basic block profiling. Emit a human readable output file. */
+
+ file = fopen ("bb.out", "a");
if (!file)
perror ("bb.out");
@@ -1513,22 +1591,25 @@ __bb_exit_func (void)
/* This is somewhat type incorrect, but it avoids worrying about
exactly where time.h is included from. It should be ok unless
- a void * differs from other pointer formats, or if sizeof(long)
+ a void * differs from other pointer formats, or if sizeof (long)
is < sizeof (time_t). It would be nice if we could assume the
use of rationale standards here. */
- time((void *) &time_value);
+ time ((void *) &time_value);
fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
/* We check the length field explicitly in order to allow compatibility
with older GCC's which did not provide it. */
- for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
+ for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
{
int i;
- int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
+ int func_p = (ptr->nwords >= sizeof (struct bb)
+ && ptr->nwords <= 1000
+ && ptr->functions);
int line_p = (func_p && ptr->line_nums);
int file_p = (func_p && ptr->filenames);
+ int addr_p = (ptr->addresses != 0);
long ncounts = ptr->ncounts;
long cnt_max = 0;
long line_max = 0;
@@ -1552,7 +1633,7 @@ __bb_exit_func (void)
if (cnt_max < ptr->counts[i])
cnt_max = ptr->counts[i];
- if (addr_max < ptr->addresses[i])
+ if (addr_p && addr_max < ptr->addresses[i])
addr_max = ptr->addresses[i];
if (line_p && line_max < ptr->line_nums[i])
@@ -1583,10 +1664,13 @@ __bb_exit_func (void)
for (i = 0; i < ncounts; i++)
{
fprintf (file,
- " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
+ " Block #%*d: executed %*ld time(s)",
blk_len, i+1,
- cnt_len, ptr->counts[i],
- addr_len, ptr->addresses[i]);
+ cnt_len, ptr->counts[i]);
+
+ if (addr_p)
+ fprintf (file, " address= 0x%.*lx", addr_len,
+ ptr->addresses[i]);
if (func_p)
fprintf (file, " function= %-*s", func_len,
@@ -1615,7 +1699,7 @@ void
__bb_init_func (struct bb *blocks)
{
/* User is supposed to check whether the first word is non-0,
- but just in case.... */
+ but just in case.... */
if (blocks->zero_word)
return;
@@ -1632,16 +1716,739 @@ __bb_init_func (struct bb *blocks)
bb_head = blocks;
}
+#ifndef MACHINE_STATE_SAVE
+#define MACHINE_STATE_SAVE(ID)
+#endif
+#ifndef MACHINE_STATE_RESTORE
+#define MACHINE_STATE_RESTORE(ID)
+#endif
+
+#include <string.h>
+
+/* Number of buckets in hashtable of basic block addresses. */
+
+#define BB_BUCKETS 311
+
+/* Maximum length of string in file bb.in. */
+
+#define BBINBUFSIZE 500
+
+/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
+ "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
+
+#define BBINBUFSIZESTR "499"
+
+struct bb_edge
+{
+ struct bb_edge *next;
+ unsigned long src_addr;
+ unsigned long dst_addr;
+ unsigned long count;
+};
+
+enum bb_func_mode
+{
+ TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
+};
+
+struct bb_func
+{
+ struct bb_func *next;
+ char *funcname;
+ char *filename;
+ enum bb_func_mode mode;
+};
+
+/* This is the connection to the outside world.
+ The BLOCK_PROFILER macro must set __bb.blocks
+ and __bb.blockno. */
+
+struct {
+ unsigned long blockno;
+ struct bb *blocks;
+} __bb;
+
+/* Vars to store addrs of source and destination basic blocks
+ of a jump. */
+
+static unsigned long bb_src = 0;
+static unsigned long bb_dst = 0;
+
+static FILE *bb_tracefile = (FILE *) 0;
+static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
+static struct bb_func *bb_func_head = (struct bb_func *) 0;
+static unsigned long bb_callcount = 0;
+static int bb_mode = 0;
+
+static unsigned long *bb_stack = (unsigned long *) 0;
+static size_t bb_stacksize = 0;
+
+static int reported = 0;
+
+/* Trace modes:
+Always : Print execution frequencies of basic blocks
+ to file bb.out.
+bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
+bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
+bb_mode & 4 != 0 : Cut call instructions from basic block flow.
+bb_mode & 8 != 0 : Insert return instructions in basic block flow.
+*/
+
+#ifdef HAVE_POPEN
+
+/*#include <sys/types.h>*/
+#include <sys/stat.h>
+/*#include <malloc.h>*/
+
+/* Commands executed by gopen. */
+
+#define GOPENDECOMPRESS "gzip -cd "
+#define GOPENCOMPRESS "gzip -c >"
+
+/* Like fopen but pipes through gzip. mode may only be "r" or "w".
+ If it does not compile, simply replace gopen by fopen and delete
+ '.gz' from any first parameter to gopen. */
+
+static FILE *
+gopen (char *fn, char *mode)
+{
+ int use_gzip;
+ char *p;
+
+ if (mode[1])
+ return (FILE *) 0;
+
+ if (mode[0] != 'r' && mode[0] != 'w')
+ return (FILE *) 0;
+
+ p = fn + strlen (fn)-1;
+ use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
+ || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
+
+ if (use_gzip)
+ {
+ if (mode[0]=='r')
+ {
+ FILE *f;
+ char *s = (char *) malloc (sizeof (char) * strlen (fn)
+ + sizeof (GOPENDECOMPRESS));
+ strcpy (s, GOPENDECOMPRESS);
+ strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
+ f = popen (s, mode);
+ free (s);
+ return f;
+ }
+
+ else
+ {
+ FILE *f;
+ char *s = (char *) malloc (sizeof (char) * strlen (fn)
+ + sizeof (GOPENCOMPRESS));
+ strcpy (s, GOPENCOMPRESS);
+ strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
+ if (!(f = popen (s, mode)))
+ f = fopen (s, mode);
+ free (s);
+ return f;
+ }
+ }
+
+ else
+ return fopen (fn, mode);
+}
+
+static int
+gclose (FILE *f)
+{
+ struct stat buf;
+
+ if (f != 0)
+ {
+ if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
+ return pclose (f);
+
+ return fclose (f);
+ }
+ return 0;
+}
+
+#endif /* HAVE_POPEN */
+
+/* Called once per program. */
+
+static void
+__bb_exit_trace_func ()
+{
+ FILE *file = fopen ("bb.out", "a");
+ struct bb_func *f;
+ struct bb_edge *e;
+ struct bb *b;
+
+ if (!file)
+ perror ("bb.out");
+
+ if (bb_mode & 1)
+ {
+ if (!bb_tracefile)
+ perror ("bbtrace");
+ else
+#ifdef HAVE_POPEN
+ gclose (bb_tracefile);
+#else
+ fclose (bb_tracefile);
+#endif /* HAVE_POPEN */
+ }
+
+ /* Check functions in `bb.in'. */
+
+ if (file)
+ {
+ long time_value;
+ const struct bb_func *p;
+ int printed_something = 0;
+ struct bb *ptr;
+ long blk;
+
+ /* This is somewhat type incorrect. */
+ time ((void *) &time_value);
+
+ for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
+ {
+ for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
+ {
+ if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
+ continue;
+ for (blk = 0; blk < ptr->ncounts; blk++)
+ {
+ if (!strcmp (p->funcname, ptr->functions[blk]))
+ goto found;
+ }
+ }
+
+ if (!printed_something)
+ {
+ fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
+ printed_something = 1;
+ }
+
+ fprintf (file, "\tFunction %s", p->funcname);
+ if (p->filename)
+ fprintf (file, " of file %s", p->filename);
+ fprintf (file, "\n" );
+
+found: ;
+ }
+
+ if (printed_something)
+ fprintf (file, "\n");
+
+ }
+
+ if (bb_mode & 2)
+ {
+ if (!bb_hashbuckets)
+ {
+ if (!reported)
+ {
+ fprintf (stderr, "Profiler: out of memory\n");
+ reported = 1;
+ }
+ return;
+ }
+
+ else if (file)
+ {
+ long time_value;
+ int i;
+ unsigned long addr_max = 0;
+ unsigned long cnt_max = 0;
+ int cnt_len;
+ int addr_len;
+
+ /* This is somewhat type incorrect, but it avoids worrying about
+ exactly where time.h is included from. It should be ok unless
+ a void * differs from other pointer formats, or if sizeof (long)
+ is < sizeof (time_t). It would be nice if we could assume the
+ use of rationale standards here. */
+
+ time ((void *) &time_value);
+ fprintf (file, "Basic block jump tracing");
+
+ switch (bb_mode & 12)
+ {
+ case 0:
+ fprintf (file, " (with call)");
+ break;
+
+ case 4:
+ /* Print nothing. */
+ break;
+
+ case 8:
+ fprintf (file, " (with call & ret)");
+ break;
+
+ case 12:
+ fprintf (file, " (with ret)");
+ break;
+ }
+
+ fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
+
+ for (i = 0; i < BB_BUCKETS; i++)
+ {
+ struct bb_edge *bucket = bb_hashbuckets[i];
+ for ( ; bucket; bucket = bucket->next )
+ {
+ if (addr_max < bucket->src_addr)
+ addr_max = bucket->src_addr;
+ if (addr_max < bucket->dst_addr)
+ addr_max = bucket->dst_addr;
+ if (cnt_max < bucket->count)
+ cnt_max = bucket->count;
+ }
+ }
+ addr_len = num_digits (addr_max, 16);
+ cnt_len = num_digits (cnt_max, 10);
+
+ for ( i = 0; i < BB_BUCKETS; i++)
+ {
+ struct bb_edge *bucket = bb_hashbuckets[i];
+ for ( ; bucket; bucket = bucket->next )
+ {
+ fprintf (file, "Jump from block 0x%.*lx to "
+ "block 0x%.*lx executed %*d time(s)\n",
+ addr_len, bucket->src_addr,
+ addr_len, bucket->dst_addr,
+ cnt_len, bucket->count);
+ }
+ }
+
+ fprintf (file, "\n");
+
+ }
+ }
+
+ if (file)
+ fclose (file);
+
+ /* Free allocated memory. */
+
+ f = bb_func_head;
+ while (f)
+ {
+ struct bb_func *old = f;
+
+ f = f->next;
+ if (old->funcname) free (old->funcname);
+ if (old->filename) free (old->filename);
+ free (old);
+ }
+
+ if (bb_stack)
+ free (bb_stack);
+
+ if (bb_hashbuckets)
+ {
+ int i;
+
+ for (i = 0; i < BB_BUCKETS; i++)
+ {
+ struct bb_edge *old, *bucket = bb_hashbuckets[i];
+
+ while (bucket)
+ {
+ old = bucket;
+ bucket = bucket->next;
+ free (old);
+ }
+ }
+ free (bb_hashbuckets);
+ }
+
+ for (b = bb_head; b; b = b->next)
+ if (b->flags) free (b->flags);
+}
+
+/* Called once per program. */
+
+static void
+__bb_init_prg ()
+{
+
+ FILE *file;
+ char buf[BBINBUFSIZE];
+ const char *p;
+ const char *pos;
+ enum bb_func_mode m;
+
+#ifdef ON_EXIT
+ /* Initialize destructor. */
+ ON_EXIT (__bb_exit_func, 0);
+#endif
+
+ if (!(file = fopen ("bb.in", "r")))
+ return;
+
+ while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
+ {
+ p = buf;
+ if (*p == '-')
+ {
+ m = TRACE_OFF;
+ p++;
+ }
+ else
+ {
+ m = TRACE_ON;
+ }
+ if (!strcmp (p, "__bb_trace__"))
+ bb_mode |= 1;
+ else if (!strcmp (p, "__bb_jumps__"))
+ bb_mode |= 2;
+ else if (!strcmp (p, "__bb_hidecall__"))
+ bb_mode |= 4;
+ else if (!strcmp (p, "__bb_showret__"))
+ bb_mode |= 8;
+ else
+ {
+ struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
+ if (f)
+ {
+ unsigned long l;
+ f->next = bb_func_head;
+ if (pos = strchr (p, ':'))
+ {
+ if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
+ continue;
+ strcpy (f->funcname, pos+1);
+ l = pos-p;
+ if ((f->filename = (char *) malloc (l+1)))
+ {
+ strncpy (f->filename, p, l);
+ f->filename[l] = '\0';
+ }
+ else
+ f->filename = (char *) 0;
+ }
+ else
+ {
+ if (!(f->funcname = (char *) malloc (strlen (p)+1)))
+ continue;
+ strcpy (f->funcname, p);
+ f->filename = (char *) 0;
+ }
+ f->mode = m;
+ bb_func_head = f;
+ }
+ }
+ }
+ fclose (file);
+
+#ifdef HAVE_POPEN
+
+ if (bb_mode & 1)
+ bb_tracefile = gopen ("bbtrace.gz", "w");
+
+#else
+
+ if (bb_mode & 1)
+ bb_tracefile = fopen ("bbtrace", "w");
+
+#endif /* HAVE_POPEN */
+
+ if (bb_mode & 2)
+ {
+ bb_hashbuckets = (struct bb_edge **)
+ malloc (BB_BUCKETS * sizeof (struct bb_edge *));
+ if (bb_hashbuckets)
+ bzero ((char *) bb_hashbuckets, BB_BUCKETS);
+ }
+
+ if (bb_mode & 12)
+ {
+ bb_stacksize = 10;
+ bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
+ }
+
+#ifdef ON_EXIT
+ /* Initialize destructor. */
+ ON_EXIT (__bb_exit_trace_func, 0);
+#endif
+
+}
+
+/* Called upon entering a basic block. */
+
+void
+__bb_trace_func ()
+{
+ struct bb_edge *bucket;
+
+ MACHINE_STATE_SAVE("1")
+
+ if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
+ goto skip;
+
+ bb_dst = __bb.blocks->addresses[__bb.blockno];
+ __bb.blocks->counts[__bb.blockno]++;
+
+ if (bb_tracefile)
+ {
+ fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
+ }
+
+ if (bb_hashbuckets)
+ {
+ struct bb_edge **startbucket, **oldnext;
+
+ oldnext = startbucket
+ = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
+ bucket = *startbucket;
+
+ for (bucket = *startbucket; bucket;
+ oldnext = &(bucket->next), bucket = *oldnext)
+ {
+ if (bucket->src_addr == bb_src
+ && bucket->dst_addr == bb_dst)
+ {
+ bucket->count++;
+ *oldnext = bucket->next;
+ bucket->next = *startbucket;
+ *startbucket = bucket;
+ goto ret;
+ }
+ }
+
+ bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
+
+ if (!bucket)
+ {
+ if (!reported)
+ {
+ fprintf (stderr, "Profiler: out of memory\n");
+ reported = 1;
+ }
+ }
+
+ else
+ {
+ bucket->src_addr = bb_src;
+ bucket->dst_addr = bb_dst;
+ bucket->next = *startbucket;
+ *startbucket = bucket;
+ bucket->count = 1;
+ }
+ }
+
+ret:
+ bb_src = bb_dst;
+
+skip:
+ ;
+
+ MACHINE_STATE_RESTORE("1")
+
+}
+
+/* Called when returning from a function and `__bb_showret__' is set. */
+
+static void
+__bb_trace_func_ret ()
+{
+ struct bb_edge *bucket;
+
+ if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
+ goto skip;
+
+ if (bb_hashbuckets)
+ {
+ struct bb_edge **startbucket, **oldnext;
+
+ oldnext = startbucket
+ = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
+ bucket = *startbucket;
+
+ for (bucket = *startbucket; bucket;
+ oldnext = &(bucket->next), bucket = *oldnext)
+ {
+ if (bucket->src_addr == bb_dst
+ && bucket->dst_addr == bb_src)
+ {
+ bucket->count++;
+ *oldnext = bucket->next;
+ bucket->next = *startbucket;
+ *startbucket = bucket;
+ goto ret;
+ }
+ }
+
+ bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
+
+ if (!bucket)
+ {
+ if (!reported)
+ {
+ fprintf (stderr, "Profiler: out of memory\n");
+ reported = 1;
+ }
+ }
+
+ else
+ {
+ bucket->src_addr = bb_dst;
+ bucket->dst_addr = bb_src;
+ bucket->next = *startbucket;
+ *startbucket = bucket;
+ bucket->count = 1;
+ }
+ }
+
+ret:
+ bb_dst = bb_src;
+
+skip:
+ ;
+
+}
+
+/* Called upon entering the first function of a file. */
+
+static void
+__bb_init_file (struct bb *blocks)
+{
+
+ const struct bb_func *p;
+ long blk, ncounts = blocks->ncounts;
+ const char **functions = blocks->functions;
+
+ /* Set up linked list. */
+ blocks->zero_word = 1;
+ blocks->next = bb_head;
+ bb_head = blocks;
+
+ blocks->flags = 0;
+ if (!bb_func_head
+ || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
+ return;
+
+ for (blk = 0; blk < ncounts; blk++)
+ blocks->flags[blk] = 0;
+
+ for (blk = 0; blk < ncounts; blk++)
+ {
+ for (p = bb_func_head; p; p = p->next)
+ {
+ if (!strcmp (p->funcname, functions[blk])
+ && (!p->filename || !strcmp (p->filename, blocks->filename)))
+ {
+ blocks->flags[blk] |= p->mode;
+ }
+ }
+ }
+
+}
+
+/* Called when exiting from a function. */
+
+void
+__bb_trace_ret ()
+{
+
+ MACHINE_STATE_SAVE("2")
+
+ if (bb_callcount)
+ {
+ if ((bb_mode & 12) && bb_stacksize > bb_callcount)
+ {
+ bb_src = bb_stack[bb_callcount];
+ if (bb_mode & 8)
+ __bb_trace_func_ret ();
+ }
+
+ bb_callcount -= 1;
+ }
+
+ MACHINE_STATE_RESTORE("2")
+
+}
+
+/* Called when entering a function. */
+
+void
+__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
+{
+ static int trace_init = 0;
+
+ MACHINE_STATE_SAVE("3")
+
+ if (!blocks->zero_word)
+ {
+ if (!trace_init)
+ {
+ trace_init = 1;
+ __bb_init_prg ();
+ }
+ __bb_init_file (blocks);
+ }
+
+ if (bb_callcount)
+ {
+
+ bb_callcount += 1;
+
+ if (bb_mode & 12)
+ {
+ if (bb_callcount >= bb_stacksize)
+ {
+ size_t newsize = bb_callcount + 100;
+
+ bb_stack = (unsigned long *) realloc (bb_stack, newsize);
+ if (! bb_stack)
+ {
+ if (!reported)
+ {
+ fprintf (stderr, "Profiler: out of memory\n");
+ reported = 1;
+ }
+ bb_stacksize = 0;
+ goto stack_overflow;
+ }
+ bb_stacksize = newsize;
+ }
+ bb_stack[bb_callcount] = bb_src;
+
+ if (bb_mode & 4)
+ bb_src = 0;
+
+ }
+
+stack_overflow:;
+
+ }
+
+ else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
+ {
+ bb_callcount = 1;
+ bb_src = 0;
+
+ if (bb_stack)
+ bb_stack[bb_callcount] = bb_src;
+ }
+
+ MACHINE_STATE_RESTORE("3")
+}
+
#endif /* not inhibit_libc */
#endif /* not BLOCK_PROFILER_CODE */
#endif /* L_bb */
/* Default free-store management functions for C++, per sections 12.5 and
- 17.3.3 of the Working Paper. */
+ 17.3.3 of the Working Paper. */
#ifdef L_op_new
/* operator new (size_t), described in 17.3.3.5. This function is used by
- C++ programs to allocate a block of memory to hold a single object. */
+ C++ programs to allocate a block of memory to hold a single object. */
typedef void (*vfp)(void);
extern vfp __new_handler;
@@ -1697,7 +2504,7 @@ __builtin_vec_new (size_t sz)
#ifdef L_new_handler
/* set_new_handler (fvoid_t *) and the default new handler, described in
17.3.3.2 and 17.3.3.5. These functions define the result of a failure
- to allocate the amount of memory requested from operator new or new []. */
+ to allocate the amount of memory requested from operator new or new []. */
#ifndef inhibit_libc
/* This gets us __GNU_LIBRARY__. */
@@ -1714,7 +2521,7 @@ __builtin_vec_new (size_t sz)
typedef void (*vfp)(void);
void __default_new_handler (void);
-vfp __new_handler = (vfp)0;
+vfp __new_handler = (vfp) 0;
vfp
set_new_handler (vfp handler)
@@ -1747,7 +2554,7 @@ __default_new_handler ()
#ifdef L_op_delete
/* operator delete (void *), described in 17.3.3.3. This function is used
by C++ programs to return to the free store a block of memory allocated
- as a single object. */
+ as a single object. */
#ifdef WEAK_ALIAS
void __builtin_delete (void *ptr)
@@ -1767,7 +2574,7 @@ __builtin_delete (void *ptr)
#ifdef L_op_vdel
/* operator delete [] (void *), described in 17.3.3.4. This function is
used by C++ programs to return to the free store a block of memory
- allocated as an array. */
+ allocated as an array. */
extern void __builtin_delete (void *);
@@ -1806,8 +2613,7 @@ unsigned int __shtab[] = {
#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
void
-__clear_cache (beg, end)
- char *beg, *end;
+__clear_cache (char *beg, char *end)
{
#ifdef CLEAR_INSN_CACHE
CLEAR_INSN_CACHE (beg, end);
@@ -1837,7 +2643,7 @@ __clear_cache (beg, end)
= JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
ptr += INSN_CACHE_LINE_WIDTH;
}
- *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
+ *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
initialized = 1;
}
@@ -1919,7 +2725,7 @@ __clear_cache (beg, end)
/* Jump to a trampoline, loading the static chain address. */
-#ifdef WINNT
+#if defined(WINNT) && ! defined(__CYGWIN32__)
long getpagesize()
{
@@ -1930,24 +2736,32 @@ long getpagesize()
#endif
}
-int mprotect(addr, len, prot)
- char *addr;
- int len, prot;
+#ifdef i386
+extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
+#endif
+
+int
+mprotect (char *addr, int len, int prot)
{
int np, op;
- if (prot == 7) np = 0x40;
- else if (prot == 5) np = 0x20;
- else if (prot == 4) np = 0x10;
- else if (prot == 3) np = 0x04;
- else if (prot == 1) np = 0x02;
- else if (prot == 0) np = 0x01;
+ if (prot == 7)
+ np = 0x40;
+ else if (prot == 5)
+ np = 0x20;
+ else if (prot == 4)
+ np = 0x10;
+ else if (prot == 3)
+ np = 0x04;
+ else if (prot == 1)
+ np = 0x02;
+ else if (prot == 0)
+ np = 0x01;
if (VirtualProtect (addr, len, np, &op))
return 0;
else
return -1;
-
}
#endif
@@ -1967,8 +2781,7 @@ TRANSFER_FROM_TRAMPOLINE
#endif
void
-__enable_execute_stack (addr)
- char *addr;
+__enable_execute_stack (char *addr)
{
kern_return_t r;
char *eaddr = addr + TRAMPOLINE_SIZE;
@@ -2016,14 +2829,14 @@ __enable_execute_stack ()
lowest = current;
}
- /* Clear instruction cache in case an old trampoline is in it. */
+ /* Clear instruction cache in case an old trampoline is in it. */
asm ("pich");
}
#endif /* __convex__ */
-#ifdef __DOLPHIN__
+#ifdef __sysV88__
-/* Modified from the convex -code above. */
+/* Modified from the convex -code above. */
#include <sys/param.h>
#include <errno.h>
@@ -2051,7 +2864,46 @@ __enable_execute_stack ()
errno=save_errno;
}
-#endif /* __DOLPHIN__ */
+#endif /* __sysV88__ */
+
+#ifdef __sysV68__
+
+#include <sys/signal.h>
+#include <errno.h>
+
+/* Motorola forgot to put memctl.o in the libp version of libc881.a,
+ so define it here, because we need it in __clear_insn_cache below */
+
+asm("\n\
+ global memctl\n\
+memctl:\n\
+ movq &75,%d0\n\
+ trap &0\n\
+ bcc.b noerror\n\
+ jmp cerror%\n\
+noerror:\n\
+ movq &0,%d0\n\
+ rts");
+
+/* Clear instruction cache so we can call trampolines on stack.
+ This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
+
+void
+__clear_insn_cache ()
+{
+ int save_errno;
+
+ /* Preserve errno, because users would be surprised to have
+ errno changing without explicitly calling any system-call. */
+ save_errno = errno;
+
+ /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
+ No need to use an address derived from _start or %sp, as 0 works also. */
+ memctl(0, 4096, MCT_TEXT);
+ errno = save_errno;
+}
+
+#endif /* __sysV68__ */
#ifdef __pyr__
@@ -2063,7 +2915,7 @@ __enable_execute_stack ()
#include <sys/vmmac.h>
/* Modified from the convex -code above.
- mremap promises to clear the i-cache. */
+ mremap promises to clear the i-cache. */
void
__enable_execute_stack ()
@@ -2078,6 +2930,31 @@ __enable_execute_stack ()
}
}
#endif /* __pyr__ */
+
+#if defined (sony_news) && defined (SYSTYPE_BSD)
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <syscall.h>
+#include <machine/sysnews.h>
+
+/* cacheflush function for NEWS-OS 4.2.
+ This function is called from trampoline-initialize code
+ defined in config/mips/mips.h. */
+
+void
+cacheflush (char *beg, int size, int flag)
+{
+ if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
+ {
+ perror ("cache_flush");
+ fflush (stderr);
+ abort ();
+ }
+}
+
+#endif /* sony_news */
#endif /* L_trampoline */
#ifdef L__main
@@ -2086,13 +2963,18 @@ __enable_execute_stack ()
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
- must define both, or neither. */
+ must define both, or neither. */
#ifndef NAME__MAIN
#define NAME__MAIN "__main"
#define SYMBOL__MAIN __main
#endif
-#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
+#ifdef INIT_SECTION_ASM_OP
+#undef HAS_INIT_SECTION
+#define HAS_INIT_SECTION
+#endif
+
+#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
/* Run all the global destructors on exit from the program. */
void
@@ -2101,14 +2983,17 @@ __do_global_dtors ()
#ifdef DO_GLOBAL_DTORS_BODY
DO_GLOBAL_DTORS_BODY;
#else
- func_ptr *p;
- for (p = __DTOR_LIST__ + 1; *p; )
- (*p++) ();
+ static func_ptr *p = __DTOR_LIST__ + 1;
+ while (*p)
+ {
+ p++;
+ (*(p-1)) ();
+ }
#endif
}
#endif
-#ifndef INIT_SECTION_ASM_OP
+#ifndef HAS_INIT_SECTION
/* Run all the global constructors on entry to the program. */
#ifndef ON_EXIT
@@ -2128,9 +3013,9 @@ __do_global_ctors ()
DO_GLOBAL_CTORS_BODY;
ON_EXIT (__do_global_dtors, 0);
}
-#endif /* no INIT_SECTION_ASM_OP */
+#endif /* no HAS_INIT_SECTION */
-#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
+#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
/* Subroutine called automatically by `main'.
Compiling a global function named `main'
produces an automatic call to this function at the beginning.
@@ -2150,7 +3035,7 @@ SYMBOL__MAIN ()
__do_global_ctors ();
}
}
-#endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
+#endif /* no HAS_INIT_SECTION or INVOKE__main */
#endif /* L__main */
@@ -2181,22 +3066,76 @@ func_ptr __DTOR_LIST__[2];
#include "gbl-ctors.h"
+#ifdef NEED_ATEXIT
+# ifdef ON_EXIT
+# undef ON_EXIT
+# endif
+int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
+#endif
+
#ifndef ON_EXIT
+#ifdef NEED_ATEXIT
+# include <errno.h>
+
+static func_ptr *atexit_chain = 0;
+static long atexit_chain_length = 0;
+static volatile long last_atexit_chain_slot = -1;
+
+int atexit (func_ptr func)
+{
+ if (++last_atexit_chain_slot == atexit_chain_length)
+ {
+ atexit_chain_length += 32;
+ if (atexit_chain)
+ atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
+ * sizeof (func_ptr));
+ else
+ atexit_chain = (func_ptr *) malloc (atexit_chain_length
+ * sizeof (func_ptr));
+ if (! atexit_chain)
+ {
+ atexit_chain_length = 0;
+ last_atexit_chain_slot = -1;
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+ atexit_chain[last_atexit_chain_slot] = func;
+ return (0);
+}
+#endif /* NEED_ATEXIT */
+
/* If we have no known way of registering our own __do_global_dtors
routine so that it will be invoked at program exit time, then we
have to define our own exit routine which will get this to happen. */
extern void __do_global_dtors ();
+extern void __bb_exit_func ();
extern void _cleanup ();
extern void _exit () __attribute__ ((noreturn));
void
-exit (status)
- int status;
+exit (int status)
{
#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
+#ifdef NEED_ATEXIT
+ if (atexit_chain)
+ {
+ for ( ; last_atexit_chain_slot-- >= 0; )
+ {
+ (*atexit_chain[last_atexit_chain_slot + 1]) ();
+ atexit_chain[last_atexit_chain_slot + 1] = 0;
+ }
+ free (atexit_chain);
+ atexit_chain = 0;
+ }
+#else /* No NEED_ATEXIT */
__do_global_dtors ();
+#endif /* No NEED_ATEXIT */
+#endif
+#ifndef inhibit_libc
+ __bb_exit_func ();
#endif
#ifdef EXIT_BODY
EXIT_BODY;
@@ -2213,149 +3152,308 @@ int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
#endif /* L_exit */
#ifdef L_eh
-typedef struct {
- void *start;
- void *end;
- void *exception_handler;
-} exception_table;
-struct exception_table_node {
- exception_table *table;
- void *start;
- void *end;
- struct exception_table_node *next;
-};
+/* Shared exception handling support routines. */
-static int except_table_pos;
-static void *except_pc;
-static struct exception_table_node *exception_table_list;
+/* Language-specific information about the active exception(s). If there
+ are no active exceptions, it is set to 0. */
+void *__eh_info;
-static exception_table *
-find_exception_table (pc)
- void* pc;
+void
+__default_terminate ()
{
- register struct exception_table_node *table = exception_table_list;
- for ( ; table != 0; table = table->next)
- {
- if (table->start <= pc && table->end > pc)
- return table->table;
- }
- return 0;
+ abort ();
}
-/* this routine takes a pc, and the address of the exception handler associated
- with the closest exception table handler entry associated with that PC,
- or 0 if there are no table entries the PC fits in. The algorithm works
- something like this:
-
- while(current_entry exists) {
- if(current_entry.start < pc )
- current_entry = next_entry;
- else {
- if(prev_entry.start <= pc && prev_entry.end > pc) {
- save pointer to prev_entry;
- return prev_entry.exception_handler;
- }
- else return 0;
- }
- }
- return 0;
-
- Assuming a correctly sorted table (ascending order) this routine should
- return the tightest match...
-
- In the advent of a tie, we have to give the last entry, as it represents
- an inner block.
- */
+void (*__terminate_func)() = __default_terminate;
+void
+__terminate ()
+{
+ (*__terminate_func)();
+}
void *
-__find_first_exception_table_match(pc)
-void *pc;
-{
- exception_table *table = find_exception_table (pc);
- int pos = 0;
- int best = 0;
- if (table == 0)
- return (void*)0;
+__throw_type_match (void *catch_type, void *throw_type, void *obj)
+{
#if 0
- printf("find_first_exception_table_match(): pc = %x!\n",pc);
+ printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
+ catch_type, throw_type);
#endif
+ if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
+ return obj;
+ return 0;
+}
- except_pc = pc;
+void
+__empty ()
+{
+}
+
+/* Support routines for setjmp/longjmp exception handling. */
-#if 0
- /* We can't do this yet, as we don't know that the table is sorted. */
- do {
- ++pos;
- if (table[pos].start > except_pc)
- /* found the first table[pos].start > except_pc, so the previous
- entry better be the one we want! */
- break;
- } while(table[pos].exception_handler != (void*)-1);
-
- --pos;
- if (table[pos].start <= except_pc && table[pos].end > except_pc)
+/* Calls to __sjthrow are generated by the compiler when an exception
+ is raised when using the setjmp/longjmp exception handling codegen
+ method. */
+
+extern void longjmp (void *, int);
+
+static void *top_elt[2];
+void **__dynamic_handler_chain = top_elt;
+
+/* Routine to get the head of the current thread's dynamic handler chain
+ use for exception handling.
+
+ TODO: make thread safe. */
+
+void ***
+__get_dynamic_handler_chain ()
+{
+ return &__dynamic_handler_chain;
+}
+
+/* This is used to throw an exception when the setjmp/longjmp codegen
+ method is used for exception handling.
+
+ We call __terminate if there are no handlers left (we know this
+ when the dynamic handler chain is top_elt). Otherwise we run the
+ cleanup actions off the dynamic cleanup stack, and pop the top of
+ the dynamic handler chain, and use longjmp to transfer back to the
+ associated handler. */
+
+void
+__sjthrow ()
+{
+ void ***dhc = __get_dynamic_handler_chain ();
+ void *jmpbuf;
+ void (*func)(void *, int);
+ void *arg;
+ void ***cleanup;
+
+ /* The cleanup chain is one word into the buffer. Get the cleanup
+ chain. */
+ cleanup = (void***)&(*dhc)[1];
+
+ /* If there are any cleanups in the chain, run them now. */
+ if (cleanup[0])
{
- except_table_pos = pos;
-#if 0
- printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
+ double store[200];
+ void **buf = (void**)store;
+ buf[1] = 0;
+ buf[0] = (*dhc);
+
+ /* try { */
+#ifdef DONT_USE_BUILTIN_SETJMP
+ if (! setjmp (&buf[2]))
+#else
+ if (! __builtin_setjmp (&buf[2]))
#endif
- return table[pos].exception_handler;
+ {
+ *dhc = buf;
+ while (cleanup[0])
+ {
+ func = (void(*)(void*, int))cleanup[0][1];
+ arg = (void*)cleanup[0][2];
+
+ /* Update this before running the cleanup. */
+ cleanup[0] = (void **)cleanup[0][0];
+
+ (*func)(arg, 2);
+ }
+ *dhc = buf[0];
+ }
+ /* catch (...) */
+ else
+ {
+ __terminate ();
+ }
}
+
+ /* We must call terminate if we try and rethrow an exception, when
+ there is no exception currently active and when there are no
+ handlers left. */
+ if (! __eh_info || (*dhc) == top_elt)
+ __terminate ();
+
+ /* Find the jmpbuf associated with the top element of the dynamic
+ handler chain. The jumpbuf starts two words into the buffer. */
+ jmpbuf = &(*dhc)[2];
+
+ /* Then we pop the top element off the dynamic handler chain. */
+ *dhc = (void**)(*dhc)[0];
+
+ /* And then we jump to the handler. */
+
+#ifdef DONT_USE_BUILTIN_SETJMP
+ longjmp (jmpbuf, 1);
#else
- while (table[++pos].exception_handler != (void*)-1) {
- if (table[pos].start <= except_pc && table[pos].end > except_pc)
- {
- /* This can apply. Make sure it is better or as good as the previous
- best. */
- /* The best one ends first. */
- if (best == 0 || (table[pos].end <= table[best].end
- /* The best one starts last. */
- && table[pos].start >= table[best].start))
- best = pos;
- }
- }
- if (best != 0)
- return table[best].exception_handler;
+ __builtin_longjmp (jmpbuf, 1);
#endif
+}
-#if 0
- printf("find_first_eh_table_match(): else: returning NULL!\n");
+/* Run cleanups on the dynamic cleanup stack for the current dynamic
+ handler, then pop the handler off the dynamic handler stack, and
+ then throw. This is used to skip the first handler, and transfer
+ control to the next handler in the dynamic handler stack. */
+
+void
+__sjpopnthrow ()
+{
+ void ***dhc = __get_dynamic_handler_chain ();
+ void *jmpbuf;
+ void (*func)(void *, int);
+ void *arg;
+ void ***cleanup;
+
+ /* The cleanup chain is one word into the buffer. Get the cleanup
+ chain. */
+ cleanup = (void***)&(*dhc)[1];
+
+ /* If there are any cleanups in the chain, run them now. */
+ if (cleanup[0])
+ {
+ double store[200];
+ void **buf = (void**)store;
+ buf[1] = 0;
+ buf[0] = (*dhc);
+
+ /* try { */
+#ifdef DONT_USE_BUILTIN_SETJMP
+ if (! setjmp (&buf[2]))
+#else
+ if (! __builtin_setjmp (&buf[2]))
#endif
- return (void*)0;
+ {
+ *dhc = buf;
+ while (cleanup[0])
+ {
+ func = (void(*)(void*, int))cleanup[0][1];
+ arg = (void*)cleanup[0][2];
+
+ /* Update this before running the cleanup. */
+ cleanup[0] = (void **)cleanup[0][0];
+
+ (*func)(arg, 2);
+ }
+ *dhc = buf[0];
+ }
+ /* catch (...) */
+ else
+ {
+ __terminate ();
+ }
+ }
+
+ /* Then we pop the top element off the dynamic handler chain. */
+ *dhc = (void**)(*dhc)[0];
+
+ __sjthrow ();
+}
+
+/* Support code for all exception region-based exception handling. */
+
+/* This value identifies the place from which an exception is being
+ thrown. */
+
+void *__eh_pc;
+
+#ifdef EH_TABLE_LOOKUP
+
+EH_TABLE_LOOKUP
+
+#else
+
+typedef struct exception_table {
+ void *start;
+ void *end;
+ void *exception_handler;
+} exception_table;
+
+/* This routine takes a PC and a pointer to the exception region TABLE for
+ its translation unit, and returns the address of the exception handler
+ associated with the closest exception table handler entry associated
+ with that PC, or 0 if there are no table entries the PC fits in.
+
+ In the advent of a tie, we have to give the last entry, as it represents
+ an inner block. */
+
+static void *
+find_exception_handler (void *pc, exception_table *table)
+{
+ if (table)
+ {
+ int pos;
+ int best = -1;
+
+ /* We can't do a binary search because the table isn't guaranteed
+ to be sorted from function to function. */
+ for (pos = 0; table[pos].exception_handler != (void *) -1; ++pos)
+ {
+ if (table[pos].start <= pc && table[pos].end > pc)
+ {
+ /* This can apply. Make sure it is at least as small as
+ the previous best. */
+ if (best == -1 || (table[pos].end <= table[best].end
+ && table[pos].start >= table[best].start))
+ best = pos;
+ }
+ /* But it is sorted by starting PC within a function. */
+ else if (best >= 0 && table[pos].start > pc)
+ break;
+ }
+ if (best != -1)
+ return table[best].exception_handler;
+ }
+
+ return (void *) 0;
}
+#endif /* EH_TABLE_LOOKUP */
+
+#ifndef DWARF2_UNWIND_INFO
+/* Support code for exception handling using inline unwinders or
+ __unwind_function. */
+
+#ifndef EH_TABLE_LOOKUP
+typedef struct exception_table_node {
+ exception_table *table;
+ void *start;
+ void *end;
+ struct exception_table_node *next;
+} exception_table_node;
+
+static struct exception_table_node *exception_table_list;
void *
-__throw_type_match (void *catch_type, void *throw_type, void* obj)
+__find_first_exception_table_match (void *pc)
{
-#if 0
- printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
- catch_type, throw_type);
-#endif
- if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
- return obj;
- return 0;
+ register exception_table_node *tnp;
+
+ for (tnp = exception_table_list; tnp != 0; tnp = tnp->next)
+ {
+ if (tnp->start <= pc && tnp->end >= pc)
+ return find_exception_handler (pc, tnp->table);
+ }
+
+ return (void *) 0;
}
void
__register_exceptions (exception_table *table)
{
- struct exception_table_node *node;
+ exception_table_node *node;
exception_table *range = table + 1;
- if (range->start == (void*)-1)
+ if (range->start == (void *) -1)
return;
- node = (struct exception_table_node*)
- malloc (sizeof (struct exception_table_node));
+ node = (exception_table_node *) malloc (sizeof (exception_table_node));
node->table = table;
/* This look can be optimized away either if the table
- is sorted, or if we pass in extra parameters. */
+ is sorted, or if we pass in extra parameters. */
node->start = range->start;
node->end = range->end;
- for (range++ ; range->start != (void*)(-1); range++)
+ for (range++ ; range->start != (void *) (-1); range++)
{
if (range->start < node->start)
node->start = range->start;
@@ -2366,6 +3464,27 @@ __register_exceptions (exception_table *table)
node->next = exception_table_list;
exception_table_list = node;
}
+#endif /* !EH_TABLE_LOOKUP */
+
+/* Throw stub routine.
+
+ This is work in progress, but not completed yet. */
+
+void
+__throw ()
+{
+ abort ();
+}
+
+/* See expand_builtin_throw for details. */
+
+void **__eh_pcnthrow () {
+ static void *buf[2] = {
+ &__eh_pc,
+ &__throw
+ };
+ return buf;
+}
#if #machine(i386)
void
@@ -2378,9 +3497,9 @@ __unwind_function(void *ptr)
/* like ret, but stay here */
asm("addl $4,%esp");
- /* Now, undo previous frame. */
+ /* Now, undo previous frame. */
/* This is a test routine, as we have to dynamically probe to find out
- what to pop for certain, this is just a guess. */
+ what to pop for certain, this is just a guess. */
asm("leal -16(%ebp),%esp");
asm("pop %ebx");
asm("pop %esi");
@@ -2391,7 +3510,7 @@ __unwind_function(void *ptr)
asm("movl %ecx,0(%esp)");
asm("ret");
}
-#elif #machine(rs6000)
+#elif #machine(rs6000) && !defined _ARCH_PPC
__unwind_function(void *ptr)
{
asm("mr 31,1");
@@ -2401,13 +3520,13 @@ __unwind_function(void *ptr)
asm("mr 31,1");
asm("l 1,0(1)");
- /* use 31 as a scratch register to restore the link register. */
+ /* use 31 as a scratch register to restore the link register. */
asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
asm("l 31,-4(1)");
asm("# br");
asm("mtctr 3;bctr # b 3");
}
-#elif #machine(powerpc)
+#elif (#machine(rs6000) || #machine(powerpc)) && defined _ARCH_PPC
__unwind_function(void *ptr)
{
asm("mr 31,1");
@@ -2417,7 +3536,7 @@ __unwind_function(void *ptr)
asm("mr 31,1");
asm("lwz 1,0(1)");
- /* use 31 as a scratch register to restore the link register. */
+ /* use 31 as a scratch register to restore the link register. */
asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
asm("lwz 31,-4(1)");
asm("# br");
@@ -2445,7 +3564,323 @@ __unwind_function(void *ptr)
abort ();
}
#endif /* powerpc */
+
+#else /* DWARF2_UNWIND_INFO */
+/* Support code for exception handling using static unwind information. */
+
+#include "frame.h"
+
+/* This type is used in get_reg and put_reg to deal with ABIs where a void*
+ is smaller than a word, such as the Irix 6 n32 ABI. We cast twice to
+ avoid a warning about casting between int and pointer of different
+ sizes. */
+
+typedef int ptr_type __attribute__ ((mode (pointer)));
+
+/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
+ frame called by UDATA or 0. */
+
+static void*
+get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
+{
+ if (udata->saved[reg] == REG_SAVED_OFFSET)
+ return (void *)(ptr_type)
+ *(word_type *)(udata->cfa + udata->reg_or_offset[reg]);
+ else if (udata->saved[reg] == REG_SAVED_REG && sub_udata)
+ return get_reg (udata->reg_or_offset[reg], sub_udata, 0);
+ else
+ abort ();
+}
+
+/* Overwrite the saved value for register REG in frame UDATA with VAL. */
+
+static void
+put_reg (unsigned reg, void *val, frame_state *udata)
+{
+ if (udata->saved[reg] == REG_SAVED_OFFSET)
+ *(word_type *)(udata->cfa + udata->reg_or_offset[reg])
+ = (word_type)(ptr_type) val;
+ else
+ abort ();
+}
+
+/* Copy the saved value for register REG from frame UDATA to frame
+ TARGET_UDATA. Unlike the previous two functions, this can handle
+ registers that are not one word large. */
+
+static void
+copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
+{
+ if (udata->saved[reg] == REG_SAVED_OFFSET
+ && target_udata->saved[reg] == REG_SAVED_OFFSET)
+ memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
+ udata->cfa + udata->reg_or_offset[reg],
+ __builtin_dwarf_reg_size (reg));
+ else
+ abort ();
+}
+
+/* Retrieve the return address for frame UDATA, where SUB_UDATA is a
+ frame called by UDATA or 0. */
+
+static inline void *
+get_return_addr (frame_state *udata, frame_state *sub_udata)
+{
+ return __builtin_extract_return_addr
+ (get_reg (udata->retaddr_column, udata, sub_udata));
+}
+
+/* Overwrite the return address for frame UDATA with VAL. */
+
+static inline void
+put_return_addr (void *val, frame_state *udata)
+{
+ val = __builtin_frob_return_addr (val);
+ put_reg (udata->retaddr_column, val, udata);
+}
+
+/* Given the current frame UDATA and its return address PC, return the
+ information about the calling frame in CALLER_UDATA. */
+
+static void *
+next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
+{
+ caller_udata = __frame_state_for (pc, caller_udata);
+ if (! caller_udata)
+ return 0;
+
+ /* Now go back to our caller's stack frame. If our caller's CFA register
+ was saved in our stack frame, restore it; otherwise, assume the CFA
+ register is SP and restore it to our CFA value. */
+ if (udata->saved[caller_udata->cfa_reg])
+ caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
+ else
+ caller_udata->cfa = udata->cfa;
+ caller_udata->cfa += caller_udata->cfa_offset;
+
+ return caller_udata;
+}
+
+#ifdef INCOMING_REGNO
+/* Is the saved value for register REG in frame UDATA stored in a register
+ window in the previous frame? */
+
+static int
+in_reg_window (int reg, frame_state *udata)
+{
+ if (udata->saved[reg] != REG_SAVED_OFFSET)
+ return 0;
+
+#ifdef STACK_GROWS_DOWNWARD
+ return udata->reg_or_offset[reg] > 0;
+#else
+ return udata->reg_or_offset[reg] < 0;
+#endif
+}
+#endif /* INCOMING_REGNO */
+
+/* We first search for an exception handler, and if we don't find
+ it, we call __terminate on the current stack frame so that we may
+ use the debugger to walk the stack and understand why no handler
+ was found.
+
+ If we find one, then we unwind the frames down to the one that
+ has the handler and transfer control into the handler. */
+
+void
+__throw ()
+{
+ void *pc, *handler, *retaddr;
+ frame_state ustruct, ustruct2;
+ frame_state *udata = &ustruct;
+ frame_state *sub_udata = &ustruct2;
+ frame_state my_ustruct, *my_udata = &my_ustruct;
+ long args_size;
+
+ /* This is required for C++ semantics. We must call terminate if we
+ try and rethrow an exception, when there is no exception currently
+ active. */
+ if (! __eh_info)
+ __terminate ();
+
+ /* Start at our stack frame. */
+label:
+ udata = __frame_state_for (&&label, udata);
+ if (! udata)
+ __terminate ();
+
+ /* We need to get the value from the CFA register. At this point in
+ compiling __throw we don't know whether or not we will use the frame
+ pointer register for the CFA, so we check our unwind info. */
+ if (udata->cfa_reg == __builtin_dwarf_fp_regnum ())
+ udata->cfa = __builtin_fp ();
+ else
+ udata->cfa = __builtin_sp ();
+ udata->cfa += udata->cfa_offset;
+
+ memcpy (my_udata, udata, sizeof (*udata));
+
+ /* Do any necessary initialization to access arbitrary stack frames.
+ On the SPARC, this means flushing the register windows. */
+ __builtin_unwind_init ();
+
+ /* Now reset pc to the right throw point. */
+ pc = __eh_pc;
+
+ handler = 0;
+ for (;;)
+ {
+ frame_state *p = udata;
+ udata = next_stack_level (pc, udata, sub_udata);
+ sub_udata = p;
+
+ /* If we couldn't find the next frame, we lose. */
+ if (! udata)
+ break;
+
+ handler = find_exception_handler (pc, udata->eh_ptr);
+
+ /* If we found one, we can stop searching. */
+ if (handler)
+ {
+ args_size = udata->args_size;
+ break;
+ }
+
+ /* Otherwise, we continue searching. We subtract 1 from PC to avoid
+ hitting the beginning of the next region. */
+ pc = get_return_addr (udata, sub_udata) - 1;
+ }
+
+ /* If we haven't found a handler by now, this is an unhandled
+ exception. */
+ if (! handler)
+ __terminate ();
+
+ if (pc == __eh_pc)
+ /* We found a handler in the throw context, no need to unwind. */
+ udata = my_udata;
+ else
+ {
+ int i;
+ void *val;
+
+ /* Unwind all the frames between this one and the handler by copying
+ their saved register values into our register save slots. */
+
+ /* Remember the PC where we found the handler. */
+ void *handler_pc = pc;
+
+ /* Start from the throw context again. */
+ pc = __eh_pc;
+ memcpy (udata, my_udata, sizeof (*udata));
+
+ while (pc != handler_pc)
+ {
+ frame_state *p = udata;
+ udata = next_stack_level (pc, udata, sub_udata);
+ sub_udata = p;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+ if (i != udata->retaddr_column && udata->saved[i])
+ {
+#ifdef INCOMING_REGNO
+ /* If you modify the saved value of the return address
+ register on the SPARC, you modify the return address for
+ your caller's frame. Don't do that here, as it will
+ confuse get_return_addr. */
+ if (in_reg_window (i, udata)
+ && udata->saved[udata->retaddr_column] == REG_SAVED_REG
+ && udata->reg_or_offset[udata->retaddr_column] == i)
+ continue;
+#endif
+ copy_reg (i, udata, my_udata);
+ }
+
+ pc = get_return_addr (udata, sub_udata) - 1;
+ }
+
+#ifdef INCOMING_REGNO
+ /* But we do need to update the saved return address register from
+ the last frame we unwind, or the handler frame will have the wrong
+ return address. */
+ if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
+ {
+ i = udata->reg_or_offset[udata->retaddr_column];
+ if (in_reg_window (i, udata))
+ copy_reg (i, udata, my_udata);
+ }
+#endif
+ }
+ /* udata now refers to the frame called by the handler frame. */
+
+ /* Emit the stub to adjust sp and jump to the handler. */
+ retaddr = __builtin_eh_stub ();
+
+ /* And then set our return address to point to the stub. */
+ if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET)
+ put_return_addr (retaddr, my_udata);
+ else
+ __builtin_set_return_addr_reg (retaddr);
+
+ /* Set up the registers we use to communicate with the stub.
+ We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack. */
+ __builtin_set_eh_regs (handler,
+#ifdef STACK_GROWS_DOWNWARD
+ udata->cfa - my_udata->cfa
+#else
+ my_udata->cfa - udata->cfa
+#endif
+ + args_size
+ );
+
+ /* Epilogue: restore the handler frame's register values and return
+ to the stub. */
+}
+#endif /* !DWARF2_UNWIND_INFO */
+
#endif /* L_eh */
+
+#ifdef L_eh_compat
+
+/* This is needed to provide the old names of the frame info registering
+ code for compatibility. It should be deleted in GCC 2.9.0. */
+
+extern void *malloc ();
+
+struct object {
+ void *pc_begin;
+ void *pc_end;
+ void *fde_begin;
+ void *fde_array;
+ size_t count;
+ struct object *next;
+};
+
+void __register_frame_info (void *, struct object *);
+void __register_frame_info_table (void *, struct object *);
+void __deregister_frame_info (void *);
+
+void
+__register_frame (void *begin)
+{
+ __register_frame_info (begin, malloc (sizeof (struct object)));
+}
+
+void
+__register_frame_table (void *begin)
+{
+ __register_frame_info_table (begin, malloc (sizeof (struct object)));
+}
+
+void
+__deregister_frame (void *begin)
+{
+ /* This leaks the memory malloced above,
+ but that's good enough for backward compatibility purposes. */
+ __deregister_frame_info (begin);
+}
+#endif
#ifdef L_pure
#ifndef inhibit_libc
diff --git a/gnu/usr.bin/gcc/listing b/gnu/usr.bin/gcc/listing
index 08abb1db4ce..dc989f6eaef 100644
--- a/gnu/usr.bin/gcc/listing
+++ b/gnu/usr.bin/gcc/listing
@@ -32,7 +32,7 @@
# mc68030 for Motorola 68030 (Sun-3, ..)
# sparc for SPARC (SUN-4, ..)
# i386 for i386 (Sun i386, ...)
-# i386-linux for i386 (Linux, ...)
+# i386-gnu-linux for i386 (GNU/Linux, ...)
# Guess what kind of objects we are creating and thus what type of assembler
# symbols to look for
@@ -62,7 +62,7 @@ cd $WD
# MYSYS=mc68030
# MYSYS=sparc
# MYSYS=i386
-# MYSYS=i386-linux
+# MYSYS=i386-gnu-linux
# MYSYS=`mach` # this will work on Suns with SunOS > 4.0.0
# MYSYS=elf
# MYSYS=coff
@@ -103,7 +103,7 @@ BEGIN {
line_delimiter = ",";
line_offset = 0;
}
- else if (sys == "mc68020" || sys == "mc68030" || sys == "i386-linux") {
+ else if (sys == "mc68020" || sys == "mc68030" || sys == "i386-gnu-linux") {
line_hint = "^[ \t]*\.stabd.*"
line_field = 3;
line_delimiter = ",";
diff --git a/gnu/usr.bin/gcc/longlong.h b/gnu/usr.bin/gcc/longlong.h
index f824b5fcd88..c3160911eb1 100644
--- a/gnu/usr.bin/gcc/longlong.h
+++ b/gnu/usr.bin/gcc/longlong.h
@@ -1,5 +1,5 @@
/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
- Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 92, 94, 95, 96, 1997 Free Software Foundation, Inc.
This definition file is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public
@@ -91,65 +91,96 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add %1,%4,%5
addc %0,%2,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("sub %1,%4,%5
subc %0,%2,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)))
#define umul_ppmm(xh, xl, m0, m1) \
do { \
USItype __m0 = (m0), __m1 = (m1); \
__asm__ ("multiplu %0,%1,%2" \
- : "=r" ((USItype)(xl)) \
+ : "=r" ((USItype) (xl)) \
: "r" (__m0), \
"r" (__m1)); \
__asm__ ("multmu %0,%1,%2" \
- : "=r" ((USItype)(xh)) \
+ : "=r" ((USItype) (xh)) \
: "r" (__m0), \
"r" (__m1)); \
} while (0)
#define udiv_qrnnd(q, r, n1, n0, d) \
__asm__ ("dividu %0,%3,%4" \
- : "=r" ((USItype)(q)), \
- "=q" ((USItype)(r)) \
- : "1" ((USItype)(n1)), \
- "r" ((USItype)(n0)), \
- "r" ((USItype)(d)))
+ : "=r" ((USItype) (q)), \
+ "=q" ((USItype) (r)) \
+ : "1" ((USItype) (n1)), \
+ "r" ((USItype) (n0)), \
+ "r" ((USItype) (d)))
#define count_leading_zeros(count, x) \
__asm__ ("clz %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x)))
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x)))
#endif /* __a29k__ */
+#if defined (__arc__)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ __asm__ ("add.f %1, %4, %5
+ adc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "rIJ" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rIJ" ((USItype) (bl)))
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ __asm__ ("sub.f %1, %4, %5
+ sbc %0, %2, %3" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rIJ" ((USItype) (bh)), \
+ "r" ((USItype) (al)), \
+ "rIJ" ((USItype) (bl)))
+/* Call libgcc1 routine. */
+#define umul_ppmm(w1, w0, u, v) \
+do { \
+ DIunion __w; \
+ __w.ll = __umulsidi3 (u, v); \
+ w1 = __w.s.high; \
+ w0 = __w.s.low; \
+} while (0)
+#define __umulsidi3 __umulsidi3
+UDItype __umulsidi3 (USItype, USItype);
+#endif
+
#if defined (__arm__)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("adds %1, %4, %5
adc %0, %2, %3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subs %1, %4, %5
sbc %0, %2, %3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "r" ((USItype)(al)), \
- "rI" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "r" ((USItype) (al)), \
+ "rI" ((USItype) (bl)))
#define umul_ppmm(xh, xl, a, b) \
{register USItype __t0, __t1, __t2; \
__asm__ ("%@ Inlined umul_ppmm
@@ -165,11 +196,11 @@
addcs %0, %0, #65536
adds %1, %1, %3, lsl #16
adc %0, %0, %3, lsr #16" \
- : "=&r" ((USItype)(xh)), \
- "=r" ((USItype)(xl)), \
+ : "=&r" ((USItype) (xh)), \
+ "=r" ((USItype) (xl)), \
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
- : "r" ((USItype)(a)), \
- "r" ((USItype)(b)));}
+ : "r" ((USItype) (a)), \
+ "r" ((USItype) (b)));}
#define UMUL_TIME 20
#define UDIV_TIME 100
#endif /* __arm__ */
@@ -181,8 +212,8 @@
} __xx; \
__asm__ ("mulwux %2,%0" \
: "=r" (__xx.__ll) \
- : "%0" ((USItype)(u)), \
- "r" ((USItype)(v))); \
+ : "%0" ((USItype) (u)), \
+ "r" ((USItype) (v))); \
(w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
#define smul_ppmm(w1, w0, u, v) \
({union {DItype __ll; \
@@ -190,15 +221,15 @@
} __xx; \
__asm__ ("mulwx %2,%0" \
: "=r" (__xx.__ll) \
- : "%0" ((SItype)(u)), \
- "r" ((SItype)(v))); \
+ : "%0" ((SItype) (u)), \
+ "r" ((SItype) (v))); \
(w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
#define __umulsidi3(u, v) \
({UDItype __w; \
__asm__ ("mulwux %2,%0" \
: "=r" (__w) \
- : "%0" ((USItype)(u)), \
- "r" ((USItype)(v))); \
+ : "%0" ((USItype) (u)), \
+ "r" ((USItype) (v))); \
__w; })
#endif /* __clipper__ */
@@ -206,60 +237,60 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add.w %5,%1
addx %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=g" ((USItype) (sh)), \
+ "=&g" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("sub.w %5,%1
subx %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=g" ((USItype) (sh)), \
+ "=&g" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define umul_ppmm(ph, pl, m0, m1) \
__asm__ ("mulx %3,%0,%1" \
- : "=g" ((USItype)(ph)), \
- "=r" ((USItype)(pl)) \
- : "%0" ((USItype)(m0)), \
- "g" ((USItype)(m1)))
+ : "=g" ((USItype) (ph)), \
+ "=r" ((USItype) (pl)) \
+ : "%0" ((USItype) (m0)), \
+ "g" ((USItype) (m1)))
#define udiv_qrnnd(q, r, nh, nl, d) \
__asm__ ("divx %4,%0,%1" \
- : "=g" ((USItype)(q)), \
- "=r" ((USItype)(r)) \
- : "1" ((USItype)(nh)), \
- "0" ((USItype)(nl)), \
- "g" ((USItype)(d)))
+ : "=g" ((USItype) (q)), \
+ "=r" ((USItype) (r)) \
+ : "1" ((USItype) (nh)), \
+ "0" ((USItype) (nl)), \
+ "g" ((USItype) (d)))
#define count_leading_zeros(count, x) \
__asm__ ("bsch/1 %1,%0" \
: "=g" (count) \
- : "g" ((USItype)(x)), \
- "0" ((USItype)0))
+ : "g" ((USItype) (x)), \
+ "0" ((USItype) 0))
#endif
#if defined (__hppa)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add %4,%5,%1
addc %2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%rM" ((USItype)(ah)), \
- "rM" ((USItype)(bh)), \
- "%rM" ((USItype)(al)), \
- "rM" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%rM" ((USItype) (ah)), \
+ "rM" ((USItype) (bh)), \
+ "%rM" ((USItype) (al)), \
+ "rM" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("sub %4,%5,%1
subb %2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "rM" ((USItype)(ah)), \
- "rM" ((USItype)(bh)), \
- "rM" ((USItype)(al)), \
- "rM" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "rM" ((USItype) (ah)), \
+ "rM" ((USItype) (bh)), \
+ "rM" ((USItype) (al)), \
+ "rM" ((USItype) (bl)))
#if defined (_PA_RISC1_1)
#define umul_ppmm(w1, w0, u, v) \
do { \
@@ -270,8 +301,8 @@
} __t; \
__asm__ ("xmpyu %1,%2,%0" \
: "=x" (__t.__f) \
- : "x" ((USItype)(u)), \
- "x" ((USItype)(v))); \
+ : "x" ((USItype) (u)), \
+ "x" ((USItype) (v))); \
(w1) = __t.__w1w0.__w1; \
(w0) = __t.__w1w0.__w0; \
} while (0)
@@ -307,39 +338,39 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("addl %5,%1
adcl %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subl %5,%1
sbbl %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("mull %3" \
- : "=a" ((USItype)(w0)), \
- "=d" ((USItype)(w1)) \
- : "%0" ((USItype)(u)), \
- "rm" ((USItype)(v)))
+ : "=a" ((USItype) (w0)), \
+ "=d" ((USItype) (w1)) \
+ : "%0" ((USItype) (u)), \
+ "rm" ((USItype) (v)))
#define udiv_qrnnd(q, r, n1, n0, d) \
__asm__ ("divl %4" \
- : "=a" ((USItype)(q)), \
- "=d" ((USItype)(r)) \
- : "0" ((USItype)(n0)), \
- "1" ((USItype)(n1)), \
- "rm" ((USItype)(d)))
+ : "=a" ((USItype) (q)), \
+ "=d" ((USItype) (r)) \
+ : "0" ((USItype) (n0)), \
+ "1" ((USItype) (n1)), \
+ "rm" ((USItype) (d)))
#define count_leading_zeros(count, x) \
do { \
USItype __cbtmp; \
__asm__ ("bsrl %1,%0" \
- : "=r" (__cbtmp) : "rm" ((USItype)(x))); \
+ : "=r" (__cbtmp) : "rm" ((USItype) (x))); \
(count) = __cbtmp ^ 31; \
} while (0)
#define UMUL_TIME 40
@@ -394,65 +425,96 @@
} __xx; \
__asm__ ("emul %2,%1,%0" \
: "=d" (__xx.__ll) \
- : "%dI" ((USItype)(u)), \
- "dI" ((USItype)(v))); \
+ : "%dI" ((USItype) (u)), \
+ "dI" ((USItype) (v))); \
(w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
#define __umulsidi3(u, v) \
({UDItype __w; \
__asm__ ("emul %2,%1,%0" \
: "=d" (__w) \
- : "%dI" ((USItype)(u)), \
- "dI" ((USItype)(v))); \
+ : "%dI" ((USItype) (u)), \
+ "dI" ((USItype) (v))); \
__w; })
#endif /* __i960__ */
+#if defined (__M32R__)
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
+ /* The cmp clears the condition bit. */ \
+ __asm__ ("cmp %0,%0
+ addx %%5,%1
+ addx %%3,%0" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "r" ((USItype) (bl)) \
+ : "cbit")
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
+ /* The cmp clears the condition bit. */ \
+ __asm__ ("cmp %0,%0
+ subx %5,%1
+ subx %3,%0" \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "r" ((USItype) (bl)) \
+ : "cbit")
+#endif /* __M32R__ */
+
#if defined (__mc68000__)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("add%.l %5,%1
addx%.l %3,%0" \
- : "=d" ((USItype)(sh)), \
- "=&d" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "d" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=d" ((USItype) (sh)), \
+ "=&d" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "d" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("sub%.l %5,%1
subx%.l %3,%0" \
- : "=d" ((USItype)(sh)), \
- "=&d" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "d" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
-#if defined (__mc68020__) || defined (__NeXT__) || defined(mc68020)
+ : "=d" ((USItype) (sh)), \
+ "=&d" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "d" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
+
+/* The '020, '030, '040 and CPU32 have 32x32->64 and 64/32->32q-32r. */
+#if defined (__mc68020__) || defined(mc68020) \
+ || defined(__mc68030__) || defined(mc68030) \
+ || defined(__mc68040__) || defined(mc68040) \
+ || defined(__mc68332__) || defined(mc68332) \
+ || defined(__NeXT__)
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("mulu%.l %3,%1:%0" \
- : "=d" ((USItype)(w0)), \
- "=d" ((USItype)(w1)) \
- : "%0" ((USItype)(u)), \
- "dmi" ((USItype)(v)))
+ : "=d" ((USItype) (w0)), \
+ "=d" ((USItype) (w1)) \
+ : "%0" ((USItype) (u)), \
+ "dmi" ((USItype) (v)))
#define UMUL_TIME 45
#define udiv_qrnnd(q, r, n1, n0, d) \
__asm__ ("divu%.l %4,%1:%0" \
- : "=d" ((USItype)(q)), \
- "=d" ((USItype)(r)) \
- : "0" ((USItype)(n0)), \
- "1" ((USItype)(n1)), \
- "dmi" ((USItype)(d)))
+ : "=d" ((USItype) (q)), \
+ "=d" ((USItype) (r)) \
+ : "0" ((USItype) (n0)), \
+ "1" ((USItype) (n1)), \
+ "dmi" ((USItype) (d)))
#define UDIV_TIME 90
#define sdiv_qrnnd(q, r, n1, n0, d) \
__asm__ ("divs%.l %4,%1:%0" \
- : "=d" ((USItype)(q)), \
- "=d" ((USItype)(r)) \
- : "0" ((USItype)(n0)), \
- "1" ((USItype)(n1)), \
- "dmi" ((USItype)(d)))
-#define count_leading_zeros(count, x) \
- __asm__ ("bfffo %1{%b2:%b2},%0" \
- : "=d" ((USItype)(count)) \
- : "od" ((USItype)(x)), "n" (0))
+ : "=d" ((USItype) (q)), \
+ "=d" ((USItype) (r)) \
+ : "0" ((USItype) (n0)), \
+ "1" ((USItype) (n1)), \
+ "dmi" ((USItype) (d)))
+
#else /* not mc68020 */
+#if !defined(__mcf5200__)
/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */
#define umul_ppmm(xh, xl, a, b) \
__asm__ ("| Inlined umul_ppmm
@@ -481,41 +543,54 @@
move%.l %/d2,%1
add%.l %/d1,%/d0
move%.l %/d0,%0" \
- : "=g" ((USItype)(xh)), \
- "=g" ((USItype)(xl)) \
- : "g" ((USItype)(a)), \
- "g" ((USItype)(b)) \
+ : "=g" ((USItype) (xh)), \
+ "=g" ((USItype) (xl)) \
+ : "g" ((USItype) (a)), \
+ "g" ((USItype) (b)) \
: "d0", "d1", "d2", "d3", "d4")
#define UMUL_TIME 100
#define UDIV_TIME 400
+#endif /* not mcf5200 */
#endif /* not mc68020 */
+
+/* The '020, '030, '040 and '060 have bitfield insns. */
+#if defined (__mc68020__) || defined(mc68020) \
+ || defined(__mc68030__) || defined(mc68030) \
+ || defined(__mc68040__) || defined(mc68040) \
+ || defined(__mc68060__) || defined(mc68060) \
+ || defined(__NeXT__)
+#define count_leading_zeros(count, x) \
+ __asm__ ("bfffo %1{%b2:%b2},%0" \
+ : "=d" ((USItype) (count)) \
+ : "od" ((USItype) (x)), "n" (0))
+#endif
#endif /* mc68000 */
#if defined (__m88000__)
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("addu.co %1,%r4,%r5
addu.ci %0,%r2,%r3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%rJ" ((USItype)(ah)), \
- "rJ" ((USItype)(bh)), \
- "%rJ" ((USItype)(al)), \
- "rJ" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%rJ" ((USItype) (ah)), \
+ "rJ" ((USItype) (bh)), \
+ "%rJ" ((USItype) (al)), \
+ "rJ" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subu.co %1,%r4,%r5
subu.ci %0,%r2,%r3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "rJ" ((USItype)(ah)), \
- "rJ" ((USItype)(bh)), \
- "rJ" ((USItype)(al)), \
- "rJ" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "rJ" ((USItype) (ah)), \
+ "rJ" ((USItype) (bh)), \
+ "rJ" ((USItype) (al)), \
+ "rJ" ((USItype) (bl)))
#define count_leading_zeros(count, x) \
do { \
USItype __cbtmp; \
__asm__ ("ff1 %0,%1" \
: "=r" (__cbtmp) \
- : "r" ((USItype)(x))); \
+ : "r" ((USItype) (x))); \
(count) = __cbtmp ^ 31; \
} while (0)
#if defined (__mc88110__)
@@ -526,8 +601,8 @@
} __xx; \
__asm__ ("mulu.d %0,%1,%2" \
: "=r" (__xx.__ll) \
- : "r" ((USItype)(u)), \
- "r" ((USItype)(v))); \
+ : "r" ((USItype) (u)), \
+ "r" ((USItype) (v))); \
(wh) = __xx.__i.__h; \
(wl) = __xx.__i.__l; \
} while (0)
@@ -540,7 +615,7 @@
__asm__ ("divu.d %0,%1,%2" \
: "=r" (__q) \
: "r" (__xx.__ll), \
- "r" ((USItype)(d))); \
+ "r" ((USItype) (d))); \
(r) = (n0) - __q * (d); (q) = __q; })
#define UMUL_TIME 5
#define UDIV_TIME 25
@@ -553,10 +628,10 @@
#if defined (__mips__)
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("multu %2,%3" \
- : "=l" ((USItype)(w0)), \
- "=h" ((USItype)(w1)) \
- : "d" ((USItype)(u)), \
- "d" ((USItype)(v)))
+ : "=l" ((USItype) (w0)), \
+ "=h" ((USItype) (w1)) \
+ : "d" ((USItype) (u)), \
+ "d" ((USItype) (v)))
#define UMUL_TIME 10
#define UDIV_TIME 100
#endif /* __mips__ */
@@ -568,15 +643,15 @@
} __xx; \
__asm__ ("meid %2,%0" \
: "=g" (__xx.__ll) \
- : "%0" ((USItype)(u)), \
- "g" ((USItype)(v))); \
+ : "%0" ((USItype) (u)), \
+ "g" ((USItype) (v))); \
(w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
#define __umulsidi3(u, v) \
({UDItype __w; \
__asm__ ("meid %2,%0" \
: "=g" (__w) \
- : "%0" ((USItype)(u)), \
- "g" ((USItype)(v))); \
+ : "%0" ((USItype) (u)), \
+ "g" ((USItype) (v))); \
__w; })
#define udiv_qrnnd(q, r, n1, n0, d) \
({union {UDItype __ll; \
@@ -586,7 +661,7 @@
__asm__ ("deid %2,%0" \
: "=g" (__xx.__ll) \
: "0" (__xx.__ll), \
- "g" ((USItype)(d))); \
+ "g" ((USItype) (d))); \
(r) = __xx.__i.__l; (q) = __xx.__i.__h; })
#endif /* __ns32000__ */
@@ -595,70 +670,70 @@
do { \
if (__builtin_constant_p (bh) && (bh) == 0) \
__asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl))); \
else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
__asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl))); \
else \
__asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%r" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "%r" ((USItype)(al)), \
- "rI" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%r" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "%r" ((USItype) (al)), \
+ "rI" ((USItype) (bl))); \
} while (0)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
do { \
if (__builtin_constant_p (ah) && (ah) == 0) \
__asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(bh)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (bh)), \
+ "rI" ((USItype) (al)), \
+ "r" ((USItype) (bl))); \
else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \
__asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(bh)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (bh)), \
+ "rI" ((USItype) (al)), \
+ "r" ((USItype) (bl))); \
else if (__builtin_constant_p (bh) && (bh) == 0) \
__asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rI" ((USItype) (al)), \
+ "r" ((USItype) (bl))); \
else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \
__asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "rI" ((USItype) (al)), \
+ "r" ((USItype) (bl))); \
else \
__asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "r" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "rI" ((USItype)(al)), \
- "r" ((USItype)(bl))); \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "r" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "rI" ((USItype) (al)), \
+ "r" ((USItype) (bl))); \
} while (0)
#define count_leading_zeros(count, x) \
__asm__ ("{cntlz|cntlzw} %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x)))
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x)))
#if defined (_ARCH_PPC)
#define umul_ppmm(ph, pl, m0, m1) \
do { \
@@ -686,8 +761,8 @@
do { \
USItype __m0 = (m0), __m1 = (m1); \
__asm__ ("mul %0,%2,%3" \
- : "=r" ((USItype)(xh)), \
- "=q" ((USItype)(xl)) \
+ : "=r" ((USItype) (xh)), \
+ "=q" ((USItype) (xl)) \
: "r" (__m0), \
"r" (__m1)); \
(xh) += ((((SItype) __m0 >> 31) & __m1) \
@@ -696,15 +771,15 @@
#define UMUL_TIME 8
#define smul_ppmm(xh, xl, m0, m1) \
__asm__ ("mul %0,%2,%3" \
- : "=r" ((SItype)(xh)), \
- "=q" ((SItype)(xl)) \
+ : "=r" ((SItype) (xh)), \
+ "=q" ((SItype) (xl)) \
: "r" (m0), \
"r" (m1))
#define SMUL_TIME 4
#define sdiv_qrnnd(q, r, nh, nl, d) \
__asm__ ("div %0,%2,%4" \
- : "=r" ((SItype)(q)), "=q" ((SItype)(r)) \
- : "r" ((SItype)(nh)), "1" ((SItype)(nl)), "r" ((SItype)(d)))
+ : "=r" ((SItype) (q)), "=q" ((SItype) (r)) \
+ : "r" ((SItype) (nh)), "1" ((SItype) (nl)), "r" ((SItype) (d)))
#define UDIV_TIME 100
#endif
#endif /* Power architecture variants. */
@@ -713,21 +788,21 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("addw %5,%1
addwc %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subw %5,%1
subwb %3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
/* This insn works on Pyramids with AP, XP, or MI CPUs, but not with SP. */
#define umul_ppmm(w1, w0, u, v) \
({union {UDItype __ll; \
@@ -737,7 +812,7 @@
uemul %2,%0" \
: "=&r" (__xx.__ll) \
: "g" ((USItype) (u)), \
- "g" ((USItype)(v))); \
+ "g" ((USItype) (v))); \
(w1) = __xx.__i.__h; (w0) = __xx.__i.__l;})
#endif /* __pyr__ */
@@ -745,21 +820,21 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("a %1,%5
ae %0,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "r" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "r" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("s %1,%5
se %0,%3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "r" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "r" ((USItype)(bl)))
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "r" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "r" ((USItype) (bl)))
#define umul_ppmm(ph, pl, m0, m1) \
do { \
USItype __m0 = (m0), __m1 = (m1); \
@@ -784,8 +859,8 @@
m r2,%3
cas %0,r2,r0
mfs r10,%1" \
- : "=r" ((USItype)(ph)), \
- "=r" ((USItype)(pl)) \
+ : "=r" ((USItype) (ph)), \
+ "=r" ((USItype) (pl)) \
: "%r" (__m0), \
"r" (__m1) \
: "r2"); \
@@ -798,13 +873,13 @@
do { \
if ((x) >= 0x10000) \
__asm__ ("clz %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x) >> 16)); \
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x) >> 16)); \
else \
{ \
__asm__ ("clz %0,%1" \
- : "=r" ((USItype)(count)) \
- : "r" ((USItype)(x))); \
+ : "=r" ((USItype) (count)) \
+ : "r" ((USItype) (x))); \
(count) += 16; \
} \
} while (0)
@@ -814,47 +889,47 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("addcc %r4,%5,%1
addx %r2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "%rJ" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "%rJ" ((USItype)(al)), \
- "rI" ((USItype)(bl)) \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "%rJ" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "%rJ" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) \
__CLOBBER_CC)
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subcc %r4,%5,%1
subx %r2,%3,%0" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
- : "rJ" ((USItype)(ah)), \
- "rI" ((USItype)(bh)), \
- "rJ" ((USItype)(al)), \
- "rI" ((USItype)(bl)) \
+ : "=r" ((USItype) (sh)), \
+ "=&r" ((USItype) (sl)) \
+ : "rJ" ((USItype) (ah)), \
+ "rI" ((USItype) (bh)), \
+ "rJ" ((USItype) (al)), \
+ "rI" ((USItype) (bl)) \
__CLOBBER_CC)
#if defined (__sparc_v8__)
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("umul %2,%3,%1;rd %%y,%0" \
- : "=r" ((USItype)(w1)), \
- "=r" ((USItype)(w0)) \
- : "r" ((USItype)(u)), \
- "r" ((USItype)(v)))
+ : "=r" ((USItype) (w1)), \
+ "=r" ((USItype) (w0)) \
+ : "r" ((USItype) (u)), \
+ "r" ((USItype) (v)))
#define udiv_qrnnd(q, r, n1, n0, d) \
__asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\
- : "=&r" ((USItype)(q)), \
- "=&r" ((USItype)(r)) \
- : "r" ((USItype)(n1)), \
- "r" ((USItype)(n0)), \
- "r" ((USItype)(d)))
+ : "=&r" ((USItype) (q)), \
+ "=&r" ((USItype) (r)) \
+ : "r" ((USItype) (n1)), \
+ "r" ((USItype) (n0)), \
+ "r" ((USItype) (d)))
#else
#if defined (__sparclite__)
/* This has hardware multiply but not divide. It also has two additional
instructions scan (ffs from high bit) and divscc. */
#define umul_ppmm(w1, w0, u, v) \
__asm__ ("umul %2,%3,%1;rd %%y,%0" \
- : "=r" ((USItype)(w1)), \
- "=r" ((USItype)(w0)) \
- : "r" ((USItype)(u)), \
- "r" ((USItype)(v)))
+ : "=r" ((USItype) (w1)), \
+ "=r" ((USItype) (w0)) \
+ : "r" ((USItype) (u)), \
+ "r" ((USItype) (v)))
#define udiv_qrnnd(q, r, n1, n0, d) \
__asm__ ("! Inlined udiv_qrnnd
wr %%g0,%2,%%y ! Not a delayed write for sparclite
@@ -895,17 +970,17 @@
bl,a 1f
add %1,%4,%1
1: ! End of inline udiv_qrnnd" \
- : "=r" ((USItype)(q)), \
- "=r" ((USItype)(r)) \
- : "r" ((USItype)(n1)), \
- "r" ((USItype)(n0)), \
- "rI" ((USItype)(d)) \
+ : "=r" ((USItype) (q)), \
+ "=r" ((USItype) (r)) \
+ : "r" ((USItype) (n1)), \
+ "r" ((USItype) (n0)), \
+ "rI" ((USItype) (d)) \
: "%g1" __AND_CLOBBER_CC)
#define UDIV_TIME 37
#define count_leading_zeros(count, x) \
__asm__ ("scan %1,0,%0" \
- : "=r" ((USItype)(x)) \
- : "r" ((USItype)(count)))
+ : "=r" ((USItype) (x)) \
+ : "r" ((USItype) (count)))
#else
/* SPARC without integer multiplication and divide instructions.
(i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */
@@ -950,10 +1025,10 @@
mulscc %%g1,0,%%g1
add %%g1,%%g2,%0
rd %%y,%1" \
- : "=r" ((USItype)(w1)), \
- "=r" ((USItype)(w0)) \
- : "%rI" ((USItype)(u)), \
- "r" ((USItype)(v)) \
+ : "=r" ((USItype) (w1)), \
+ "=r" ((USItype) (w0)) \
+ : "%rI" ((USItype) (u)), \
+ "r" ((USItype) (v)) \
: "%g1", "%g2" __AND_CLOBBER_CC)
#define UMUL_TIME 39 /* 39 instructions */
/* It's quite necessary to add this much assembler for the sparc.
@@ -983,11 +1058,11 @@
sub %1,%2,%1
3: xnor %0,0,%0
! End of inline udiv_qrnnd" \
- : "=&r" ((USItype)(q)), \
- "=&r" ((USItype)(r)) \
- : "r" ((USItype)(d)), \
- "1" ((USItype)(n1)), \
- "0" ((USItype)(n0)) : "%g1" __AND_CLOBBER_CC)
+ : "=&r" ((USItype) (q)), \
+ "=&r" ((USItype) (r)) \
+ : "r" ((USItype) (d)), \
+ "1" ((USItype) (n1)), \
+ "0" ((USItype) (n0)) : "%g1" __AND_CLOBBER_CC)
#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */
#endif /* __sparclite__ */
#endif /* __sparc_v8__ */
@@ -997,21 +1072,21 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("addl2 %5,%1
adwc %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "%0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "%1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=g" ((USItype) (sh)), \
+ "=&g" ((USItype) (sl)) \
+ : "%0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "%1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subl2 %5,%1
sbwc %3,%0" \
- : "=g" ((USItype)(sh)), \
- "=&g" ((USItype)(sl)) \
- : "0" ((USItype)(ah)), \
- "g" ((USItype)(bh)), \
- "1" ((USItype)(al)), \
- "g" ((USItype)(bl)))
+ : "=g" ((USItype) (sh)), \
+ "=&g" ((USItype) (sl)) \
+ : "0" ((USItype) (ah)), \
+ "g" ((USItype) (bh)), \
+ "1" ((USItype) (al)), \
+ "g" ((USItype) (bl)))
#define umul_ppmm(xh, xl, m0, m1) \
do { \
union { \
@@ -1161,9 +1236,9 @@ extern const UQItype __clz_tab[];
\
if (SI_TYPE_SIZE <= 32) \
{ \
- __a = __xr < (1<<2*__BITS4) \
- ? (__xr < (1<<__BITS4) ? 0 : __BITS4) \
- : (__xr < (1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
+ __a = __xr < ((USItype)1<<2*__BITS4) \
+ ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
+ : (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
} \
else \
{ \
diff --git a/gnu/usr.bin/gcc/machmode.def b/gnu/usr.bin/gcc/machmode.def
index 625586cd96f..88af09b913e 100644
--- a/gnu/usr.bin/gcc/machmode.def
+++ b/gnu/usr.bin/gcc/machmode.def
@@ -1,6 +1,6 @@
/* This file contains the definitions and documentation for the
machine modes used in the the GNU compiler.
- Copyright (C) 1987, 1992, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1992, 1994, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -84,6 +84,8 @@ DEF_MACHMODE (XFmode, "XF", MODE_FLOAT, 12, 12, TFmode) /* IEEE extended */
DEF_MACHMODE (TFmode, "TF", MODE_FLOAT, 16, 16, VOIDmode)
/* Complex modes. */
+DEF_MACHMODE (QCmode, "QC", MODE_COMPLEX_FLOAT, 2, 1, HCmode)
+DEF_MACHMODE (HCmode, "HC", MODE_COMPLEX_FLOAT, 4, 2, SCmode)
DEF_MACHMODE (SCmode, "SC", MODE_COMPLEX_FLOAT, 8, 4, DCmode)
DEF_MACHMODE (DCmode, "DC", MODE_COMPLEX_FLOAT, 16, 8, XCmode)
DEF_MACHMODE (XCmode, "XC", MODE_COMPLEX_FLOAT, 24, 12, TCmode)
diff --git a/gnu/usr.bin/gcc/machmode.h b/gnu/usr.bin/gcc/machmode.h
index 85b554389cf..f1f146f2ecf 100644
--- a/gnu/usr.bin/gcc/machmode.h
+++ b/gnu/usr.bin/gcc/machmode.h
@@ -1,5 +1,5 @@
/* Machine mode definitions for GNU C-Compiler; included by rtl.h and tree.h.
- Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1994, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,17 +18,10 @@ 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. */
-
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
#ifndef HAVE_MACHINE_MODES
+#define HAVE_MACHINE_MODES
+
+#include "gansidecl.h"
/* Strictly speaking, this isn't the proper place to include these definitions,
but this file is included by every GCC file.
@@ -60,7 +53,72 @@ Boston, MA 02111-1307, USA. */
/* Provide a default way to print an address in hex via printf. */
#ifndef HOST_PTR_PRINTF
-#define HOST_PTR_PRINTF sizeof (int) == sizeof (char *) ? "%x" : "%lx"
+#define HOST_PTR_PRINTF \
+ (sizeof (int) == sizeof (char *) ? "%x" \
+ : sizeof (long) == sizeof (char *) ? "%lx" : "%llx")
+#endif
+
+/* Provide defaults for the way to print a HOST_WIDE_INT
+ in various manners. */
+
+#ifndef HOST_WIDE_INT_PRINT_DEC
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+#define HOST_WIDE_INT_PRINT_DEC "%d"
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+#define HOST_WIDE_INT_PRINT_DEC "%ld"
+#else
+#define HOST_WIDE_INT_PRINT_DEC "%lld"
+#endif
+#endif
+#endif
+
+#ifndef HOST_WIDE_INT_PRINT_UNSIGNED
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+#define HOST_WIDE_INT_PRINT_UNSIGNED "%u"
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+#define HOST_WIDE_INT_PRINT_UNSIGNED "%lu"
+#else
+#define HOST_WIDE_INT_PRINT_UNSIGNED "%llu"
+#endif
+#endif
+#endif
+
+#ifndef HOST_WIDE_INT_PRINT_HEX
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+#define HOST_WIDE_INT_PRINT_HEX "0x%x"
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+#define HOST_WIDE_INT_PRINT_HEX "0x%lx"
+#else
+#define HOST_WIDE_INT_PRINT_HEX "0x%llx"
+#endif
+#endif
+#endif
+
+#ifndef HOST_WIDE_INT_PRINT_DOUBLE_HEX
+#if HOST_BITS_PER_WIDE_INT == 64
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%016x"
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%016lx"
+#else
+#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%016llx"
+#endif
+#endif
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%x%08x"
+#else
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
+#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%lx%08lx"
+#else
+#define HOST_WIDE_INT_PRINT_DOUBLE_HEX "0x%llx%08llx"
+#endif
+#endif
+#endif
#endif
/* Make an enum class that gives all the machine modes. */
@@ -77,8 +135,6 @@ MAX_MACHINE_MODE };
#undef DEF_MACHMODE
-#define HAVE_MACHINE_MODES
-
#ifndef NUM_MACHINE_MODES
#define NUM_MACHINE_MODES (int) MAX_MACHINE_MODE
#endif
@@ -86,7 +142,7 @@ MAX_MACHINE_MODE };
/* Get the name of mode MODE as a string. */
extern char *mode_name[];
-#define GET_MODE_NAME(MODE) (mode_name[(int)(MODE)])
+#define GET_MODE_NAME(MODE) (mode_name[(int) (MODE)])
enum mode_class { MODE_RANDOM, MODE_INT, MODE_FLOAT, MODE_PARTIAL_INT, MODE_CC,
MODE_COMPLEX_INT, MODE_COMPLEX_FLOAT, MAX_MODE_CLASS};
@@ -95,7 +151,7 @@ enum mode_class { MODE_RANDOM, MODE_INT, MODE_FLOAT, MODE_PARTIAL_INT, MODE_CC,
(integer, floating, complex, etc.) */
extern enum mode_class mode_class[];
-#define GET_MODE_CLASS(MODE) (mode_class[(int)(MODE)])
+#define GET_MODE_CLASS(MODE) (mode_class[(int) (MODE)])
/* Nonzero if MODE is an integral mode. */
#define INTEGRAL_MODE_P(MODE) \
@@ -111,12 +167,12 @@ extern enum mode_class mode_class[];
/* Get the size in bytes of an object of mode MODE. */
extern int mode_size[];
-#define GET_MODE_SIZE(MODE) (mode_size[(int)(MODE)])
+#define GET_MODE_SIZE(MODE) (mode_size[(int) (MODE)])
/* Get the size in bytes of the basic parts of an object of mode MODE. */
extern int mode_unit_size[];
-#define GET_MODE_UNIT_SIZE(MODE) (mode_unit_size[(int)(MODE)])
+#define GET_MODE_UNIT_SIZE(MODE) (mode_unit_size[(int) (MODE)])
/* Get the number of units in the object. */
@@ -126,7 +182,7 @@ extern int mode_unit_size[];
/* Get the size in bits of an object of mode MODE. */
-#define GET_MODE_BITSIZE(MODE) (BITS_PER_UNIT * mode_size[(int)(MODE)])
+#define GET_MODE_BITSIZE(MODE) (BITS_PER_UNIT * mode_size[(int) (MODE)])
/* Get a bitmask containing 1 for all bits in a word
that fit within mode MODE. */
@@ -138,7 +194,7 @@ extern int mode_unit_size[];
/* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */
extern enum machine_mode mode_wider_mode[];
-#define GET_MODE_WIDER_MODE(MODE) (mode_wider_mode[(int)(MODE)])
+#define GET_MODE_WIDER_MODE(MODE) (mode_wider_mode[(int) (MODE)])
/* Return the mode for data of a given size SIZE and mode class CLASS.
If LIMIT is nonzero, then don't use modes bigger than MAX_FIXED_MODE_SIZE.
@@ -159,7 +215,7 @@ extern enum machine_mode get_best_mode PROTO((int, int, int, enum machine_mode,
/* For each class, get the narrowest mode in that class. */
extern enum machine_mode class_narrowest_mode[];
-#define GET_CLASS_NARROWEST_MODE(CLASS) class_narrowest_mode[(int)(CLASS)]
+#define GET_CLASS_NARROWEST_MODE(CLASS) class_narrowest_mode[(int) (CLASS)]
/* Define the integer modes whose sizes are BITS_PER_UNIT and BITS_PER_WORD
and the mode whose class is Pmode and whose size is POINTER_SIZE. */
diff --git a/gnu/usr.bin/gcc/make-cc1.com b/gnu/usr.bin/gcc/make-cc1.com
index b98d02efbf1..618fc2a8d33 100644
--- a/gnu/usr.bin/gcc/make-cc1.com
+++ b/gnu/usr.bin/gcc/make-cc1.com
@@ -1,53 +1,83 @@
-$! Set the def dir to proper place for use in batch. Works for interactive too.
-$flnm = f$enviroment("PROCEDURE") ! get current procedure name
-$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$v='f$verify(0) !make-cc1.com
$!
-$ v=f$verify(0)
+$! Build the GNU C compiler on VMS.
$!
-$! CAUTION: If you want to link gcc-cc1 to the sharable image library
-$! VAXCRTL, see the notes in gcc.texinfo (or INSTALL) first.
+$! Usage:
+$! $ @make-cc1.com [host-compiler] [various]
$!
-$! Build the GNU "C" compiler on VMS
+$! where [host-compiler] is one of "GNUC", "VAXC", "DECC";
+$! default when none specified is "GNUC",
+$! and where [various] is one or more of "CC1", "CC1PLUS",
+$! "CC1OBJ", "OBJCLIB", "INDEPENDENT", "BC", "ALL", "LINK", "DEBUG".
+$! "CC1" (C compiler) is the default; of the others, only
+$! "CC1PLUS" (C++ compiler), "CC1OBJ" (Objective-C compiler),
+$! and "OBJCLIB" (Objective-C run-time library) are of interest
+$! for normal installation.
+$! If both [host-compiler] and other option(s) are specified,
+$! the host compiler argument must come first.
$!
-$! Note: to build with DEC's VAX C compiler, uncomment the 2nd CC, CFLAGS,
-$! and LIBS alternatives, and also execute the following command:
-$! DEFINE SYS SYS$LIBRARY:
-$! After a successful build, restore those items and rebuild with gcc.
+$ if f$type(gcc_debug).eqs."INTEGER" then if gcc_debug.and.1 then set verify
+$
+$ p1 = f$edit(p1,"UPCASE,TRIM")
+$ if p1.eqs."" then p1 = "GNUC"
+$!
+$! Compiler-specific setup (assume GNU C, then override as necessary):
+$!
+$ CC = "gcc"
+$ CFLAGS = "/Opt=2/Debug/noVerbos/CC1=""-mpcc-alignment"""
+$ LIBS = "gnu_cc:[000000]gcclib.olb/Libr,sys$library:vaxcrtl.olb/Libr"
+$ if p1.eqs."GNUC"
+$ then
+$ p1 = ""
+$ else
+$ CC = "cc"
+$ CFLAGS = "/noOpt" !disable optimizer when bootstrapping with native cc
+$ if p2.eqs."DEBUG" .or. p3.eqs."DEBUG" then CFLAGS = CFLAGS + "/Debug"
+$ if p1.eqs."VAXC"
+$ then
+$ p1 = ""
+$ if f$trnlnm("DECC$CC_DEFAULT").nes."" then CC = "cc/VAXC"
+$ LIBS = "alloca.obj,sys$library:vaxcrtl.olb/Libr"
+$ define/noLog SYS SYS$LIBRARY:
+$ else
+$ if p1.eqs."DECC"
+$ then
+$ p1 = ""
+$ if f$trnlnm("DECC$CC_DEFAULT").nes."" then CC = "cc/DECC"
+$ CC = CC + "/Prefix=All/Warn=Disabl=(ImplicitFunc)"
+$ LIBS = "alloca.obj" !DECC$SHR will be found implicitly by linker
+$ define/noLog SYS DECC$LIBRARY_INCLUDE:
+$ endif !DECC
+$ endif !VAXC
+$ endif !GNUC
$
-$! C compiler
-$!
-$ CC = "gcc"
-$! CC = "cc" !uncomment for VAXC
-$ BISON = "bison"
-$ BISON_FLAGS= "/Define/Verbose"
-$ RENAME= "rename/New_Version"
-$ LINK = "link"
-$ EDIT = "edit"
-$ SEARCH= "search"
-$ ABORT = "exit %x002C"
-$ echo = "write sys$output"
-$!
-$! Compiler options
-$!
-$ CFLAGS = "/Debug/noVerbos/CC1=""-mpcc-alignment"""
-$! CFLAGS = "/noOpt" !uncomment for VAXC
-$ CINCL1 = "/Incl=[]" !stage 1 -I flags
-$ CINCL2 = "/Incl=([],[.ginclude])" !stage 2,3,... flags
-$ CINCL_SUB = "/Incl=([],[-],[-.ginclude])" ![.cp] flags
$!
-$! Link options
+$! Other setup:
$!
$ LDFLAGS = "/noMap"
+$ PARSER = "bison"
+$ PARSER_FLAGS= "/Define/Verbose"
+$ RENAME = "rename/New_Version"
+$ LINK = "link"
+$ EDIT = "edit"
+$ SEARCH = "search"
+$ ABORT = "exit %x002C"
+$ echo = "write sys$output"
$!
-$! Link libraries
+$! Stage[123] options
$!
-$ LIBS = "gnu_cc:[000000]gcclib.olb/Libr,sys$library:vaxcrtl.olb/Libr"
-$! LIBS = "alloca.obj,sys$library:vaxcrtl.olb/Libr" !uncomment for VAXC
+$ CINCL1 = "/Incl=[]" !stage 1 -I flags
+$ CINCL2 = "/Incl=([],[.ginclude])" !stage 2,3,... flags
+$ CINCL_SUB = "/Incl=([],[-],[-.ginclude])" ![.cp] flags
$
$!!!!!!!
$! Nothing beyond this point should need any local configuration changes.
$!!!!!!!
$
+$! Set the default directory to the same place as this command procedure.
+$ flnm = f$enviroment("PROCEDURE") !get current procedure name
+$ set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$
$!
$! First we figure out what needs to be done. This is sort of like a limited
$! make facility - the command line options specify exactly what components
@@ -70,6 +100,9 @@ $!
$! BC:
$! Compile byte compiler source modules. (On by default).
$!
+$! OBJCLIB:
+$! Compile Objective-C run-time library.
+$!
$! DEBUG: Link images with /debug.
$!
$! If you want to list more than one option, you should use a spaces to
@@ -84,7 +117,7 @@ $! If you do not specify which compiler you want to build, it is assumed that
$! you want to build GNU-C ("CC1").
$!
$! Now figure out what we have been requested to do.
-$p1 = p1+" "+p2+" "+p3+" "+p4+" "+p5+" "+p6+" "+p7
+$p1 = p1+" "+p2+" "+p3+" "+p4+" "+p5+" "+p6+" "+p7+" "+p8
$p1 = f$edit(p1,"COMPRESS,TRIM")
$i=0
$DO_ALL = 0
@@ -207,12 +240,12 @@ $ if f$search("alloca.obj").nes."" then - !does .obj exist? is it up to date?
if f$cvtime(f$file_attributes("alloca.obj","RDT")).gts.-
f$cvtime(f$file_attributes("alloca.c","RDT")) then goto skip_alloca
$set verify
-$ 'CC''CFLAGS'/Define="STACK_DIRECTION=(-1)" alloca.c
+$ 'CC''CFLAGS'/Defi=("HAVE_CONFIG_H","STACK_DIRECTION=(-1)") alloca.c
$!'f$verify(0)
$skip_alloca:
$!
-$if DO_BC.eq.1
-$ THEN
+$if DO_BC.eq.1
+$ then
$ call compile bi_all.opt ""
$ if f$trnlnm("ifile$").nes."" then close/noLog ifile$
$ open ifile$ bc_all.list
@@ -229,8 +262,8 @@ $bc_done:
$ endif
$!
$!
-$if DO_INDEPENDENT.eq.1
-$ THEN
+$if DO_INDEPENDENT.eq.1
+$ then
$!
$! First build a couple of header files from the machine description
$! These are used by many of the source modules, so we build them now.
@@ -262,16 +295,17 @@ $if (f$search("C-PARSE.Y") .eqs. "") then goto yes_yfiles
$if (f$cvtime(f$file_attributes("C-PARSE.IN","RDT")).gts. -
f$cvtime(f$file_attributes("C-PARSE.Y","RDT"))) -
then goto yes_yfiles
-$if (f$search("OBJC-PARSE.Y") .eqs. "") then goto yes_yfiles
+$if f$parse("[.OBJC]").eqs."" then create/Directory [.objc]
+$if (f$search("[.OBJC]OBJC-PARSE.Y") .eqs. "") then goto yes_yfiles
$if (f$cvtime(f$file_attributes("C-PARSE.IN","RDT")).gts. -
- f$cvtime(f$file_attributes("OBJC-PARSE.Y","RDT"))) -
+ f$cvtime(f$file_attributes("[.OBJC]OBJC-PARSE.Y","RDT"))) -
then goto yes_yfiles
$GOTO no_yfiles
$yes_yfiles:
-$echo "Now processing c-parse.in to generate c-parse.y and objc-parse.y."
-$ edit/tpu/nojournal/nosection/nodisplay/command=sys$input
+$echo "Now processing c-parse.in to generate c-parse.y and [.objc]objc-parse.y."
+$ EDIT/Tpu/noJournal/noSection/noDisplay/Command=sys$input:
!
-! Read c-parse.in, write c-parse.y and objc-parse.y, depending on
+! Read c-parse.in, write c-parse.y and objc/objc-parse.y, depending on
! paired lines of "ifc" & "end ifc" and "ifobjc" & "end ifobjc" to
! control what goes into each file. Most lines will be common to
! both (hence not bracketed by either control pair). Mismatched
@@ -311,7 +345,7 @@ $ edit/tpu/nojournal/nosection/nodisplay/command=sys$input
ENDLOOP;
WRITE_FILE(c, "c-parse.y");
- WRITE_FILE(objc, "objc-parse.y");
+ WRITE_FILE(objc, "[.objc]objc-parse.y");
QUIT
$ endif
$no_yfiles:
@@ -415,27 +449,26 @@ $ save_cflags = CFLAGS
$ CFLAGS = CFLAGS - CINCL1 - CINCL2 + CINCL_SUB
$ endif
$!
-$if f$locate("parse",flnm).nes.f$length(flnm)
-$ then
-$ if (f$search("''flnm'.C") .eqs. "") then goto yes_bison
-$ if (f$cvtime(f$file_attributes("''flnm'.Y","RDT")).les. -
- f$cvtime(f$file_attributes("''flnm'.C","RDT"))) -
- then goto no_bison
-$yes_bison:
-$set verify
-$ 'BISON''BISON_FLAGS' 'flnm'.y
-$ 'RENAME' 'flnm'_tab.c 'flnm'.c
-$ 'RENAME' 'flnm'_tab.h 'flnm'.h
+$ if f$locate("parse",flnm).nes.f$length(flnm)
+$ then
+$ if f$search("''flnm'.c").nes."" then -
+ if f$cvtime(f$file_attributes("''flnm'.c","RDT")).ges. -
+ f$cvtime(f$file_attributes("''flnm'.y","RDT")) then goto skip_yacc
+$ set verify
+$ 'PARSER' 'PARSER_FLAGS' 'flnm'.y
+$ 'RENAME' 'flnm'_tab.c 'flnm'.c
+$ 'RENAME' 'flnm'_tab.h 'flnm'.h
$!'f$verify(0)
$ if flnm.eqs."cp-parse" .or. (prfx.eqs."cp" .and. flnm.eqs."parse")
$ then ! fgrep '#define YYEMPTY' cp-parse.c >>cp-parse.h
+$ if f$trnlnm("JFILE$").nes."" then close/noLog jfile$
$ open/Append jfile$ 'flnm'.h
$ 'SEARCH'/Exact/Output=jfile$ 'flnm'.c "#define YYEMPTY"
$ close jfile$
$ endif
-$no_bison:
+$skip_yacc:
$ echo " (Ignore any warning about not finding file ""bison.simple"".)"
-$ endif
+$ endif
$!
$if f$extract(0,5,flnm).eqs."insn-" then call generate 'flnm'.c
$!
@@ -461,7 +494,7 @@ $close ifile$
$endsubroutine
$!
$! This subroutine generates the insn-* files. The first argument is the
-$! name of the insn-* file to generate. The second argument contains a
+$! name of the insn-* file to generate. The second argument contains a
$! list of any other object modules which must be linked to the gen*.c
$! program.
$!
@@ -475,7 +508,7 @@ $ endif
$root1=f$parse(f$extract(5,255,p1),,,"NAME")
$ set verify
$ 'CC''CFLAGS' GEN'root1'.C
-$ 'LINK''LDFLAGS' GEN'root1'.OBJ,rtl.obj,obstack.obj,'p2' -
+$ 'LINK''f$string(LDFLAGS - "/Debug")' GEN'root1'.OBJ,rtl.obj,obstack.obj,'p2' -
'LIBS'
$! 'f$verify(0)
$!
@@ -486,7 +519,7 @@ $!'f$verify(0)
$endsubroutine
$!
$! This subroutine generates the bc-* files. The first argument is the
-$! name of the bc-* file to generate. The second argument contains a
+$! name of the bc-* file to generate. The second argument contains a
$! list of any other object modules which must be linked to the bi*.c
$! program.
$!
@@ -500,7 +533,7 @@ $ endif
$root1=f$parse(f$extract(3,255,p1),,,"NAME")
$ set verify
$ 'CC''CFLAGS' BI-'root1'.C
-$ 'LINK''LDFLAGS' BI-'root1'.OBJ,'p2' -
+$ 'LINK''f$string(LDFLAGS - "/Debug")' BI-'root1'.OBJ,'p2' -
'LIBS'
$! 'f$verify(0)
$!
diff --git a/gnu/usr.bin/gcc/make-cccp.com b/gnu/usr.bin/gcc/make-cccp.com
index d19940a4f28..342c71015a4 100644
--- a/gnu/usr.bin/gcc/make-cccp.com
+++ b/gnu/usr.bin/gcc/make-cccp.com
@@ -1,79 +1,119 @@
-$! Set the def dir to proper place for use in batch. Works for interactive too.
-$flnm = f$enviroment("PROCEDURE") ! get current procedure name
-$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$v='f$verify(0) !make-cccp.com
$!
-$! Build the GNU "C" pre-processor on VMS
+$! Build the GNU C preprocessor on VMS.
$!
-$! Note: to build with DEC's VAX C compiler, uncomment the 2nd CC, CFLAGS,
-$! and LIBS alternatives, and also execute the following command:
-$! DEFINE SYS SYS$LIBRARY:
-$
+$! Usage:
+$! $ @make-cccp.com [compiler] [link-only]
$!
-$! C compiler
+$! where [compiler] is one of "GNUC", "VAXC", "DECC";
+$! default when none specified is "GNUC",
+$! and where [link-only] is "LINK" or omitted.
+$! If both options are specified, the compiler must come first.
$!
-$ CC = "gcc"
-$! CC = "cc" !uncomment for VAXC
-$ BISON = "bison"
-$ RENAME= "rename/New_Version"
-$ LINK = "link"
-$ echo = "write sys$output"
+$ if f$type(gcc_debug).eqs."INTEGER" then if gcc_debug.and.1 then set verify
+$
+$ p1 = f$edit(p1,"UPCASE,TRIM")
+$ if p1.eqs."" then p1 = "GNUC"
$!
-$! Compiler options
+$! Compiler-specific setup (assume GNU C, then override as necessary):
$!
-$ CFLAGS = "/Debug/noVerbos"
-$! CFLAGS = "/noOpt" !uncomment for VAXC
+$ CC = "gcc"
+$ CFLAGS = "/Opt=2/Debug/noVerbos"
+$ LIBS = "gnu_cc:[000000]gcclib.olb/Libr,sys$library:vaxcrtl.olb/Libr"
+$ if p1.nes."GNUC"
+$ then
+$ CC = "cc"
+$ CFLAGS = "/noOpt" !disable optimizer when bootstrapping with native cc
+$ if p1.eqs."VAXC"
+$ then
+$ if f$trnlnm("DECC$CC_DEFAULT").nes."" then CC = "cc/VAXC"
+$ LIBS = "alloca.obj,sys$library:vaxcrtl.olb/Libr"
+$ define/noLog SYS SYS$LIBRARY:
+$ else
+$ if p1.eqs."DECC"
+$ then
+$ if f$trnlnm("DECC$CC_DEFAULT").nes."" then CC = "cc/DECC"
+$ CC = CC + "/Prefix=All"
+$ LIBS = "alloca.obj" !DECC$SHR will be found implicitly by linker
+$ define/noLog SYS DECC$LIBRARY_INCLUDE:
+$ else
+$ if p1.nes."LINK"
+$ then
+$ type sys$input: /Output=sys$error:
+$DECK
+[compiler] argument should be one of "GNUC", "VAXC", or "DECC".
+
+Usage:
+$ @make-cccp.com [compiler] [link-only]
+
+$EOD
+$ exit %x1000002C + 0*f$verify(v) !%SYSTEM-F-ABORT
+$ endif !!LINK
+$ endif !DECC
+$ endif !VAXC
+$ endif !!GNUC
+$
$!
-$! Link options
+$! Other setup:
$!
$ LDFLAGS = "/noMap"
-$!
-$! Link libraries
-$!
-$ LIBS = "gnu_cc:[000000]gcclib.olb/Libr,sys$library:vaxcrtl.olb/Libr"
-$! LIBS = "alloca.obj,sys$library:vaxcrtl.olb/Libr" !uncomment for VAXC
+$ PARSER = "bison"
+$ RENAME = "rename/New_Version"
+$ LINK = "link"
+$ echo = "write sys$output"
$
$!!!!!!!
$! Nothing beyond this point should need any local configuration changes.
$!!!!!!!
$
-$ if "''p1'" .eqs. "LINK" then goto Link
+$! Set the default directory to the same place as this command procedure.
+$ flnm = f$enviroment("PROCEDURE") !get current procedure name
+$ set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$
+$ if p1.eqs."LINK" .or. p2.eqs."LINK" then goto Link
$ echo " Building the preprocessor."
+$
+$! Compile the simplest file first, to catch problem with compiler setup early.
+$ set verify
+$ 'CC''CFLAGS' version.c
+$!'f$verify(0)
+$
$ set verify
$ 'CC''CFLAGS' cccp.c
$!'f$verify(0)
-$ t1:='f$search("CEXP.C")'
-$ if "''t1'" .eqs. "" then goto 10$
-$ t1:='f$file_attributes("CEXP.Y","RDT")'
-$ t1:='f$cvtime(t1)'
-$ t2:='f$file_attributes("CEXP.C","RDT")'
-$ t2:='f$cvtime(t2)'
-$ if t1 .les. t2 then goto 20$
-$10$:
+$
+$! Compile preprocessor's parser, possibly making it with yacc first.
+$ if f$search("CEXP.C").nes."" then -
+ if f$cvtime(f$file_attributes("CEXP.C","RDT")).ges.-
+ f$cvtime(f$file_attributes("CEXP.Y","RDT")) then goto skip_yacc
$ set verify
-$ 'BISON' cexp.y
+$ 'PARSER' cexp.y
$ 'RENAME' cexp_tab.c cexp.c
$!'f$verify(0)
-$20$:
-$!
+$skip_yacc:
+$ echo " (Ignore any warning about not finding file ""bison.simple"".)"
+$ set verify
+$ 'CC''CFLAGS' cexp.c
+$ 'CC''CFLAGS'/Define="PREFIX=""_dummy_""" prefix.c
+$!'f$verify(0)
+$
+$! In case there's no builtin alloca support, use the C simulation.
$ if f$locate("alloca.obj",f$edit(LIBS,"lowercase")).lt.f$length(LIBS)
$ then
$ set verify
-$ 'CC''CFLAGS'/Define="STACK_DIRECTION=(-1)" alloca.c !#'f$verify(1)
+$ 'CC''CFLAGS'/Incl=[]/Defi=("HAVE_CONFIG_H","STACK_DIRECTION=(-1)") alloca.c
$!'f$verify(0)
$ endif
$!
-$ echo " (Ignore any warning about not finding file ""bison.simple"".)"
-$ set verify
-$ 'CC''CFLAGS' cexp.c
-$ 'CC''CFLAGS' version.c
-$!'f$verify(0)
+$
$Link:
$ echo " Linking the preprocessor."
$ set verify
-$ 'LINK''LDFLAGS'/Exe=gcc-cpp.exe cccp.obj,cexp.obj,version.obj,version.opt/Opt,-
+$ 'LINK''LDFLAGS'/Exe=gcc-cpp.exe -
+ cccp.obj,cexp.obj,prefix.obj,version.obj,version.opt/Opt,-
'LIBS'
$!'f$verify(0)
$!
$! Done
$!
-$ exit
+$ exit 1+0*f$verify(v)
diff --git a/gnu/usr.bin/gcc/make-gcc.com b/gnu/usr.bin/gcc/make-gcc.com
index 5bae51939e6..58632eb10c6 100644
--- a/gnu/usr.bin/gcc/make-gcc.com
+++ b/gnu/usr.bin/gcc/make-gcc.com
@@ -1,32 +1,71 @@
+$! make-gcc.com -- VMS build procedure for GNU CC.
$!
-$! Build GCC
+$! Usage:
+$! $ @make-gcc.com [host-compiler] [component list]
$!
-$! Set the def dir to proper place for use in batch. Works for interactive too.
-$flnm = f$enviroment("PROCEDURE") ! get current procedure name
-$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$! where [host-compiler] is one of "GNUC", "VAXC", "DECC";
+$! default when none specified is "GNUC",
+$! and where [component list] is space separated list beginning
+$! with "CC1" and optionally followed by "CC1PLUS"; default if
+$! nothing is specified is "CC1" (the C compiler); choosing
+$! "CC1PLUS" (the C++ compiler) without also specifying "CC1"
+$! will not work. (See make-cc1.com for other potential component
+$! values; but unless you're developing or debugging the compiler
+$! suite itself, the two above are the only ones of interest.)
$!
+$! For a "stage 2" or subsequent build, always specify GNUC as
+$! the host compiler.
$!
-$! First, build the preprocessor.
+$! Note:
+$! Even though it is possible to build with VAX C or DEC C,
+$! a prior version of the gcc-vms binary distribution is still
+$! required to be able to use the newly built GNU CC compiler(s),
+$! because the gcc source distribution does not supply the driver
+$! program which the DCL command "GCC" implements or the C header
+$! files and gcclib support library.
$!
-$ @make-cccp
+$
$!
-$! To build the GNU C++ compiler in addition to the GNU CC compiler, comment
-$! out the `@make-cc1' line, and uncomment the `@make-cc1 cc1 cc1plus' line.
-$! To also build Objective-C, add "cc1obj" to the list.
+$! Change working directory to the location of this procedure.
$!
-$! See the file make-cc1.com for a complete list of options.
+$ flnm = f$enviroment("PROCEDURE") !get current procedure name
+$ set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$
$!
-$ @make-cc1
-$! @make-cc1 cc1 cc1plus
+$! First, we build the preprocessor.
$!
+$ @make-cccp.com 'p1' 'p2'
$!
-$! Now build the library routines that are required. These will be placed in
-$! libgcc2.olb. To install, extract all of the modules from libgcc2.olb and
-$! add them to gnu_cc:[000000]gcclib.olb. You may have to delete the eprintf
-$! and new modules from the gnu_cc:[000000]gcclib.olb, since libgcc2 supplies
-$! these same routines with different module names.
+$! To install it, copy the resulting GCC-CPP.EXE to the GNU_CC:[000000]
+$! directory.
$!
-$! Now build gcclib2.olb
+$
$!
-$ @make-l2
+$! Now we build the C compiler. To build the C++ compiler too, use
+$! $ @make-gcc GNUC cc1 cc1plus
+$! when invoking this command procedure. Note that you should not
+$! do this for a "stage 1" build.
$!
+$ @make-cc1.com 'p1' 'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
+$!
+$! To install it (them), copy the resulting GCC-CC1.EXE (and GCC-CC1PLUS.EXE)
+$! to the GNU_CC:[000000] directory.
+$!
+$
+$!
+$! Now we build the `libgcc2' support library. It will need to be merged
+$! with the existing gcclib.olb library.
+$!
+$ @make-l2.com 'p1' 'p2' 'p3' 'p4' 'p5' 'p6' 'p7' 'p8'
+$!
+$! To install, save a backup copy of GNU_CC:[000000]GCCLIB.OLB somewhere,
+$! then update the original using the newly created LIBGCC2.OLB via
+$! $ library/Obj libgcc2.olb /Extract=*/Output=libgcc2.obj
+$! $ library/Obj gnu_cc:[000000]gcclib.olb libgcc2.obj /Replace
+$!
+$! Depending upon how old your present gcclib library is, you might have
+$! to delete some modules, such as `eprintf' and `new', to avoid conflicting
+$! symbols from obsolete routines. After deleting any such modules, just
+$! repeat the `library/replace' step.
+$!
+$ exit
diff --git a/gnu/usr.bin/gcc/make-l2.com b/gnu/usr.bin/gcc/make-l2.com
index d22ad9b0f85..9f45e64d95d 100644
--- a/gnu/usr.bin/gcc/make-l2.com
+++ b/gnu/usr.bin/gcc/make-l2.com
@@ -1,36 +1,44 @@
-$! Set the def dir to proper place for use in batch. Works for interactive too.
-$flnm = f$enviroment("PROCEDURE") ! get current procedure name
-$set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
+$! make-l2.com -- VMS build procedure for libgcc2.
+$
+$! Change working directory to the location of this command procedure.
+$ flnm = f$enviroment("PROCEDURE") !get current procedure name
+$ set default 'f$parse(flnm,,,"DEVICE")''f$parse(flnm,,,"DIRECTORY")'
$!
-$! Command file to build libgcc2.olb. You should only run this once you
+$! Command file to build libgcc2.olb. You should only run this once you
$! have the current compiler installed, otherwise some of the builtins will
$! not be recognized. Once you have built libgcc2.olb, you can merge this
$! with gnu_cc:[000000]gcclib.olb
$!
-$! All of the source code is assumed to be in libgcc2.c, and a list of the
+$! All of the C source code is assumed to be in libgcc2.c, and a list of the
$! modules that we need from there is in libgcc2.list (which is generated
-$! when config-gcc.com is run).
+$! when vmsconfig.com is run). The C++ source is found in the [.cp.inc]
+$! directory and managed via libgcc2-cxx.list.
$!
-$if f$search("gcc-cc1.exe").eqs.""
-$ then
+$ if f$search("gcc-cc1.exe").eqs.""
+$ then
$ gcc_cc1:=$gnu_cc:[000000]gcc-cc1
$ if f$extract(0,1,f$trnlnm("GNU_CC_VERSION")).eqs."1" then goto nocompile
-$ else
+$ else
$ gcc_cc1:=$sys$disk:[]gcc-cc1
-$ endif
+$ endif
$!
-$if f$search("gcc-cpp.exe").eqs.""
-$ then
+$ if f$search("gcc-cpp.exe").eqs.""
+$ then
$ gcc_cpp:=$gnu_cc:[000000]gcc-cpp
$ if f$extract(0,1,f$trnlnm("GNU_CC_VERSION")).eqs."1" then goto nocompile
$ Version:='f$trnlnm("GNU_CC_VERSION")'
-$ else
+$ else
$ gcc_cpp:=$sys$disk:[]gcc-cpp
$ open ifile$ version.opt
$ read ifile$ line
$ close ifile$
-$ Version=line-"ident="""-"""
-$ endif
+$ Version=line - "ident=""" - """
+$ endif
+$!
+$ if f$search("gcc-cc1plus.exe").eqs.""
+$ then gcc_cxx = "$gnu_cc:[000000]gcc-cc1plus"
+$ else gcc_cxx = "$sys$disk:[]gcc-cc1plus"
+$ endif
$!
$gcc_as:=$gnu_cc:[000000]gcc-as
$cpp_file:=sys$scratch:gcc_'f$getjpi(0,"pid")'.cpp
@@ -48,9 +56,12 @@ $compile:
$lib/create libgcc2.olb
$on error then goto c_err
$on control_y then goto c_err
+$
+$if f$trnlnm("IFILE$").nes."" then close/noLog ifile$
$open ifile$ libgcc2.list
-$loop: read ifile$ line/end=c_done
+$loop:
$!
+$read ifile$ line/end=c_done
$i=0
$loop1:
$flnm=f$element(i," ",line)
@@ -69,8 +80,8 @@ $! We do this by hand, since the VMS compiler driver does not have a way
$! of specifying an alternate location for the compiler executables.
$!
$ gcc_cpp "-I[]" "-I[.ginclude]" "-D''flnm'" libgcc2.c 'cpp_file'
-$ gcc_cc1 'cpp_file' -dumpbase 'objname' -
- -quiet -mgnu -g "-O1" -mvaxc-alignment -o 's_file'
+$ gcc_cc1 'cpp_file' -dumpbase 'objname' -fexceptions -
+ -quiet -mgnu -g "-O1" -mvaxc-alignment -o 's_file'
$ delete/nolog 'cpp_file';
$ gcc_as "-vGNU CC V''Version'" 's_file' -o 'objname'.OBJ
$! Assemble again, preserving lowercase symbol names this time.
@@ -82,13 +93,51 @@ $ delete/nolog 'objname'.obj;,'objname'-c.obj;
$!
$goto loop1
$!
-$goto loop
-$!
$! In case of error or abort, go here (In order to close file).
$!
-$c_err: !'f$verify(0)
+$c_err: !'f$verify(0)
$close ifile$
$ exit %x2c
$!
$c_done:
$close ifile$
+$
+$
+$ EXIT
+$ !gcc-2.8.0: C++ libgcc2 code disabled since it's not adequately tested
+$
+$!
+$ p1 = p1+" "+p2+" "+p3+" "+p4+" "+p5+" "+p6+" "+p7+" "+p8
+$ p1 = " " + f$edit(p1,"COMPRESS,TRIM,UPCASE") + " "
+$! (note: substring locations can only be equal when neither string is present)
+$ if f$locate(" CC1PLUS ",p1).eq.f$locate(" CXX ",p1) then goto cxx_done
+$ if f$search("libgcc2-cxx.list").eqs."" then goto cxx_done
+$!
+$ open/read ifile$ libgcc2-cxx.list
+$cxx_line_loop:
+$ read ifile$ line/end=cxx_done
+$ i = 0
+$cxx_file_loop:
+$ flnm = f$element(i,",",line)
+$ i = i + 1
+$ if flnm.eqs."" .or. flnm.eqs."," then goto cxx_line_loop
+$ write sys$output "$ gcc/plus/debug ''flnm'.cc"
+$ objname = flnm
+$!
+$ gcc_cpp -+ "-I[]" "-I[.ginclude]" "-I[.cp.inc]" [.cp]'flnm'.cc 'cpp_file'
+$ gcc_cxx 'cpp_file' -dumpbase 'objname' -fexceptions -
+ -quiet -mgnu -g "-O1" -mvaxc-alignment -o 's_file'
+$ delete/nolog 'cpp_file';
+$ gcc_as "-vGNU CC V''Version'" 's_file' -o 'objname'.OBJ
+$! Assemble again, preserving lowercase symbol names this time.
+$ gcc_as "-vGNU CC V''Version'" -h3 's_file' -o 'objname'-c.OBJ
+$ delete/nolog 's_file';
+$
+$ library libgcc2.olb 'objname'.obj,'objname'-c.obj
+$ delete/nolog 'objname'.obj;,'objname'-c.obj;
+$!
+$ goto cxx_file_loop
+$!
+$cxx_done:
+$ close ifile$
+$ exit
diff --git a/gnu/usr.bin/gcc/md.texi b/gnu/usr.bin/gcc/md.texi
index 6fcf4190e82..e74a8e259d3 100644
--- a/gnu/usr.bin/gcc/md.texi
+++ b/gnu/usr.bin/gcc/md.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
+@c Copyright (C) 1988,89,92,93,94,96 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -174,7 +174,9 @@ Operand numbers must be chosen consecutively counting from zero in
each instruction pattern. There may be only one @code{match_operand}
expression in the pattern for each operand number. Usually operands
are numbered in the order of appearance in @code{match_operand}
-expressions.
+expressions. In the case of a @code{define_expand}, any operand numbers
+used only in @code{match_dup} expressions have higher values than all
+other operand numbers.
@var{predicate} is a string that is the name of a C function that accepts two
arguments, an expression and a machine mode. During matching, the
@@ -507,8 +509,8 @@ already defined, then you can simply use @code{#} as the output template
instead of writing an output template that emits the multiple assembler
instructions.
-If @code{ASSEMBLER_DIALECT} is defined, you can use
-@samp{@{option0|option1|option2@}} constructs in the templates. These
+If the macro @code{ASSEMBLER_DIALECT} is defined, you can use construct
+of the form @samp{@{option0|option1|option2@}} in the templates. These
describe multiple variants of assembler language syntax.
@xref{Instruction Output}.
@@ -621,7 +623,7 @@ as follows, having the output control string start with a @samp{@@}:
@cindex constraints
Each @code{match_operand} in an instruction pattern can specify a
-constraint for the type of operands allowed.
+constraint for the type of operands allowed.
@end ifset
@ifclear INTERNALS
@node Constraints
@@ -794,7 +796,7 @@ registers that are not general registers.
@ifset INTERNALS
Any operand whatsoever is allowed, even if it does not satisfy
@code{general_operand}. This is normally used in the constraint of
-a @code{match_scratch} when certain alternatives will not actually
+a @code{match_scratch} when certain alternatives will not actually
require a scratch register.
@end ifset
@ifclear INTERNALS
@@ -818,7 +820,7 @@ input operands and one output operand in the RTL, but on most CISC
@end ifset
@ifclear INTERNALS
which @code{asm} distinguishes. For example, an add instruction uses
-two input operands and an output operand, but on most CISC
+two input operands and an output operand, but on most CISC
@end ifclear
machines an add instruction really has only two operands, one of them an
input-output operand:
@@ -992,6 +994,15 @@ If the operand's predicate can recognize registers, but the constraint does
not permit them, it can make the compiler crash. When this operand happens
to be a register, the reload pass will be stymied, because it does not know
how to copy a register temporarily into memory.
+
+If the predicate accepts a unary operator, the constraint applies to the
+operand. For example, the MIPS processor at ISA level 3 supports an
+instruction which adds two registers in @code{SImode} to produce a
+@code{DImode} result, but only if the registers are correctly sign
+extended. This predicate for the input operands accepts a
+@code{sign_extend} of an @code{SImode} register. Write the constraint
+to indicate the type of register that is required for the operand of the
+@code{sign_extend}.
@end ifset
@node Multi-Alternative
@@ -1108,17 +1119,25 @@ identifies an operand that is both input and output; all other operands
are assumed to be input only.
@cindex @samp{&} in constraint
+@cindex earlyclobber operand
@item &
-Means (in a particular alternative) that this operand is written
-before the instruction is finished using the input operands.
-Therefore, this operand may not lie in a register that is used as an
-input operand or as part of any memory address.
+Means (in a particular alternative) that this operand is an
+@dfn{earlyclobber} operand, which is modified before the instruction is
+finished using the input operands. Therefore, this operand may not lie
+in a register that is used as an input operand or as part of any memory
+address.
@samp{&} applies only to the alternative in which it is written. In
constraints with multiple alternatives, sometimes one alternative
requires @samp{&} while others do not. See, for example, the
@samp{movdf} insn of the 68000.
+An input operand can be tied to an earlyclobber operand if its only
+use as an input occurs before the early result is written. Adding
+alternatives of this form often allows GCC to produce better code
+when only some of the inputs can be affected by the earlyclobber.
+See, for example, the @samp{mulsi3} insn of the ARM.
+
@samp{&} does not obviate the need to write @samp{=}.
@cindex @samp{%} in constraint
@@ -1249,7 +1268,7 @@ Integer that satisfies constraint @samp{I} when negated (twos complement)
Integer in the range 0 to 32
@item Q
-A memory reference where the exact address is in a single register
+A memory reference where the exact address is in a single register
(`@samp{m}' is preferable for @code{asm} statements)
@item R
@@ -1370,6 +1389,18 @@ instruction per word
@item Q
Memory operand that is an offset from a register (@samp{m} is preferable
for @code{asm} statements)
+
+@item R
+AIX TOC entry
+
+@item S
+Windows NT SYMBOL_REF
+
+@item T
+Windows NT LABEL_REF
+
+@item U
+System V Release 4 small data area reference
@end table
@item Intel 386---@file{i386.h}
@@ -1552,6 +1583,9 @@ Signed number whose magnitude is greater than 0x80
@item L
Integer in the range -8 to -1
+@item M
+Signed number whose magnitude is greater than 0x100
+
@item G
Floating point constant that is not a 68881 constant
@@ -1563,7 +1597,10 @@ Floating point constant that can be used by Sun FPA
@item SPARC---@file{sparc.h}
@table @code
@item f
-Floating-point register
+Floating-point register that can hold 32 or 64 bit values.
+
+@item e
+Floating-point register that can hold 64 or 128 bit values.
@item I
Signed 13 bit constant
@@ -1591,7 +1628,7 @@ Constant, or memory address
@item T
Memory address aligned to an 8-byte boundary
-@item U
+@item U
Even register
@end table
@end table
@@ -1698,23 +1735,23 @@ scratch registers after reload, you must define
patterns @samp{reload_in@var{m}} or @samp{reload_out@var{m}} to handle
them. @xref{Register Classes}.
-The constraints on a @samp{move@var{m}} must permit moving any hard
+The constraints on a @samp{mov@var{m}} must permit moving any hard
register to any other hard register provided that
@code{HARD_REGNO_MODE_OK} permits mode @var{m} in both registers and
@code{REGISTER_MOVE_COST} applied to their classes returns a value of 2.
-It is obligatory to support floating point @samp{move@var{m}}
+It is obligatory to support floating point @samp{mov@var{m}}
instructions into and out of any registers that can hold fixed point
values, because unions and structures (which have modes @code{SImode} or
@code{DImode}) can be in those registers and they may have floating
point members.
-There may also be a need to support fixed point @samp{move@var{m}}
+There may also be a need to support fixed point @samp{mov@var{m}}
instructions in and out of floating point registers. Unfortunately, I
have forgotten why this was so, and I don't know whether it is still
true. If @code{HARD_REGNO_MODE_OK} rejects fixed point values in
floating point registers, then the constraints of the fixed point
-@samp{move@var{m}} instructions must be designed to avoid ever trying to
+@samp{mov@var{m}} instructions must be designed to avoid ever trying to
reload into a floating point register.
@cindex @code{reload_in} instruction pattern
@@ -1776,8 +1813,8 @@ means of constraints requiring operands 1 and 0 to be the same location.
@cindex @code{udiv@var{m}3} instruction pattern
@cindex @code{mod@var{m}3} instruction pattern
@cindex @code{umod@var{m}3} instruction pattern
-@cindex @code{min@var{m}3} instruction pattern
-@cindex @code{max@var{m}3} instruction pattern
+@cindex @code{smin@var{m}3} instruction pattern
+@cindex @code{smax@var{m}3} instruction pattern
@cindex @code{umin@var{m}3} instruction pattern
@cindex @code{umax@var{m}3} instruction pattern
@cindex @code{and@var{m}3} instruction pattern
@@ -1922,6 +1959,17 @@ it may provide the value 4 for this operand.
These patterns need not give special consideration to the possibility
that the source and destination strings might overlap.
+@cindex @code{clrstr@var{m}} instruction pattern
+@item @samp{clrstr@var{m}}
+Block clear instruction. The addresses of the destination string is the
+first operand, in mode @code{Pmode}. The number of bytes to clear is
+the second operand, in mode @var{m}.
+
+The third operand is the known alignment of the destination, in the form
+of a @code{const_int} rtx. Thus, if the compiler knows that the
+destination is word-aligned, it may provide the value 4 for this
+operand.
+
@cindex @code{cmpstr@var{m}} instruction pattern
@item @samp{cmpstr@var{m}}
Block compare instruction, with five operands. Operand 0 is the output;
@@ -1932,6 +1980,7 @@ to store a value in operand 0 whose sign indicates the result of the
comparison.
@cindex @code{strlen@var{m}} instruction pattern
+@item @samp{strlen@var{m}}
Compute the length of a string, with three operands.
Operand 0 is the result (of mode @var{m}), operand 1 is
a @code{mem} referring to the first character of the string,
@@ -1981,20 +2030,20 @@ of mode @var{m} by converting the value to an integer.
Like @samp{fixuns@var{m}@var{n}2} but works for any floating point
value of mode @var{m} by converting the value to an integer.
-@cindex @code{trunc@var{mn}} instruction pattern
-@item @samp{trunc@var{m}@var{n}}
+@cindex @code{trunc@var{mn}2} instruction pattern
+@item @samp{trunc@var{m}@var{n}2}
Truncate operand 1 (valid for mode @var{m}) to mode @var{n} and
store in operand 0 (which has mode @var{n}). Both modes must be fixed
point or both floating point.
-@cindex @code{extend@var{mn}} instruction pattern
-@item @samp{extend@var{m}@var{n}}
+@cindex @code{extend@var{mn}2} instruction pattern
+@item @samp{extend@var{m}@var{n}2}
Sign-extend operand 1 (valid for mode @var{m}) to mode @var{n} and
store in operand 0 (which has mode @var{n}). Both modes must be fixed
point or both floating point.
-@cindex @code{zero_extend@var{mn}} instruction pattern
-@item @samp{zero_extend@var{m}@var{n}}
+@cindex @code{zero_extend@var{mn}2} instruction pattern
+@item @samp{zero_extend@var{m}@var{n}2}
Zero-extend operand 1 (valid for mode @var{m}) to mode @var{n} and
store in operand 0 (which has mode @var{n}). Both modes must be fixed
point.
@@ -2264,6 +2313,23 @@ table it uses. Its assembler code normally has no need to use the
second operand, but you should incorporate it in the RTL pattern so
that the jump optimizer will not delete the table as unreachable code.
+@cindex @code{canonicalize_funcptr_for_compare} instruction pattern
+@item @samp{canonicalize_funcptr_for_compare}
+Canonicalize the function pointer in operand 1 and store the result
+into operand 0.
+
+Operand 0 is always a @code{reg} and has mode @code{Pmode}; operand 1
+may be a @code{reg}, @code{mem}, @code{symbol_ref}, @code{const_int}, etc
+and also has mode @code{Pmode}.
+
+Canonicalization of a function pointer usually involves computing
+the address of the function which would be called if the function
+pointer were used in an indirect call.
+
+Only define this pattern if function pointers on the target machine
+can have different values but still call the same function when
+used in an indirect call.
+
@cindex @code{save_stack_block} instruction pattern
@cindex @code{save_stack_function} instruction pattern
@cindex @code{save_stack_nonlocal} instruction pattern
@@ -2326,13 +2392,88 @@ nonlocal gotos and a @code{reg} in the other two cases.
@cindex @code{allocate_stack} instruction pattern
@item @samp{allocate_stack}
-Subtract (or add if @code{STACK_GROWS_DOWNWARD} is undefined) operand 0 from
+Subtract (or add if @code{STACK_GROWS_DOWNWARD} is undefined) operand 1 from
the stack pointer to create space for dynamically allocated data.
+Store the resultant pointer to this space into operand 0. If you
+are allocating space from the main stack, do this by emitting a
+move insn to copy @code{virtual_stack_dynamic_rtx} to operand 0.
+If you are allocating the space elsewhere, generate code to copy the
+location of the space to operand 0. In the latter case, you must
+ensure this space gets freed when the corresponding space on the main
+stack is free.
+
Do not define this pattern if all that must be done is the subtraction.
Some machines require other operations such as stack probes or
maintaining the back chain. Define this pattern to emit those
operations in addition to updating the stack pointer.
+
+@cindex @code{probe} instruction pattern
+@item @samp{probe}
+Some machines require instructions to be executed after space is
+allocated from the stack, for example to generate a reference at
+the bottom of the stack.
+
+If you need to emit instructions before the stack has been adjusted,
+put them into the @samp{allocate_stack} pattern. Otherwise, define
+this pattern to emit the required instructions.
+
+No operands are provided.
+
+@cindex @code{check_stack} instruction pattern
+@item @samp{check_stack}
+If stack checking cannot be done on your system by probing the stack with
+a load or store instruction (@pxref{Stack Checking}), define this pattern
+to perform the needed check and signaling an error if the stack
+has overflowed. The single operand is the location in the stack furthest
+from the current stack pointer that you need to validate. Normally,
+on machines where this pattern is needed, you would obtain the stack
+limit from a global or thread-specific variable or register.
+
+@cindex @code{nonlocal_goto} instruction pattern
+@item @samp{nonlocal_goto}
+Emit code to generate a non-local goto, e.g., a jump from one function
+to a label in an outer function. This pattern has four arguments,
+each representing a value to be used in the jump. The first
+argument is to be loadedd into the frame pointer, the second is
+the address to branch to (code to dispatch to the actual label),
+the third is the address of a location where the stack is saved,
+and the last is the address of the label, to be placed in the
+location for the incoming static chain.
+
+On most machines you need not define this pattern, since GNU CC will
+already generate the correct code, which is to load the frame pointer
+and static chain, restore the stack (using the
+@samp{restore_stack_nonlocal} pattern, if defined), and jump indirectly
+to the dispatcher. You need only define this pattern if this code will
+not work on your machine.
+
+@cindex @code{nonlocal_goto_receiver} instruction pattern
+@item @samp{nonlocal_goto_receiver}
+This pattern, if defined, contains code needed at the target of a
+nonlocal goto after the code already generated by GNU CC. You will not
+normally need to define this pattern. A typical reason why you might
+need this pattern is if some value, such as a pointer to a global table,
+must be restored when the frame pointer is restored. There are no
+arguments.
+
+@cindex @code{exception_receiver} instruction pattern
+@item @samp{exception_receiver}
+This pattern, if defined, contains code needed at the site of an
+exception handler that isn't needed at the site of a nonlocal goto. You
+will not normally need to define this pattern. A typical reason why you
+might need this pattern is if some value, such as a pointer to a global
+table, must be restored after control flow is branched to the handler of
+an exception. There are no arguments.
+
+@cindex @code{builtin_setjmp_receiver} instruction pattern
+@item @samp{builtin_setjmp_receiver}
+This pattern, if defined, contains code needed at the site of an
+builtin setjmp that isn't needed at the site of a nonlocal goto. You
+will not normally need to define this pattern. A typical reason why you
+might need this pattern is if some value, such as a pointer to a global
+table, must be restored. This pattern is called immediate after the
+call to @code{__dummy} has been emitted. There are no arguments.
@end table
@node Pattern Ordering
@@ -2608,6 +2749,7 @@ converted into the appropriate multiplication by a power of two.
@cindex @code{ior}, canonicalization of
@cindex @code{and}, canonicalization of
@cindex De Morgan's law
+@item
De`Morgan's Law is used to move bitwise negation inside a bitwise
logical-and or logical-or operation. If this results in only one
operand being a @code{not} expression, it will be the first one.
@@ -3209,8 +3351,8 @@ an equality comparison of a register and a large constant:
(set (match_dup 0) (compare:CC (match_dup 3) (match_dup 5)))]
"
@{
- /* Get the constant we are comparing against, C, and see what it
- looks like sign-extended to 16 bits. Then see what constant
+ /* Get the constant we are comparing against, C, and see what it
+ looks like sign-extended to 16 bits. Then see what constant
could be XOR'ed with C to get the sign-extended value. */
int c = INTVAL (operands[2]);
@@ -3320,7 +3462,7 @@ defined and the function to obtain the attribute's value will return
@cindex attribute expressions
RTL expressions used to define attributes use the codes described above
-plus a few specific to attribute definitions, to be discussed below.
+plus a few specific to attribute definitions, to be discussed below.
Attribute value expressions must have one of the following forms:
@table @code
@@ -3485,21 +3627,21 @@ scheduled.
@var{name} is a string specifying one of a fixed set of flags to test.
Test the flags @code{forward} and @code{backward} to determine the
-direction of a conditional branch. Test the flags @code{very_likely},
-@code{likely}, @code{very_unlikely}, and @code{unlikely} to determine
+direction of a conditional branch. Test the flags @code{very_likely},
+@code{likely}, @code{very_unlikely}, and @code{unlikely} to determine
if a conditional branch is expected to be taken.
-If the @code{very_likely} flag is true, then the @code{likely} flag is also
+If the @code{very_likely} flag is true, then the @code{likely} flag is also
true. Likewise for the @code{very_unlikely} and @code{unlikely} flags.
This example describes a conditional branch delay slot which
-can be nullified for forward branches that are taken (annul-true) or
-for backward branches which are not taken (annul-false).
+can be nullified for forward branches that are taken (annul-true) or
+for backward branches which are not taken (annul-false).
@smallexample
(define_delay (eq_attr "type" "cbranch")
- [(eq_attr "in_branch_delay" "true")
- (and (eq_attr "in_branch_delay" "true")
+ [(eq_attr "in_branch_delay" "true")
+ (and (eq_attr "in_branch_delay" "true")
(attr_flag "forward"))
(and (eq_attr "in_branch_delay" "true")
(attr_flag "backward"))])
@@ -3508,12 +3650,12 @@ for backward branches which are not taken (annul-false).
The @code{forward} and @code{backward} flags are false if the current
@code{insn} being scheduled is not a conditional branch.
-The @code{very_likely} and @code{likely} flags are true if the
-@code{insn} being scheduled is not a conditional branch. The
+The @code{very_likely} and @code{likely} flags are true if the
+@code{insn} being scheduled is not a conditional branch.
The @code{very_unlikely} and @code{unlikely} flags are false if the
@code{insn} being scheduled is not a conditional branch.
-@code{attr_flag} is only used during delay slot scheduling and has no
+@code{attr_flag} is only used during delay slot scheduling and has no
meaning to other passes of the compiler.
@end table
@@ -3702,7 +3844,7 @@ must be a @code{label_ref}.
@item (pc)
This refers to the address of the @emph{current} insn. It might have
been more consistent with other usage to make this the address of the
-@emph{next} insn but this would be confusing because the length of the
+@emph{next} insn but this would be confusing because the length of the
current insn is to be computed.
@end table
@@ -3713,7 +3855,7 @@ For normal insns, the length will be determined by value of the
@code{addr_diff_vec} insn patterns, the length is computed as
the number of vectors multiplied by the size of each vector.
-Lengths are measured in addressable storage units (bytes).
+Lengths are measured in addressable storage units (bytes).
The following macros can be used to refine the length computation:
@@ -3813,7 +3955,7 @@ On some machines, conditional branch instructions can optionally
instruction will not be executed for certain branch outcomes. Both
instructions that annul if the branch is true and instructions that
annul if the branch is false are supported.
-
+
Delay slot scheduling differs from instruction scheduling in that
determining whether an instruction needs a delay slot is dependent only
on the type of instruction being generated, not on data flow between the
diff --git a/gnu/usr.bin/gcc/mips-tdump.c b/gnu/usr.bin/gcc/mips-tdump.c
index 36dfd150fa8..edebf022c1e 100644
--- a/gnu/usr.bin/gcc/mips-tdump.c
+++ b/gnu/usr.bin/gcc/mips-tdump.c
@@ -1,5 +1,5 @@
/* Read and manage MIPS symbol tables from object modules.
- Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by hartzell@boulder.colorado.edu,
Rewritten by meissner@osf.org.
@@ -20,13 +20,13 @@ 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 <stdio.h>
#include <sys/types.h>
#include <sys/file.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
-#include "config.h"
#ifdef index
#undef index
@@ -44,7 +44,7 @@ Boston, MA 02111-1307, USA. */
which does not include mips.h.
These must match the corresponding definitions in gdb/mipsread.c.
- Unfortunately, gcc and gdb do not currently share any directories. */
+ Unfortunately, gcc and gdb do not currently share any directories. */
#define CODE_MASK 0x8F300
#define MIPS_IS_STAB(sym) (((sym)->index & 0xFFF00) == CODE_MASK)
@@ -308,7 +308,7 @@ read_seek (ptr, size, offset, context)
if (size == 0) /* nothing to read */
return ptr;
- if ((ptr == (PTR_T)0 && (ptr = malloc (size)) == (PTR_T)0)
+ if ((ptr == (PTR_T) 0 && (ptr = malloc (size)) == (PTR_T) 0)
|| (tfile_offset != offset && lseek (tfile_fd, offset, 0) == -1)
|| (read_size = read (tfile_fd, ptr, size)) < 0)
{
@@ -721,7 +721,7 @@ type_to_string (aux_ptr, index, fdp)
int j;
/* Print array bounds reversed (ie, in the order the C
- programmer writes them). C is such a fun language.... */
+ programmer writes them). C is such a fun language.... */
while (i < 5 && qualifiers[i+1].type == tq_Array)
i++;
@@ -833,60 +833,60 @@ print_sym_hdr (sym_ptr)
printf(" %-*s %11s %11s %11s\n", width, "====", "======", "======", "=====\n");
printf(" %-*s %11ld %11ld %11ld [%d]\n", width, "Line numbers",
- (long)sym_ptr->cbLineOffset,
- (long)sym_ptr->cbLine,
- (long)sym_ptr->cbLine,
- (int)sym_ptr->ilineMax);
+ (long) sym_ptr->cbLineOffset,
+ (long) sym_ptr->cbLine,
+ (long) sym_ptr->cbLine,
+ (int) sym_ptr->ilineMax);
printf(" %-*s %11ld %11ld %11ld\n", width, "Dense numbers",
- (long)sym_ptr->cbDnOffset,
- (long)sym_ptr->idnMax,
- (long)(sym_ptr->idnMax * sizeof (DNR)));
+ (long) sym_ptr->cbDnOffset,
+ (long) sym_ptr->idnMax,
+ (long) (sym_ptr->idnMax * sizeof (DNR)));
printf(" %-*s %11ld %11ld %11ld\n", width, "Procedures Tables",
- (long)sym_ptr->cbPdOffset,
- (long)sym_ptr->ipdMax,
- (long)(sym_ptr->ipdMax * sizeof (PDR)));
+ (long) sym_ptr->cbPdOffset,
+ (long) sym_ptr->ipdMax,
+ (long) (sym_ptr->ipdMax * sizeof (PDR)));
printf(" %-*s %11ld %11ld %11ld\n", width, "Local Symbols",
- (long)sym_ptr->cbSymOffset,
- (long)sym_ptr->isymMax,
- (long)(sym_ptr->isymMax * sizeof (SYMR)));
+ (long) sym_ptr->cbSymOffset,
+ (long) sym_ptr->isymMax,
+ (long) (sym_ptr->isymMax * sizeof (SYMR)));
printf(" %-*s %11ld %11ld %11ld\n", width, "Optimization Symbols",
- (long)sym_ptr->cbOptOffset,
- (long)sym_ptr->ioptMax,
- (long)(sym_ptr->ioptMax * sizeof (OPTR)));
+ (long) sym_ptr->cbOptOffset,
+ (long) sym_ptr->ioptMax,
+ (long) (sym_ptr->ioptMax * sizeof (OPTR)));
printf(" %-*s %11ld %11ld %11ld\n", width, "Auxiliary Symbols",
- (long)sym_ptr->cbAuxOffset,
- (long)sym_ptr->iauxMax,
- (long)(sym_ptr->iauxMax * sizeof (AUXU)));
+ (long) sym_ptr->cbAuxOffset,
+ (long) sym_ptr->iauxMax,
+ (long) (sym_ptr->iauxMax * sizeof (AUXU)));
printf(" %-*s %11ld %11ld %11ld\n", width, "Local Strings",
- (long)sym_ptr->cbSsOffset,
- (long)sym_ptr->issMax,
- (long)sym_ptr->issMax);
+ (long) sym_ptr->cbSsOffset,
+ (long) sym_ptr->issMax,
+ (long) sym_ptr->issMax);
printf(" %-*s %11ld %11ld %11ld\n", width, "External Strings",
- (long)sym_ptr->cbSsExtOffset,
- (long)sym_ptr->issExtMax,
- (long)sym_ptr->issExtMax);
+ (long) sym_ptr->cbSsExtOffset,
+ (long) sym_ptr->issExtMax,
+ (long) sym_ptr->issExtMax);
printf(" %-*s %11ld %11ld %11ld\n", width, "File Tables",
- (long)sym_ptr->cbFdOffset,
- (long)sym_ptr->ifdMax,
- (long)(sym_ptr->ifdMax * sizeof (FDR)));
+ (long) sym_ptr->cbFdOffset,
+ (long) sym_ptr->ifdMax,
+ (long) (sym_ptr->ifdMax * sizeof (FDR)));
printf(" %-*s %11ld %11ld %11ld\n", width, "Relative Files",
- (long)sym_ptr->cbRfdOffset,
- (long)sym_ptr->crfd,
- (long)(sym_ptr->crfd * sizeof (ulong)));
+ (long) sym_ptr->cbRfdOffset,
+ (long) sym_ptr->crfd,
+ (long) (sym_ptr->crfd * sizeof (ulong)));
printf(" %-*s %11ld %11ld %11ld\n", width, "External Symbols",
- (long)sym_ptr->cbExtOffset,
- (long)sym_ptr->iextMax,
- (long)(sym_ptr->iextMax * sizeof (EXTR)));
+ (long) sym_ptr->cbExtOffset,
+ (long) sym_ptr->iextMax,
+ (long) (sym_ptr->iextMax * sizeof (EXTR)));
}
@@ -909,7 +909,7 @@ print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
printf ("\n Symbol# %d: \"%s\"\n", number, sym_ptr->iss + strbase);
- if (aux_base != (AUXU *)0 && index != indexNil)
+ if (aux_base != (AUXU *) 0 && index != indexNil)
switch (symbol_type)
{
case st_Nil:
@@ -921,7 +921,7 @@ print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
printf (" End+1 symbol: %ld\n", index);
if (want_scope)
{
- if (free_scope == (scope_t *)0)
+ if (free_scope == (scope_t *) 0)
scope_ptr = (scope_t *) malloc (sizeof (scope_t));
else
{
@@ -947,7 +947,7 @@ print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
if (want_scope)
{
- if (cur_scope == (scope_t *)0)
+ if (cur_scope == (scope_t *) 0)
printf (" Can't pop end scope\n");
else
{
@@ -975,7 +975,7 @@ print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
if (want_scope)
{
- if (free_scope == (scope_t *)0)
+ if (free_scope == (scope_t *) 0)
scope_ptr = (scope_t *) malloc (sizeof (scope_t));
else
{
@@ -1011,12 +1011,12 @@ print_symbol (sym_ptr, number, strbase, aux_base, ifd, fdp)
if (want_scope)
{
printf (" Scopes: ");
- if (cur_scope == (scope_t *)0)
+ if (cur_scope == (scope_t *) 0)
printf (" none\n");
else
{
for (scope_ptr = cur_scope;
- scope_ptr != (scope_t *)0;
+ scope_ptr != (scope_t *) 0;
scope_ptr = scope_ptr->prev)
{
char *class;
@@ -1220,7 +1220,7 @@ print_file_desc (fdp, number)
(ulong) (fdp->rfdBase * sizeof(ulong) + sym_hdr.cbRfdOffset));
- if (want_scope && cur_scope != (scope_t *)0)
+ if (want_scope && cur_scope != (scope_t *) 0)
printf ("\n Warning scope does not start at 0!\n");
/*
@@ -1238,7 +1238,7 @@ print_file_desc (fdp, number)
-1,
fdp);
- if (want_scope && cur_scope != (scope_t *)0)
+ if (want_scope && cur_scope != (scope_t *) 0)
printf ("\n Warning scope does not end at 0!\n");
/*
@@ -1328,7 +1328,7 @@ print_file_desc (fdp, number)
if (pdi == fdp->cpd + fdp->ipdFirst - 1) /* last procedure */
line_end = ((uchar *)lines) + fdp->cbLine + fdp->cbLineOffset;
- else /* not last proc. */
+ else /* not last proc. */
line_end = (((uchar *)lines) + proc_desc[pdi+1].cbLineOffset
+ fdp->cbLineOffset);
@@ -1368,12 +1368,12 @@ read_tfile __proto((void))
short magic;
off_t sym_hdr_offset = 0;
- (void) read_seek ((PTR_T) &magic, sizeof (magic), (off_t)0, "Magic number");
+ (void) read_seek ((PTR_T) &magic, sizeof (magic), (off_t) 0, "Magic number");
if (!tfile)
{
/* Print out the global header, since this is not a T-file. */
- (void) read_seek ((PTR_T) &global_hdr, sizeof (global_hdr), (off_t)0,
+ (void) read_seek ((PTR_T) &global_hdr, sizeof (global_hdr), (off_t) 0,
"Global file header");
print_global_hdr (&global_hdr);
@@ -1394,32 +1394,32 @@ read_tfile __proto((void))
print_sym_hdr (&sym_hdr);
- lines = (LINER *) read_seek ((PTR_T)0,
+ lines = (LINER *) read_seek ((PTR_T) 0,
sym_hdr.cbLine,
sym_hdr.cbLineOffset,
"Line numbers");
- dense_nums = (DNR *) read_seek ((PTR_T)0,
+ dense_nums = (DNR *) read_seek ((PTR_T) 0,
sym_hdr.idnMax * sizeof (DNR),
sym_hdr.cbDnOffset,
"Dense numbers");
- proc_desc = (PDR *) read_seek ((PTR_T)0,
+ proc_desc = (PDR *) read_seek ((PTR_T) 0,
sym_hdr.ipdMax * sizeof (PDR),
sym_hdr.cbPdOffset,
"Procedure tables");
- l_symbols = (SYMR *) read_seek ((PTR_T)0,
+ l_symbols = (SYMR *) read_seek ((PTR_T) 0,
sym_hdr.isymMax * sizeof (SYMR),
sym_hdr.cbSymOffset,
"Local symbols");
- opt_symbols = (OPTR *) read_seek ((PTR_T)0,
+ opt_symbols = (OPTR *) read_seek ((PTR_T) 0,
sym_hdr.ioptMax * sizeof (OPTR),
sym_hdr.cbOptOffset,
"Optimization symbols");
- aux_symbols = (AUXU *) read_seek ((PTR_T)0,
+ aux_symbols = (AUXU *) read_seek ((PTR_T) 0,
sym_hdr.iauxMax * sizeof (AUXU),
sym_hdr.cbAuxOffset,
"Auxiliary symbols");
@@ -1427,34 +1427,34 @@ read_tfile __proto((void))
if (sym_hdr.iauxMax > 0)
{
aux_used = calloc (sym_hdr.iauxMax, 1);
- if (aux_used == (char *)0)
+ if (aux_used == (char *) 0)
{
perror ("calloc");
exit (1);
}
}
- l_strings = (char *) read_seek ((PTR_T)0,
+ l_strings = (char *) read_seek ((PTR_T) 0,
sym_hdr.issMax,
sym_hdr.cbSsOffset,
"Local string table");
- e_strings = (char *) read_seek ((PTR_T)0,
+ e_strings = (char *) read_seek ((PTR_T) 0,
sym_hdr.issExtMax,
sym_hdr.cbSsExtOffset,
"External string table");
- file_desc = (FDR *) read_seek ((PTR_T)0,
+ file_desc = (FDR *) read_seek ((PTR_T) 0,
sym_hdr.ifdMax * sizeof (FDR),
sym_hdr.cbFdOffset,
"File tables");
- rfile_desc = (ulong *) read_seek ((PTR_T)0,
+ rfile_desc = (ulong *) read_seek ((PTR_T) 0,
sym_hdr.crfd * sizeof (ulong),
sym_hdr.cbRfdOffset,
"Relative file tables");
- e_symbols = (EXTR *) read_seek ((PTR_T)0,
+ e_symbols = (EXTR *) read_seek ((PTR_T) 0,
sym_hdr.iextMax * sizeof (EXTR),
sym_hdr.cbExtOffset,
"External symbols");
@@ -1526,9 +1526,9 @@ main (argc, argv)
if (sym_hdr.ifdMax == 0)
last_aux_in_use = 0;
else
- last_aux_in_use =
- file_desc[sym_hdr.ifdMax-1].iauxBase +
- file_desc[sym_hdr.ifdMax-1].caux - 1;
+ last_aux_in_use
+ = (file_desc[sym_hdr.ifdMax-1].iauxBase
+ + file_desc[sym_hdr.ifdMax-1].caux - 1);
if (last_aux_in_use < sym_hdr.iauxMax-1)
{
diff --git a/gnu/usr.bin/gcc/mips-tfile.c b/gnu/usr.bin/gcc/mips-tfile.c
index cce203f7ace..39f3bc61f1f 100644
--- a/gnu/usr.bin/gcc/mips-tfile.c
+++ b/gnu/usr.bin/gcc/mips-tfile.c
@@ -2,7 +2,7 @@
contain debugging information specified by the GNU compiler
in the form of comments (the mips assembler does not support
assembly access to debug information).
- Copyright (C) 1991, 1993, 1994. 1995 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
Contributed by Michael Meissner, meissner@osf.org
This file is part of GNU CC.
@@ -599,12 +599,12 @@ Boston, MA 02111-1307, USA. */
*/
+#include "config.h"
#ifdef __STDC__
#include <stdarg.h>
#else
#include <varargs.h>
#endif
-#include "config.h"
#include <stdio.h>
#ifndef __SABER__
@@ -939,7 +939,7 @@ typedef enum coff_dt {
typedef enum hash_state {
hash_no = 0, /* don't hash type */
hash_yes = 1, /* ok to hash type, or use previous hash */
- hash_record = 2 /* ok to record hash, but don't use prev. */
+ hash_record = 2 /* ok to record hash, but don't use prev. */
} hash_state_t;
@@ -1014,15 +1014,15 @@ typedef struct varray {
#endif
#define INIT_VARRAY(type) { /* macro to initialize a varray */ \
- (vlinks_t *)0, /* first */ \
- (vlinks_t *)0, /* last */ \
+ (vlinks_t *) 0, /* first */ \
+ (vlinks_t *) 0, /* last */ \
0, /* num_allocated */ \
sizeof (type), /* object_size */ \
OBJECTS_PER_PAGE (type), /* objects_per_page */ \
OBJECTS_PER_PAGE (type), /* objects_last_page */ \
}
-/* Master type for indexes within the symbol table. */
+/* Master type for indexes within the symbol table. */
typedef unsigned long symint_t;
@@ -1171,12 +1171,12 @@ static efdr_t init_file =
0, /* cbLine: size of lines for this file */
},
- (FDR *)0, /* orig_fdr: original file header pointer */
- (char *)0, /* name: pointer to filename */
+ (FDR *) 0, /* orig_fdr: original file header pointer */
+ (char *) 0, /* name: pointer to filename */
0, /* name_len: length of filename */
0, /* void_type: ptr to aux node for void type */
0, /* int_type: ptr to aux node for int type */
- (scope_t *)0, /* cur_scope: current scope being processed */
+ (scope_t *) 0, /* cur_scope: current scope being processed */
0, /* file_index: current file # */
0, /* nested_scopes: # nested scopes */
INIT_VARRAY (char), /* strings: local string varray */
@@ -1184,9 +1184,9 @@ static efdr_t init_file =
INIT_VARRAY (PDR), /* procs: procedure varray */
INIT_VARRAY (AUXU), /* aux_syms: auxiliary symbols varray */
- (struct efdr *)0, /* next_file: next file structure */
+ (struct efdr *) 0, /* next_file: next file structure */
- (shash_t **)0, /* shash_head: string hash table */
+ (shash_t **) 0, /* shash_head: string hash table */
{ 0 }, /* thash_head: type hash table */
};
@@ -1609,17 +1609,17 @@ static PDR *cur_proc_ptr = (PDR *) 0; /* current procedure header */
static SYMR *cur_oproc_begin = (SYMR *) 0; /* original proc. sym begin info */
static SYMR *cur_oproc_end = (SYMR *) 0; /* original proc. sym end info */
static PDR *cur_oproc_ptr = (PDR *) 0; /* current original procedure*/
-static thead_t *cur_tag_head = (thead_t *)0; /* current tag head */
+static thead_t *cur_tag_head = (thead_t *) 0;/* current tag head */
static long file_offset = 0; /* current file offset */
static long max_file_offset = 0; /* maximum file offset */
-static FILE *object_stream = (FILE *)0; /* file desc. to output .o */
-static FILE *obj_in_stream = (FILE *)0; /* file desc. to input .o */
-static char *progname = (char *)0; /* program name for errors */
+static FILE *object_stream = (FILE *) 0; /* file desc. to output .o */
+static FILE *obj_in_stream = (FILE *) 0; /* file desc. to input .o */
+static char *progname = (char *) 0; /* program name for errors */
static char *input_name = "stdin"; /* name of input file */
-static char *object_name = (char *)0; /* tmp. name of object file */
-static char *obj_in_name = (char *)0; /* name of input object file */
-static char *cur_line_start = (char *)0; /* current line read in */
-static char *cur_line_ptr = (char *)0; /* ptr within current line */
+static char *object_name = (char *) 0; /* tmp. name of object file */
+static char *obj_in_name = (char *) 0; /* name of input object file */
+static char *cur_line_start = (char *) 0; /* current line read in */
+static char *cur_line_ptr = (char *) 0; /* ptr within current line */
static unsigned cur_line_nbytes = 0; /* # bytes for current line */
static unsigned cur_line_alloc = 0; /* # bytes total in buffer */
static long line_number = 0; /* current input line number */
@@ -1767,7 +1767,7 @@ extern int optind;
extern int opterr;
extern char *version_string;
#ifndef NO_SYS_SIGLIST
-#ifndef DONT_DECLARE_SYS_SIGLIST
+#ifndef SYS_SIGLIST_DECLARED
extern char *sys_siglist[NSIG + 1];
#endif
#endif
@@ -1782,7 +1782,7 @@ extern char *sys_siglist[NSIG + 1];
/* List of assembler pseudo ops and beginning sequences that need
special actions. Someday, this should be a hash table, and such,
but for now a linear list of names and calls to memcmp will
- do...... */
+ do...... */
typedef struct _pseudo_ops {
const char *name; /* pseudo-op in ascii */
@@ -1826,7 +1826,7 @@ add_varray_page (vp)
new_links->start_index = vp->num_allocated;
vp->objects_last_page = 0;
- if (vp->first == (vlinks_t *)0) /* first allocation? */
+ if (vp->first == (vlinks_t *) 0) /* first allocation? */
vp->first = vp->last = new_links;
else
{ /* 2nd or greater allocation */
@@ -1860,10 +1860,10 @@ hash_string (text, hash_len, hash_tbl, ret_hash_index)
hi &= (1 << HASHBITS) - 1;
hi %= SHASH_SIZE;
- if (ret_hash_index != (symint_t *)0)
+ if (ret_hash_index != (symint_t *) 0)
*ret_hash_index = hi;
- for (ptr = hash_tbl[hi]; ptr != (shash_t *)0; ptr = ptr->next)
+ for (ptr = hash_tbl[hi]; ptr != (shash_t *) 0; ptr = ptr->next)
if (hash_len == ptr->len
&& first_ch == ptr->string[0]
&& memcmp ((CPTR_T) text, (CPTR_T) ptr->string, hash_len) == 0)
@@ -1893,14 +1893,14 @@ add_string (vp, hash_tbl, start, end_p1, ret_hash)
fatal ("String too big (%ld bytes)", (long) len);
hash_ptr = hash_string (start, len, hash_tbl, &hi);
- if (hash_ptr == (shash_t *)0)
+ if (hash_ptr == (shash_t *) 0)
{
register char *p;
if (vp->objects_last_page + len >= PAGE_USIZE)
{
- vp->num_allocated =
- ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
+ vp->num_allocated
+ = ((vp->num_allocated + PAGE_USIZE - 1) / PAGE_USIZE) * PAGE_USIZE;
add_varray_page (vp);
}
@@ -1921,7 +1921,7 @@ add_string (vp, hash_tbl, start, end_p1, ret_hash)
*p = '\0';
}
- if (ret_hash != (shash_t **)0)
+ if (ret_hash != (shash_t **) 0)
*ret_hash = hash_ptr;
return hash_ptr->indx;
@@ -1947,7 +1947,7 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
register tag_t *ptag_next;
register varray_t *vp = &cur_file_ptr->symbols;
register int scope_delta = 0;
- shash_t *hash_ptr = (shash_t *)0;
+ shash_t *hash_ptr = (shash_t *) 0;
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
@@ -1958,7 +1958,7 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
psym->st = (unsigned) type;
psym->sc = (unsigned) storage;
psym->index = indx;
- psym->iss = (str_start == (const char *)0)
+ psym->iss = (str_start == (const char *) 0)
? 0
: add_string (&cur_file_ptr->strings,
&cur_file_ptr->shash_head[0],
@@ -1973,7 +1973,7 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
/* Save the symbol within the hash table if this is a static
item, and it has a name. */
- if (hash_ptr != (shash_t *)0
+ if (hash_ptr != (shash_t *) 0
&& (type == st_Global || type == st_Static || type == st_Label
|| type == st_Proc || type == st_StaticProc))
hash_ptr->sym_ptr = psym;
@@ -2030,10 +2030,10 @@ add_local_symbol (str_start, str_end_p1, type, storage, value, indx)
cur_tag_head = ptag_head->prev;
for (ptag = ptag_head->first_tag;
- ptag != (tag_t *)0;
+ ptag != (tag_t *) 0;
ptag = ptag_next)
{
- if (ptag->forward_ref != (forward_t *)0)
+ if (ptag->forward_ref != (forward_t *) 0)
add_unknown_tag (ptag);
ptag_next = ptag->same_block;
@@ -2119,7 +2119,7 @@ add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
{
register EXTR *psym;
register varray_t *vp = &ext_symbols;
- shash_t *hash_ptr = (shash_t *)0;
+ shash_t *hash_ptr = (shash_t *) 0;
if (debug > 1)
{
@@ -2146,7 +2146,7 @@ add_ext_symbol (str_start, str_end_p1, type, storage, value, indx, ifd)
psym->asym.st = (unsigned) type;
psym->asym.sc = (unsigned) storage;
psym->asym.index = indx;
- psym->asym.iss = (str_start == (const char *)0)
+ psym->asym.iss = (str_start == (const char *) 0)
? 0
: add_string (&ext_strings,
&ext_str_hash[0],
@@ -2232,7 +2232,7 @@ add_aux_sym_tir (t, state, hash_tbl)
/* For anything that adds additional information, we must not hash,
- so check here, and reset our state. */
+ so check here, and reset our state. */
if (state != hash_no
&& (t->type_qualifiers[0] == tq_Array
@@ -2262,17 +2262,17 @@ add_aux_sym_tir (t, state, hash_tbl)
hi %= THASH_SIZE;
for (hash_ptr = hash_tbl[hi];
- hash_ptr != (thash_t *)0;
+ hash_ptr != (thash_t *) 0;
hash_ptr = hash_ptr->next)
{
if (aux.isym == hash_ptr->type.isym)
break;
}
- if (hash_ptr != (thash_t *)0 && state == hash_yes)
+ if (hash_ptr != (thash_t *) 0 && state == hash_yes)
return hash_ptr->indx;
- if (hash_ptr == (thash_t *)0)
+ if (hash_ptr == (thash_t *) 0)
{
hash_ptr = allocate_thash ();
hash_ptr->next = hash_tbl[hi];
@@ -2282,7 +2282,7 @@ add_aux_sym_tir (t, state, hash_tbl)
}
}
- /* Everything is set up, add the aux symbol. */
+ /* Everything is set up, add the aux symbol. */
if (vp->objects_last_page == vp->objects_per_page)
add_varray_page (vp);
@@ -2350,7 +2350,7 @@ add_aux_sym_tir (t, state, hash_tbl)
cur_file_ptr->int_type);
(void) add_aux_sym_symint (cur_file_ptr->file_index); /* file index*/
- (void) add_aux_sym_symint ((symint_t)0); /* low bound */
+ (void) add_aux_sym_symint ((symint_t) 0); /* low bound */
(void) add_aux_sym_symint (t->dimensions[i] - 1); /* high bound*/
(void) add_aux_sym_symint ((t->dimensions[i] == 0) /* stride */
? 0
@@ -2358,7 +2358,7 @@ add_aux_sym_tir (t, state, hash_tbl)
};
/* NOTE: Mips documentation claims that the bitfield width goes here.
- But it needs to be emitted earlier. */
+ But it needs to be emitted earlier. */
return ret;
}
@@ -2378,10 +2378,10 @@ get_tag (tag_start, tag_end_p1, indx, basic_type)
hash_ptr = hash_string (tag_start,
tag_end_p1 - tag_start,
&tag_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (hash_ptr != (shash_t *)0
- && hash_ptr->tag_ptr != (tag_t *)0)
+ if (hash_ptr != (shash_t *) 0
+ && hash_ptr->tag_ptr != (tag_t *) 0)
{
tag_ptr = hash_ptr->tag_ptr;
if (indx != indexNil)
@@ -2448,17 +2448,17 @@ add_unknown_tag (ptag)
name_end_p1,
st_Block,
sc_Info,
- (symint_t)0,
- (symint_t)0);
+ (symint_t) 0,
+ (symint_t) 0);
(void) add_local_symbol (name_start,
name_end_p1,
st_End,
sc_Info,
- (symint_t)0,
- (symint_t)0);
+ (symint_t) 0,
+ (symint_t) 0);
- while (f_next != (forward_t *)0)
+ while (f_next != (forward_t *) 0)
{
f_cur = f_next;
f_next = f_next->next;
@@ -2490,7 +2490,7 @@ add_procedure (func_start, func_end_p1)
register shash_t *shash_ptr = hash_string (func_start,
func_end_p1 - func_start,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
if (debug)
fputc ('\n', stderr);
@@ -2504,14 +2504,14 @@ add_procedure (func_start, func_end_p1)
/* Did the assembler create this procedure? If so, get the PDR information. */
- cur_oproc_ptr = (PDR *)0;
- if (shash_ptr != (shash_t *)0)
+ cur_oproc_ptr = (PDR *) 0;
+ if (shash_ptr != (shash_t *) 0)
{
register PDR *old_proc_ptr = shash_ptr->proc_ptr;
register SYMR *sym_ptr = shash_ptr->sym_ptr;
- if (old_proc_ptr != (PDR *)0
- && sym_ptr != (SYMR *)0
+ if (old_proc_ptr != (PDR *) 0
+ && sym_ptr != (SYMR *) 0
&& ((st_t)sym_ptr->st == st_Proc || (st_t)sym_ptr->st == st_StaticProc))
{
cur_oproc_begin = sym_ptr;
@@ -2524,17 +2524,17 @@ add_procedure (func_start, func_end_p1)
}
}
- if (cur_oproc_ptr == (PDR *)0)
+ if (cur_oproc_ptr == (PDR *) 0)
error ("Did not find a PDR block for %.*s", func_end_p1 - func_start, func_start);
- /* Determine the start of symbols. */
+ /* Determine the start of symbols. */
new_proc_ptr->isym = file_ptr->symbols.num_allocated;
/* Push the start of the function. */
(void) add_local_symbol (func_start, func_end_p1,
proc_type, sc_Text,
value,
- (symint_t)0);
+ (symint_t) 0);
}
@@ -2558,7 +2558,7 @@ add_file (file_start, file_end_p1)
/* See if the file has already been created. */
for (file_ptr = first_file;
- file_ptr != (efdr_t *)0;
+ file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
if (first_ch == file_ptr->name[0]
@@ -2570,14 +2570,14 @@ add_file (file_start, file_end_p1)
}
}
- /* If this is a new file, create it. */
- if (file_ptr == (efdr_t *)0)
+ /* If this is a new file, create it. */
+ if (file_ptr == (efdr_t *) 0)
{
if (file_desc.objects_last_page == file_desc.objects_per_page)
add_varray_page (&file_desc);
- file_ptr = cur_file_ptr =
- &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
+ file_ptr = cur_file_ptr
+ = &file_desc.last->datum->file[ file_desc.objects_last_page++ ];
*file_ptr = init_file;
file_ptr->file_index = file_desc.num_allocated++;
@@ -2590,7 +2590,7 @@ add_file (file_start, file_end_p1)
&file_ptr->shash_head[0],
&zero_bytes[0],
&zero_bytes[0],
- (shash_t **)0);
+ (shash_t **) 0);
if (file_end_p1 - file_start > PAGE_USIZE-2)
fatal ("Filename goes over one page boundary.");
@@ -2598,7 +2598,7 @@ add_file (file_start, file_end_p1)
/* Push the start of the filename. We assume that the filename
will be stored at string offset 1. */
(void) add_local_symbol (file_start, file_end_p1, st_File, sc_Text,
- (symint_t)0, (symint_t)0);
+ (symint_t) 0, (symint_t) 0);
file_ptr->fdr.rss = 1;
file_ptr->name = &file_ptr->strings.last->datum->byte[1];
file_ptr->name_len = file_end_p1 - file_start;
@@ -2745,7 +2745,7 @@ read_line __proto((void))
register int ch;
register char *ptr;
- if (cur_line_start == (char *)0)
+ if (cur_line_start == (char *) 0)
{ /* allocate initial page */
cur_line_start = (char *) allocate_page ();
cur_line_alloc = PAGE_SIZE;
@@ -2804,8 +2804,8 @@ read_line __proto((void))
if (ferror (stdin))
pfatal_with_name (input_name);
- cur_line_ptr = (char *)0;
- return (char *)0;
+ cur_line_ptr = (char *) 0;
+ return (char *) 0;
}
@@ -2820,13 +2820,13 @@ parse_begin (start)
int ch;
shash_t *hash_ptr; /* hash pointer to lookup label */
- if (cur_file_ptr == (efdr_t *)0)
+ if (cur_file_ptr == (efdr_t *) 0)
{
error ("#.begin directive without a preceding .file directive");
return;
}
- if (cur_proc_ptr == (PDR *)0)
+ if (cur_proc_ptr == (PDR *) 0)
{
error ("#.begin directive without a preceding .ent directive");
return;
@@ -2838,24 +2838,24 @@ parse_begin (start)
hash_ptr = hash_string (start,
end_p1 - start,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (hash_ptr == (shash_t *)0)
+ if (hash_ptr == (shash_t *) 0)
{
error ("Label %.*s not found for #.begin", end_p1 - start, start);
return;
}
- if (cur_oproc_begin == (SYMR *)0)
+ if (cur_oproc_begin == (SYMR *) 0)
{
error ("Procedure table %.*s not found for #.begin", end_p1 - start, start);
return;
}
- (void) add_local_symbol ((const char *)0, (const char *)0,
+ (void) add_local_symbol ((const char *) 0, (const char *) 0,
st_Block, sc_Text,
- (symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
- (symint_t)0);
+ (symint_t) hash_ptr->sym_ptr->value - cur_oproc_begin->value,
+ (symint_t) 0);
}
@@ -2870,13 +2870,13 @@ parse_bend (start)
int ch;
shash_t *hash_ptr; /* hash pointer to lookup label */
- if (cur_file_ptr == (efdr_t *)0)
+ if (cur_file_ptr == (efdr_t *) 0)
{
error ("#.begin directive without a preceding .file directive");
return;
}
- if (cur_proc_ptr == (PDR *)0)
+ if (cur_proc_ptr == (PDR *) 0)
{
error ("#.bend directive without a preceding .ent directive");
return;
@@ -2888,24 +2888,24 @@ parse_bend (start)
hash_ptr = hash_string (start,
end_p1 - start,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (hash_ptr == (shash_t *)0)
+ if (hash_ptr == (shash_t *) 0)
{
error ("Label %.*s not found for #.bend", end_p1 - start, start);
return;
}
- if (cur_oproc_begin == (SYMR *)0)
+ if (cur_oproc_begin == (SYMR *) 0)
{
error ("Procedure table %.*s not found for #.bend", end_p1 - start, start);
return;
}
- (void) add_local_symbol ((const char *)0, (const char *)0,
+ (void) add_local_symbol ((const char *) 0, (const char *) 0,
st_End, sc_Text,
(symint_t)hash_ptr->sym_ptr->value - cur_oproc_begin->value,
- (symint_t)0);
+ (symint_t) 0);
}
@@ -2929,12 +2929,12 @@ parse_def (name_start)
const char *arg_start; /* start of current argument */
const char *arg_end_p1; /* end+1 of current argument */
const char *name_end_p1; /* end+1 of label */
- const char *tag_start = (const char *)0; /* start of tag name */
- const char *tag_end_p1 = (const char *)0; /* end+1 of tag name */
+ const char *tag_start = (const char *) 0; /* start of tag name */
+ const char *tag_end_p1 = (const char *) 0; /* end+1 of tag name */
sc_t storage_class = sc_Nil;
st_t symbol_type = st_Nil;
type_info_t t;
- EXTR *eptr = (EXTR *)0; /* ext. sym equivalent to def*/
+ EXTR *eptr = (EXTR *) 0; /* ext. sym equivalent to def*/
int is_function = 0; /* != 0 if function */
symint_t value = 0;
symint_t indx = cur_file_ptr->void_type;
@@ -3002,7 +3002,7 @@ parse_def (name_start)
/* Pick up the subdirective argument now. */
arg_was_number = arg_number = 0;
- arg_end_p1 = (const char *)0;
+ arg_end_p1 = (const char *) 0;
arg_start = dir_end_p1+1;
ch = *arg_start;
while (ch == ' ' || ch == '\t')
@@ -3247,20 +3247,20 @@ parse_def (name_start)
ext_hash_ptr = hash_string (arg_start,
arg_end_p1 - arg_start,
&ext_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (ext_hash_ptr != (shash_t *)0
- && ext_hash_ptr->esym_ptr != (EXTR *)0)
+ if (ext_hash_ptr != (shash_t *) 0
+ && ext_hash_ptr->esym_ptr != (EXTR *) 0)
eptr = ext_hash_ptr->esym_ptr;
orig_hash_ptr = hash_string (arg_start,
arg_end_p1 - arg_start,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if ((orig_hash_ptr == (shash_t *)0
- || orig_hash_ptr->sym_ptr == (SYMR *)0)
- && eptr == (EXTR *)0)
+ if ((orig_hash_ptr == (shash_t *) 0
+ || orig_hash_ptr->sym_ptr == (SYMR *) 0)
+ && eptr == (EXTR *) 0)
{
fprintf (stderr, "warning, %.*s not found in original or external symbol tables, value defaults to 0\n",
arg_end_p1 - arg_start,
@@ -3269,8 +3269,8 @@ parse_def (name_start)
}
else
{
- SYMR *ptr = (orig_hash_ptr != (shash_t *)0
- && orig_hash_ptr->sym_ptr != (SYMR *)0)
+ SYMR *ptr = (orig_hash_ptr != (shash_t *) 0
+ && orig_hash_ptr->sym_ptr != (SYMR *) 0)
? orig_hash_ptr->sym_ptr
: &eptr->asym;
@@ -3294,14 +3294,22 @@ parse_def (name_start)
}
- t.extra_sizes = (tag_start != (char *)0);
+ if (storage_class == sc_Bits)
+ {
+ t.bitfield = 1;
+ t.extra_sizes = 1;
+ }
+ else
+ t.extra_sizes = 0;
+
if (t.num_dims > 0)
{
- int diff = t.num_dims - t.num_sizes;
+ int num_real_sizes = t.num_sizes - t.extra_sizes;
+ int diff = t.num_dims - num_real_sizes;
int i = t.num_dims - 1;
int j;
- if (t.num_sizes != 1 || diff < 0)
+ if (num_real_sizes != 1 || diff < 0)
{
error_line = __LINE__;
saber_stop ();
@@ -3312,7 +3320,6 @@ parse_def (name_start)
and sizes were passed, creating extra sizes for multiply
dimensioned arrays if not passed. */
- t.extra_sizes = 0;
if (diff)
{
for (j = (sizeof (t.sizes) / sizeof (t.sizes[0])) - 1; j >= 0; j--)
@@ -3329,14 +3336,6 @@ parse_def (name_start)
}
}
- else if (symbol_type == st_Member && t.num_sizes - t.extra_sizes == 1)
- { /* Is this a bitfield? This is indicated by a structure member
- having a size field that isn't an array. */
-
- t.bitfield = 1;
- }
-
-
/* Except for enumeration members & begin/ending of scopes, put the
type word in the aux. symbol table. */
@@ -3352,7 +3351,7 @@ parse_def (name_start)
|| t.basic_type == bt_Union
|| t.basic_type == bt_Enum)
{
- if (tag_start == (char *)0)
+ if (tag_start == (char *) 0)
{
error ("No tag specified for %.*s",
name_end_p1 - name_start,
@@ -3380,8 +3379,8 @@ parse_def (name_start)
/* If this is an external or static symbol, update the appropriate
external symbol. */
- if (eptr != (EXTR *)0
- && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *)0))
+ if (eptr != (EXTR *) 0
+ && (eptr->asym.index == indexNil || cur_proc_ptr == (PDR *) 0))
{
eptr->ifd = cur_file_ptr->file_index;
eptr->asym.index = indx;
@@ -3418,7 +3417,7 @@ parse_def (name_start)
that any error reporting above gives the correct name. */
case st_End:
- name_start = name_end_p1 = (const char *)0;
+ name_start = name_end_p1 = (const char *) 0;
value = inside_enumeration = 0;
break;
@@ -3440,9 +3439,9 @@ parse_def (name_start)
/* Add the symbol, except for global symbols outside of functions,
for which the external symbol table is fine enough. */
- if (eptr == (EXTR *)0
+ if (eptr == (EXTR *) 0
|| eptr->asym.st == (int)st_Nil
- || cur_proc_ptr != (PDR *)0)
+ || cur_proc_ptr != (PDR *) 0)
{
symint_t isym = add_local_symbol (name_start, name_end_p1,
symbol_type, storage_class,
@@ -3465,7 +3464,7 @@ parse_def (name_start)
forward_t *f_next = tag_ptr->forward_ref;
forward_t *f_cur;
- while (f_next != (forward_t *)0)
+ while (f_next != (forward_t *) 0)
{
f_cur = f_next;
f_next = f_next->next;
@@ -3476,7 +3475,7 @@ parse_def (name_start)
free_forward (f_cur);
}
- tag_ptr->forward_ref = (forward_t *)0;
+ tag_ptr->forward_ref = (forward_t *) 0;
}
}
@@ -3505,13 +3504,13 @@ parse_end (start)
register symint_t value;
register FDR *orig_fdr;
- if (cur_file_ptr == (efdr_t *)0)
+ if (cur_file_ptr == (efdr_t *) 0)
{
error (".end directive without a preceding .file directive");
return;
}
- if (cur_proc_ptr == (PDR *)0)
+ if (cur_proc_ptr == (PDR *) 0)
{
error (".end directive without a preceding .ent directive");
return;
@@ -3541,7 +3540,7 @@ parse_end (start)
orig_fdr = cur_file_ptr->orig_fdr;
value = 0;
- if (orig_fdr != (FDR *)0 && cur_oproc_end != (SYMR *)0)
+ if (orig_fdr != (FDR *)0 && cur_oproc_end != (SYMR *) 0)
value = cur_oproc_end->value;
else
@@ -3550,9 +3549,9 @@ parse_end (start)
(void) add_local_symbol (start_func, end_func_p1,
st_End, sc_Text,
value,
- (symint_t)0);
+ (symint_t) 0);
- cur_proc_ptr = cur_oproc_ptr = (PDR *)0;
+ cur_proc_ptr = cur_oproc_ptr = (PDR *) 0;
}
@@ -3565,13 +3564,13 @@ parse_ent (start)
register const char *start_func, *end_func_p1;
register int ch;
- if (cur_file_ptr == (efdr_t *)0)
+ if (cur_file_ptr == (efdr_t *) 0)
{
error (".ent directive without a preceding .file directive");
return;
}
- if (cur_proc_ptr != (PDR *)0)
+ if (cur_proc_ptr != (PDR *) 0)
{
error ("second .ent directive found before .end directive");
return;
@@ -3605,14 +3604,14 @@ parse_file (start)
(void) strtol (start, &p, 0);
if (start == p
- || (start_name = local_index (p, '"')) == (char *)0
- || (end_name_p1 = local_rindex (++start_name, '"')) == (char *)0)
+ || (start_name = local_index (p, '"')) == (char *) 0
+ || (end_name_p1 = local_rindex (++start_name, '"')) == (char *) 0)
{
error ("Invalid .file directive");
return;
}
- if (cur_proc_ptr != (PDR *)0)
+ if (cur_proc_ptr != (PDR *) 0)
{
error ("No way to handle .file within .ent/.end section");
return;
@@ -3630,7 +3629,7 @@ mark_stabs (start)
{
if (!stabs_seen)
{
- /* Add a dummy @stabs symbol. */
+ /* Add a dummy @stabs symbol. */
stabs_seen = 1;
(void) add_local_symbol (stabs_symbol,
stabs_symbol + sizeof (stabs_symbol),
@@ -3673,7 +3672,7 @@ STATIC void
parse_stabs_common (string_start, string_end, rest)
const char *string_start; /* start of string or NULL */
const char *string_end; /* end+1 of string or NULL */
- const char *rest; /* rest of the directive. */
+ const char *rest; /* rest of the directive. */
{
efdr_t *save_file_ptr = cur_file_ptr;
symint_t code;
@@ -3733,10 +3732,10 @@ parse_stabs_common (string_start, string_end, rest)
shash_ptr = hash_string (p,
strlen (p) - 1,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (shash_ptr == (shash_t *)0
- || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
+ if (shash_ptr == (shash_t *) 0
+ || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
{
error ("Invalid .stabs/.stabn directive, value not found");
return;
@@ -3796,27 +3795,27 @@ parse_stabs_common (string_start, string_end, rest)
const char *start, *end_p1;
start = p;
- if ((end_p1 = strchr (start, '+')) == (char *)0)
+ if ((end_p1 = strchr (start, '+')) == (char *) 0)
{
- if ((end_p1 = strchr (start, '-')) == (char *)0)
+ if ((end_p1 = strchr (start, '-')) == (char *) 0)
end_p1 = start + strlen(start) - 1;
}
shash_ptr = hash_string (start,
end_p1 - start,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (shash_ptr == (shash_t *)0
- || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *)0)
+ if (shash_ptr == (shash_t *) 0
+ || (sym_ptr = shash_ptr->sym_ptr) == (SYMR *) 0)
{
shash_ptr = hash_string (start,
end_p1 - start,
&ext_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (shash_ptr == (shash_t *)0
- || shash_ptr->esym_ptr == (EXTR *)0)
+ if (shash_ptr == (shash_t *) 0
+ || shash_ptr->esym_ptr == (EXTR *) 0)
{
error ("Invalid .stabs/.stabn directive, value not found");
return;
@@ -3825,8 +3824,8 @@ parse_stabs_common (string_start, string_end, rest)
sym_ptr = &(shash_ptr->esym_ptr->asym);
}
- /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */
- if (code == (int)N_LBRAC || code == (int)N_RBRAC)
+ /* Traditionally, N_LBRAC and N_RBRAC are *not* relocated. */
+ if (code == (int) N_LBRAC || code == (int) N_RBRAC)
{
sc = scNil;
st = stNil;
@@ -3874,7 +3873,7 @@ parse_stabs (start)
{
const char *end = local_index (start+1, '"');
- if (*start != '"' || end == (const char *)0 || end[1] != ',')
+ if (*start != '"' || end == (const char *) 0 || end[1] != ',')
{
error ("Invalid .stabs directive, no string");
return;
@@ -3888,7 +3887,7 @@ STATIC void
parse_stabn (start)
const char *start; /* start of directive */
{
- parse_stabs_common ((const char *)0, (const char *)0, start);
+ parse_stabs_common ((const char *) 0, (const char *) 0, start);
}
@@ -3914,7 +3913,7 @@ parse_input __proto((void))
ptag_head->prev = cur_tag_head;
cur_tag_head = ptag_head;
- while ((p = read_line ()) != (char *)0)
+ while ((p = read_line ()) != (char *) 0)
{
/* Skip leading blanks */
while (isspace (*p))
@@ -3939,10 +3938,10 @@ parse_input __proto((void))
cur_tag_head = ptag_head->prev;
for (ptag = ptag_head->first_tag;
- ptag != (tag_t *)0;
+ ptag != (tag_t *) 0;
ptag = ptag_next)
{
- if (ptag->forward_ref != (forward_t *)0)
+ if (ptag->forward_ref != (forward_t *) 0)
add_unknown_tag (ptag);
ptag_next = ptag->same_block;
@@ -3985,7 +3984,7 @@ update_headers __proto((void))
for the filename. */
for (file_ptr = first_file;
- file_ptr != (efdr_t *)0;
+ file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
register SYMR *sym_start;
@@ -4015,8 +4014,8 @@ update_headers __proto((void))
hash_ptr = hash_string (str,
(Ptrdiff_t)len,
&file_ptr->shash_head[0],
- (symint_t *)0);
- if (hash_ptr == (shash_t *)0)
+ (symint_t *) 0);
+ if (hash_ptr == (shash_t *) 0)
{
(void) add_local_symbol (str, str + len,
(st_t)sym->st, (sc_t)sym->sc,
@@ -4025,10 +4024,10 @@ update_headers __proto((void))
}
}
}
- (void) add_local_symbol ((const char *)0, (const char *)0,
+ (void) add_local_symbol ((const char *) 0, (const char *) 0,
st_End, sc_Text,
- (symint_t)0,
- (symint_t)0);
+ (symint_t) 0,
+ (symint_t) 0);
file_ptr->fdr.cpd = file_ptr->procs.num_allocated;
file_ptr->fdr.ipdFirst = symbolic_header.ipdMax;
@@ -4092,7 +4091,7 @@ update_headers __proto((void))
file_offset = ALIGN_SYMTABLE_OFFSET (file_offset);
}
- i = symbolic_header.iauxMax; /* aux syms. */
+ i = symbolic_header.iauxMax; /* aux syms. */
if (i > 0)
{
symbolic_header.cbAuxOffset = file_offset;
@@ -4164,9 +4163,9 @@ write_varray (vp, offset, str)
&& fseek (object_stream, (long)offset, SEEK_SET) < 0)
pfatal_with_name (object_name);
- for (ptr = vp->first; ptr != (vlinks_t *)0; ptr = ptr->next)
+ for (ptr = vp->first; ptr != (vlinks_t *) 0; ptr = ptr->next)
{
- num_write = (ptr->next == (vlinks_t *)0)
+ num_write = (ptr->next == (vlinks_t *) 0)
? vp->objects_last_page * vp->object_size
: vp->objects_per_page * vp->object_size;
@@ -4284,7 +4283,7 @@ write_object __proto((void))
{
offset = symbolic_header.cbPdOffset;
for (file_ptr = first_file;
- file_ptr != (efdr_t *)0;
+ file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->procs, offset, "Procedure tables");
@@ -4296,7 +4295,7 @@ write_object __proto((void))
{
offset = symbolic_header.cbSymOffset;
for (file_ptr = first_file;
- file_ptr != (efdr_t *)0;
+ file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->symbols, offset, "Local symbols");
@@ -4308,7 +4307,7 @@ write_object __proto((void))
{
offset = symbolic_header.cbAuxOffset;
for (file_ptr = first_file;
- file_ptr != (efdr_t *)0;
+ file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->aux_syms, offset, "Aux. symbols");
@@ -4320,7 +4319,7 @@ write_object __proto((void))
{
offset = symbolic_header.cbSsOffset;
for (file_ptr = first_file;
- file_ptr != (efdr_t *)0;
+ file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
write_varray (&file_ptr->strings, offset, "Local strings");
@@ -4340,7 +4339,7 @@ write_object __proto((void))
file_offset = offset;
for (file_ptr = first_file;
- file_ptr != (efdr_t *)0;
+ file_ptr != (efdr_t *) 0;
file_ptr = file_ptr->next_file)
{
if (debug)
@@ -4416,7 +4415,7 @@ read_seek (size, offset, str)
long sys_read = 0;
if (size == 0) /* nothing to read */
- return (page_t *)0;
+ return (page_t *) 0;
if (debug)
fprintf (stderr, "\trseek\tsize = %7u, offset = %7u, currently at %7u, %s\n",
@@ -4542,7 +4541,7 @@ copy_object __proto((void))
sections, so in theory no extra seeks are done.
For simplicity sake, round each read up to a page boundary,
- we may want to revisit this later.... */
+ we may want to revisit this later.... */
file_offset = orig_file_header.f_symptr + sizeof (struct filehdr);
@@ -4623,7 +4622,7 @@ copy_object __proto((void))
char *filename = orig_local_strs + (orig_files->issBase + orig_files->rss);
char *suffix = local_rindex (filename, '.');
- if (suffix != (char *)0 && strcmp (suffix, ".s") == 0)
+ if (suffix != (char *) 0 && strcmp (suffix, ".s") == 0)
delete_ifd = 1;
}
@@ -4670,7 +4669,7 @@ copy_object __proto((void))
(st_t) eptr->asym.st,
(sc_t) eptr->asym.sc,
eptr->asym.value,
- (symint_t)((eptr->asym.index == indexNil) ? indexNil : 0),
+ (symint_t) ((eptr->asym.index == indexNil) ? indexNil : 0),
(ifd < orig_sym_hdr.ifdMax) ? remap_file_number[ ifd ] : ifd);
}
@@ -4735,7 +4734,7 @@ copy_object __proto((void))
&orig_str_hash[0],
&hash_index);
- if (shash_ptr != (shash_t *)0)
+ if (shash_ptr != (shash_t *) 0)
error ("internal error, %s is already in original symbol table", str);
else
@@ -4763,9 +4762,9 @@ copy_object __proto((void))
register shash_t *shash_ptr = hash_string (str,
(Ptrdiff_t)len,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (shash_ptr != (shash_t *)0)
+ if (shash_ptr != (shash_t *) 0)
shash_ptr->end_ptr = sym;
}
}
@@ -4793,9 +4792,9 @@ copy_object __proto((void))
register shash_t *shash_ptr = hash_string (str,
(Ptrdiff_t)len,
&orig_str_hash[0],
- (symint_t *)0);
+ (symint_t *) 0);
- if (shash_ptr == (shash_t *)0)
+ if (shash_ptr == (shash_t *) 0)
error ("internal error, function %s is not in original symbol table", str);
else
@@ -4811,12 +4810,12 @@ copy_object __proto((void))
/* Copy all of the object file up to the symbol table. Originally
we were going to use ftruncate, but that doesn't seem to work
- on Ultrix 3.1.... */
+ on Ultrix 3.1.... */
- if (fseek (obj_in_stream, (long)0, SEEK_SET) != 0)
+ if (fseek (obj_in_stream, (long) 0, SEEK_SET) != 0)
pfatal_with_name (obj_in_name);
- if (fseek (object_stream, (long)0, SEEK_SET) != 0)
+ if (fseek (object_stream, (long) 0, SEEK_SET) != 0)
pfatal_with_name (object_name);
for (remaining = orig_file_header.f_symptr;
@@ -4910,7 +4909,7 @@ main (argc, argv)
break;
case 'I':
- if (rename_output || obj_in_name != (char *)0)
+ if (rename_output || obj_in_name != (char *) 0)
had_errors++;
else
rename_output = 1;
@@ -4918,7 +4917,7 @@ main (argc, argv)
/* fall through to 'i' case. */
case 'i':
- if (obj_in_name == (char *)0)
+ if (obj_in_name == (char *) 0)
{
obj_in_name = optarg;
iflag++;
@@ -4928,7 +4927,7 @@ main (argc, argv)
break;
case 'o':
- if (object_name == (char *)0)
+ if (object_name == (char *) 0)
object_name = optarg;
else
had_errors++;
@@ -4939,22 +4938,22 @@ main (argc, argv)
break;
}
- if (obj_in_name == (char *)0 && optind <= argc - 2)
+ if (obj_in_name == (char *) 0 && optind <= argc - 2)
obj_in_name = argv[--argc];
- if (object_name == (char *)0 && optind <= argc - 2)
+ if (object_name == (char *) 0 && optind <= argc - 2)
object_name = argv[--argc];
/* If there is an output name, but no input name use
the same file for both, deleting the name between
opening it for input and opening it for output. */
- if (obj_in_name == (char *)0 && object_name != (char *)0)
+ if (obj_in_name == (char *) 0 && object_name != (char *)0)
{
obj_in_name = object_name;
delete_input = 1;
}
- if (object_name == (char *)0 || had_errors || optind != argc - 1)
+ if (object_name == (char *) 0 || had_errors || optind != argc - 1)
{
fprintf (stderr, "Calling Sequence:\n");
fprintf (stderr, "\tmips-tfile [-d <num>] [-v] [-i <o-in-file>] -o <o-out-file> <s-file> (or)\n");
@@ -4979,7 +4978,7 @@ main (argc, argv)
fputc ('\n', stderr);
}
- if (obj_in_name == (char *)0)
+ if (obj_in_name == (char *) 0)
obj_in_name = object_name;
if (rename_output && rename (object_name, obj_in_name) != 0)
@@ -5024,14 +5023,14 @@ main (argc, argv)
/* Must open input before output, since the output may be the same file, and
we need to get the input handle before truncating it. */
obj_in_stream = fopen (obj_in_name, "r");
- if (obj_in_stream == (FILE *)0)
+ if (obj_in_stream == (FILE *) 0)
pfatal_with_name (obj_in_name);
if (delete_input && unlink (obj_in_name) != 0)
pfatal_with_name (obj_in_name);
object_stream = fopen (object_name, "w");
- if (object_stream == (FILE *)0)
+ if (object_stream == (FILE *) 0)
pfatal_with_name (object_name);
if (strcmp (argv[optind], "-") != 0)
@@ -5072,7 +5071,7 @@ STATIC void
catch_signal (signum)
int signum;
{
- (void) signal (signum, SIG_DFL); /* just in case... */
+ (void) signal (signum, SIG_DFL); /* just in case... */
#ifdef NO_SYS_SIGLIST
fatal ("caught signal");
#else
@@ -5087,7 +5086,7 @@ void
pfatal_with_name (msg)
char *msg;
{
- int save_errno = errno; /* just in case.... */
+ int save_errno = errno; /* just in case.... */
if (line_number > 0)
fprintf (stderr, "%s, %s:%ld ", progname, input_name, line_number);
else
@@ -5275,7 +5274,7 @@ allocate_scope __proto((void))
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int)alloc_type_scope ].free_list.f_scope;
- if (ptr != (scope_t *)0)
+ if (ptr != (scope_t *) 0)
alloc_counts[ (int)alloc_type_scope ].free_list.f_scope = ptr->free;
else
@@ -5432,7 +5431,7 @@ allocate_tag __proto((void))
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int)alloc_type_tag ].free_list.f_tag;
- if (ptr != (tag_t *)0)
+ if (ptr != (tag_t *) 0)
alloc_counts[ (int)alloc_type_tag ].free_list.f_tag = ptr->free;
else
@@ -5490,7 +5489,7 @@ allocate_forward __proto((void))
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int)alloc_type_forward ].free_list.f_forward;
- if (ptr != (forward_t *)0)
+ if (ptr != (forward_t *) 0)
alloc_counts[ (int)alloc_type_forward ].free_list.f_forward = ptr->free;
else
@@ -5548,7 +5547,7 @@ allocate_thead __proto((void))
#ifndef MALLOC_CHECK
ptr = alloc_counts[ (int)alloc_type_thead ].free_list.f_thead;
- if (ptr != (thead_t *)0)
+ if (ptr != (thead_t *) 0)
alloc_counts[ (int)alloc_type_thead ].free_list.f_thead = ptr->free;
else
@@ -5614,7 +5613,7 @@ fatal VPROTO((const char *format, ...))
VA_START (ap, format);
#ifndef __STDC__
- format = va_arg (ap, char*);
+ format = va_arg (ap, char *);
#endif
if (line_number > 0)
@@ -5644,7 +5643,7 @@ error VPROTO((const char *format, ...))
VA_START (ap, format);
#ifndef __STDC__
- format = va_arg (ap, char*);
+ format = va_arg (ap, char *);
#endif
if (line_number > 0)
@@ -5779,7 +5778,7 @@ local_index (str, sentinel)
for ( ; (ch = *str) != sentinel; str++)
{
if (ch == '\0')
- return (char *)0;
+ return (char *) 0;
}
return (char *)str;
@@ -5791,7 +5790,7 @@ local_rindex (str, sentinel)
int sentinel;
{
int ch;
- const char *ret = (const char *)0;
+ const char *ret = (const char *) 0;
for ( ; (ch = *str) != '\0'; str++)
{
diff --git a/gnu/usr.bin/gcc/objc/NXConstStr.h b/gnu/usr.bin/gcc/objc/NXConstStr.h
index 6899c74070b..b2c013e5c38 100644
--- a/gnu/usr.bin/gcc/objc/NXConstStr.h
+++ b/gnu/usr.bin/gcc/objc/NXConstStr.h
@@ -19,6 +19,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. */
+/* 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. */
+
#ifndef __nxconstantstring_INCLUDE_GNU
#define __nxconstantstring_INCLUDE_GNU
diff --git a/gnu/usr.bin/gcc/objc/NXConstStr.m b/gnu/usr.bin/gcc/objc/NXConstStr.m
index d3b21174366..d4db76880cd 100644
--- a/gnu/usr.bin/gcc/objc/NXConstStr.m
+++ b/gnu/usr.bin/gcc/objc/NXConstStr.m
@@ -19,6 +19,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. */
+/* 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. */
+
#include "objc/NXConstStr.h"
@implementation NXConstantString
diff --git a/gnu/usr.bin/gcc/objc/Object.m b/gnu/usr.bin/gcc/objc/Object.m
index 518d02a3a67..d6a10019773 100644
--- a/gnu/usr.bin/gcc/objc/Object.m
+++ b/gnu/usr.bin/gcc/objc/Object.m
@@ -1,5 +1,5 @@
/* The implementation of class Object for Objective-C.
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -29,8 +29,6 @@ Boston, MA 02111-1307, USA. */
#include "objc/Protocol.h"
#include "objc/objc-api.h"
-extern void (*_objc_error)(id object, const char *format, va_list);
-
extern int errno;
#define MAX_CLASS_NAME_LEN 256
@@ -215,7 +213,7 @@ extern int errno;
}
}
- if (parent = [self superClass])
+ if ((parent = [self superClass]))
return [parent conformsTo: aProtocol];
else
return NO;
@@ -337,7 +335,7 @@ extern size_t strlen(const char*);
object_is_instance(self)?"instance":"class",
(aString!=NULL)?aString:"");
va_start(ap, aString);
- (*_objc_error)(self, fmt, ap);
+ objc_error(self, OBJC_ERR_UNKNOWN, fmt, ap);
va_end(ap);
return nil;
#undef FMT
diff --git a/gnu/usr.bin/gcc/objc/archive.c b/gnu/usr.bin/gcc/objc/archive.c
index 0d5515270b4..af9591b25ec 100644
--- a/gnu/usr.bin/gcc/objc/archive.c
+++ b/gnu/usr.bin/gcc/objc/archive.c
@@ -1,5 +1,5 @@
/* GNU Objective C Runtime archiving
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@@ -24,10 +24,15 @@ Boston, MA 02111-1307, USA. */
however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */
+#include "config.h"
#include "runtime.h"
#include "typedstream.h"
#include "encoding.h"
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
extern int fflush(FILE*);
#define ROUND(V, A) \
@@ -37,11 +42,6 @@ extern int fflush(FILE*);
#define PTR2LONG(P) (((char*)(P))-(char*)0)
#define LONG2PTR(L) (((char*)0)+(L))
-#define __objc_fatal(format, args...) \
- { fprintf(stderr, "archiving: "); \
- fprintf(stderr, format, ## args); \
- fprintf(stderr, "\n"); abort(); }
-
/* Declare some functions... */
static int
@@ -141,7 +141,8 @@ __objc_code_unsigned_short (unsigned char* buf, unsigned short val)
}
int
-objc_write_unsigned_short (struct objc_typed_stream* stream, unsigned short value)
+objc_write_unsigned_short (struct objc_typed_stream* stream,
+ unsigned short value)
{
unsigned char buf[sizeof (unsigned short)+1];
int len = __objc_code_unsigned_short (buf, value);
@@ -252,7 +253,8 @@ __objc_code_unsigned_long (unsigned char* buf, unsigned long val)
}
int
-objc_write_unsigned_long (struct objc_typed_stream* stream, unsigned long value)
+objc_write_unsigned_long (struct objc_typed_stream* stream,
+ unsigned long value)
{
unsigned char buf[sizeof(unsigned long)+1];
int len = __objc_code_unsigned_long (buf, value);
@@ -315,7 +317,8 @@ objc_write_string_atomic (struct objc_typed_stream* stream,
}
static int
-objc_write_register_common (struct objc_typed_stream* stream, unsigned long key)
+objc_write_register_common (struct objc_typed_stream* stream,
+ unsigned long key)
{
unsigned char buf[sizeof (unsigned long)+2];
int len = __objc_code_unsigned_long (buf+1, key);
@@ -359,7 +362,11 @@ __objc_write_extension (struct objc_typed_stream* stream, unsigned char code)
return (*stream->write)(stream->physical, &buf, 1);
}
else
- abort();
+ {
+ objc_error(nil, OBJC_ERR_BAD_OPCODE,
+ "__objc_write_extension: bad opcode %c\n", code);
+ return -1;
+ }
}
__inline__ int
@@ -392,9 +399,10 @@ objc_write_object_reference (struct objc_typed_stream* stream, id object)
int
objc_write_root_object (struct objc_typed_stream* stream, id object)
{
- int len;
+ int len = 0;
if (stream->writing_root_p)
- __objc_fatal ("objc_write_root_object called recursively")
+ objc_error (nil, OBJC_ERR_RECURSE_ROOT,
+ "objc_write_root_object called recursively");
else
{
stream->writing_root_p = 1;
@@ -488,7 +496,8 @@ objc_write_selector (struct objc_typed_stream* stream, SEL selector)
else
{
int length;
- hash_add (&stream->stream_table, LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
+ hash_add (&stream->stream_table,
+ LONG2PTR(key=PTR2LONG(sel_name)), (char*)sel_name);
if ((length = objc_write_register_common (stream, key)))
return __objc_write_selector (stream, selector);
return length;
@@ -520,8 +529,9 @@ objc_read_char (struct objc_typed_stream* stream, char* val)
}
else
- __objc_fatal("expected 8bit signed int, got %dbit int",
- (int)(buf&_B_NUMBER)*8);
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected 8bit signed int, got %dbit int",
+ (int)(buf&_B_NUMBER)*8);
}
return len;
}
@@ -541,8 +551,9 @@ objc_read_unsigned_char (struct objc_typed_stream* stream, unsigned char* val)
len = (*stream->read)(stream->physical, val, 1);
else
- __objc_fatal("expected 8bit unsigned int, got %dbit int",
- (int)(buf&_B_NUMBER)*8);
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected 8bit unsigned int, got %dbit int",
+ (int)(buf&_B_NUMBER)*8);
}
return len;
}
@@ -562,7 +573,8 @@ objc_read_short (struct objc_typed_stream* stream, short* value)
int pos = 1;
int nbytes = buf[0] & _B_NUMBER;
if (nbytes > sizeof (short))
- __objc_fatal("expected short, got bigger (%dbits)", nbytes*8);
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected short, got bigger (%dbits)", nbytes*8);
len = (*stream->read)(stream->physical, buf+1, nbytes);
(*value) = 0;
while (pos <= nbytes)
@@ -590,7 +602,8 @@ objc_read_unsigned_short (struct objc_typed_stream* stream,
int pos = 1;
int nbytes = buf[0] & _B_NUMBER;
if (nbytes > sizeof (short))
- __objc_fatal("expected short, got int or bigger");
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected short, got int or bigger");
len = (*stream->read)(stream->physical, buf+1, nbytes);
(*value) = 0;
while (pos <= nbytes)
@@ -616,7 +629,7 @@ objc_read_int (struct objc_typed_stream* stream, int* value)
int pos = 1;
int nbytes = buf[0] & _B_NUMBER;
if (nbytes > sizeof (int))
- __objc_fatal("expected int, got bigger");
+ objc_error(nil, OBJC_ERR_BAD_DATA, "expected int, got bigger");
len = (*stream->read)(stream->physical, buf+1, nbytes);
(*value) = 0;
while (pos <= nbytes)
@@ -643,7 +656,7 @@ objc_read_long (struct objc_typed_stream* stream, long* value)
int pos = 1;
int nbytes = buf[0] & _B_NUMBER;
if (nbytes > sizeof (long))
- __objc_fatal("expected long, got bigger");
+ objc_error(nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
len = (*stream->read)(stream->physical, buf+1, nbytes);
(*value) = 0;
while (pos <= nbytes)
@@ -663,7 +676,7 @@ __objc_read_nbyte_uint (struct objc_typed_stream* stream,
unsigned char buf[sizeof(unsigned int)+1];
if (nbytes > sizeof (int))
- __objc_fatal("expected int, got bigger");
+ objc_error(nil, OBJC_ERR_BAD_DATA, "expected int, got bigger");
len = (*stream->read)(stream->physical, buf, nbytes);
(*val) = 0;
@@ -699,7 +712,7 @@ __objc_read_nbyte_ulong (struct objc_typed_stream* stream,
unsigned char buf[sizeof(unsigned long)+1];
if (nbytes > sizeof (long))
- __objc_fatal("expected long, got bigger");
+ objc_error(nil, OBJC_ERR_BAD_DATA, "expected long, got bigger");
len = (*stream->read)(stream->physical, buf, nbytes);
(*val) = 0;
@@ -747,7 +760,7 @@ objc_read_string (struct objc_typed_stream* stream,
case _B_SSTR:
{
int length = buf[0]&_B_VALUE;
- (*string) = (char*)__objc_xmalloc(length+1);
+ (*string) = (char*)objc_malloc(length+1);
if (key)
hash_add (&stream->stream_table, LONG2PTR(key), *string);
len = (*stream->read)(stream->physical, *string, length);
@@ -760,7 +773,7 @@ objc_read_string (struct objc_typed_stream* stream,
char *tmp;
len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
tmp = hash_value_for_key (stream->stream_table, LONG2PTR (key));
- *string = __objc_xmalloc (strlen(tmp) + 1);
+ *string = objc_malloc (strlen(tmp) + 1);
strcpy (*string, tmp);
}
break;
@@ -770,7 +783,7 @@ objc_read_string (struct objc_typed_stream* stream,
unsigned int nbytes = buf[0]&_B_VALUE;
len = __objc_read_nbyte_uint(stream, nbytes, &nbytes);
if (len) {
- (*string) = (char*)__objc_xmalloc(nbytes+1);
+ (*string) = (char*)objc_malloc(nbytes+1);
if (key)
hash_add (&stream->stream_table, LONG2PTR(key), *string);
len = (*stream->read)(stream->physical, *string, nbytes);
@@ -780,7 +793,8 @@ objc_read_string (struct objc_typed_stream* stream,
break;
default:
- __objc_fatal("expected string, got opcode %c\n", (buf[0]&_B_CODE));
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected string, got opcode %c\n", (buf[0]&_B_CODE));
}
}
@@ -825,13 +839,14 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
/* check null-byte */
len = (*stream->read)(stream->physical, buf, 1);
if (buf[0] != '\0')
- __objc_fatal("expected null-byte, got opcode %c", buf[0]);
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected null-byte, got opcode %c", buf[0]);
}
else if ((buf[0]&_B_CODE) == _B_UCOMM)
{
if (key)
- __objc_fatal("cannot register use upcode...");
+ objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
(*object) = hash_value_for_key (stream->object_table, LONG2PTR(key));
}
@@ -840,20 +855,24 @@ objc_read_object (struct objc_typed_stream* stream, id* object)
{
struct objc_list* other;
len = objc_read_unsigned_long (stream, &key);
- other = (struct objc_list*)hash_value_for_key (stream->object_refs, LONG2PTR(key));
- hash_add (&stream->object_refs, LONG2PTR(key), (void*)list_cons(object, other));
+ other = (struct objc_list*)hash_value_for_key (stream->object_refs,
+ LONG2PTR(key));
+ hash_add (&stream->object_refs, LONG2PTR(key),
+ (void*)list_cons(object, other));
}
else if (buf[0] == (_B_EXT | _BX_OBJROOT)) /* a root object */
{
if (key)
- __objc_fatal("cannot register root object...");
+ objc_error(nil, OBJC_ERR_BAD_KEY,
+ "cannot register root object...");
len = objc_read_object (stream, object);
__objc_finish_read_root_object (stream);
}
else
- __objc_fatal("expected object, got opcode %c", buf[0]);
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected object, got opcode %c", buf[0]);
}
return len;
}
@@ -881,7 +900,7 @@ objc_read_class (struct objc_typed_stream* stream, Class* class)
/* get class */
len = objc_read_string (stream, &class_name);
(*class) = objc_get_class(class_name);
- free (class_name);
+ objc_free(class_name);
/* register */
if (key)
@@ -894,15 +913,17 @@ objc_read_class (struct objc_typed_stream* stream, Class* class)
else if ((buf[0]&_B_CODE) == _B_UCOMM)
{
if (key)
- __objc_fatal("cannot register use upcode...");
+ objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
(*class) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
if (!*class)
- __objc_fatal("cannot find class for key %lu", key);
+ objc_error(nil, OBJC_ERR_BAD_CLASS,
+ "cannot find class for key %lu", key);
}
else
- __objc_fatal("expected class, got opcode %c", buf[0]);
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected class, got opcode %c", buf[0]);
}
return len;
}
@@ -936,7 +957,7 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
}
else
(*selector) = sel_get_any_uid(selector_name);
- free (selector_name);
+ objc_free(selector_name);
/* register */
if (key)
@@ -946,13 +967,15 @@ objc_read_selector (struct objc_typed_stream* stream, SEL* selector)
else if ((buf[0]&_B_CODE) == _B_UCOMM)
{
if (key)
- __objc_fatal("cannot register use upcode...");
+ objc_error(nil, OBJC_ERR_BAD_KEY, "cannot register use upcode...");
len = __objc_read_nbyte_ulong(stream, (buf[0] & _B_VALUE), &key);
- (*selector) = hash_value_for_key (stream->stream_table, LONG2PTR(key));
+ (*selector) = hash_value_for_key (stream->stream_table,
+ LONG2PTR(key));
}
else
- __objc_fatal("expected selector, got opcode %c", buf[0]);
+ objc_error(nil, OBJC_ERR_BAD_DATA,
+ "expected selector, got opcode %c", buf[0]);
}
return len;
}
@@ -1019,13 +1042,15 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
break;
case _C_ATOM:
- return objc_write_string_atomic (stream, *(char**)data, strlen(*(char**)data));
+ return objc_write_string_atomic (stream, *(char**)data,
+ strlen(*(char**)data));
break;
case _C_ARY_B:
{
int len = atoi(type+1);
- while (isdigit(*++type));
+ while (isdigit(*++type))
+ ;
return objc_write_array (stream, type, len, data);
}
break;
@@ -1034,8 +1059,9 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
{
int acc_size = 0;
int align;
- while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
- while (*type != _C_STRUCT_E);
+ while (*type != _C_STRUCT_E && *type++ != '=')
+ ; /* skip "<name>=" */
+ while (*type != _C_STRUCT_E)
{
align = objc_alignof_type (type); /* padd to alignment */
acc_size += ROUND (acc_size, align);
@@ -1047,8 +1073,11 @@ objc_write_type(TypedStream* stream, const char* type, const void* data)
}
default:
- fprintf(stderr, "objc_write_type: cannot parse typespec: %s\n", type);
- abort();
+ {
+ objc_error(nil, OBJC_ERR_BAD_TYPE,
+ "objc_write_type: cannot parse typespec: %s\n", type);
+ return 0;
+ }
}
}
@@ -1116,7 +1145,8 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
case _C_ARY_B:
{
int len = atoi(type+1);
- while (isdigit(*++type));
+ while (isdigit(*++type))
+ ;
return objc_read_array (stream, type, len, data);
}
break;
@@ -1125,8 +1155,9 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
{
int acc_size = 0;
int align;
- while (*type != _C_STRUCT_E && *type++ != '='); /* skip "<name>=" */
- while (*type != _C_STRUCT_E);
+ while (*type != _C_STRUCT_E && *type++ != '=')
+ ; /* skip "<name>=" */
+ while (*type != _C_STRUCT_E)
{
align = objc_alignof_type (type); /* padd to alignment */
acc_size += ROUND (acc_size, align);
@@ -1138,8 +1169,11 @@ objc_read_type(TypedStream* stream, const char* type, void* data)
}
default:
- fprintf(stderr, "objc_read_type: cannot parse typespec: %s\n", type);
- abort();
+ {
+ objc_error(nil, OBJC_ERR_BAD_TYPE,
+ "objc_read_type: cannot parse typespec: %s\n", type);
+ return 0;
+ }
}
}
@@ -1229,17 +1263,18 @@ objc_write_types (TypedStream* stream, const char* type, ...)
{
int len = atoi(c+1);
const char* t = c;
- while (isdigit(*++t));
+ while (isdigit(*++t))
+ ;
res = objc_write_array (stream, t, len, va_arg(args, void*));
t = objc_skip_typespec (t);
if (*t != _C_ARY_E)
- __objc_fatal("expected `]', got: %s", t);
+ objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
}
break;
default:
- fprintf(stderr, "objc_write_types: cannot parse typespec: %s\n", type);
- abort();
+ objc_error(nil, OBJC_ERR_BAD_TYPE,
+ "objc_write_types: cannot parse typespec: %s\n", type);
}
}
va_end(args);
@@ -1320,17 +1355,18 @@ objc_read_types(TypedStream* stream, const char* type, ...)
{
int len = atoi(c+1);
const char* t = c;
- while (isdigit(*++t));
+ while (isdigit(*++t))
+ ;
res = objc_read_array (stream, t, len, va_arg(args, void*));
t = objc_skip_typespec (t);
if (*t != _C_ARY_E)
- __objc_fatal("expected `]', got: %s", t);
+ objc_error(nil, OBJC_ERR_BAD_TYPE, "expected `]', got: %s", t);
}
break;
default:
- fprintf(stderr, "objc_read_types: cannot parse typespec: %s\n", type);
- abort();
+ objc_error(nil, OBJC_ERR_BAD_TYPE,
+ "objc_read_types: cannot parse typespec: %s\n", type);
}
}
va_end(args);
@@ -1379,12 +1415,6 @@ objc_read_array (TypedStream* stream, const char* type,
return 1;
}
-static void
-__objc_free (void* p)
-{
- free (p);
-}
-
static int
__objc_fread(FILE* file, char* data, int len)
{
@@ -1406,13 +1436,15 @@ __objc_feof(FILE* file)
static int
__objc_no_write(FILE* file, char* data, int len)
{
- __objc_fatal ("TypedStream not open for writing");
+ objc_error (nil, OBJC_ERR_NO_WRITE, "TypedStream not open for writing");
+ return 0;
}
static int
__objc_no_read(FILE* file, char* data, int len)
{
- __objc_fatal ("TypedStream not open for reading");
+ objc_error (nil, OBJC_ERR_NO_READ, "TypedStream not open for reading");
+ return 0;
}
static int
@@ -1422,10 +1454,12 @@ __objc_read_typed_stream_signature (TypedStream* stream)
int pos = 0;
do
(*stream->read)(stream->physical, buffer+pos, 1);
- while (buffer[pos++] != '\0');
+ while (buffer[pos++] != '\0')
+ ;
sscanf (buffer, "GNU TypedStream %d", &stream->version);
if (stream->version != OBJC_TYPED_STREAM_VERSION)
- __objc_fatal ("cannot handle TypedStream version %d", stream->version);
+ objc_error (nil, OBJC_ERR_STREAM_VERSION,
+ "cannot handle TypedStream version %d", stream->version);
return 1;
}
@@ -1450,11 +1484,12 @@ static void __objc_finish_write_root_object(struct objc_typed_stream* stream)
static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
{
node_ptr node;
- struct objc_list* free_list;
SEL awake_sel = sel_get_any_uid ("awake");
+ cache_ptr free_list = hash_new (64,
+ (hash_func_type) hash_ptr,
+ (compare_func_type) compare_ptrs);
/* resolve object forward references */
- free_list = list_cons(NULL, NULL);
for (node = hash_next (stream->object_refs, NULL); node;
node = hash_next (stream->object_refs, node))
{
@@ -1464,13 +1499,19 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
while(reflist)
{
*((id*)reflist->head) = object;
- if (list_find(&free_list, reflist) == NULL)
- free_list = list_cons (reflist, free_list);
+ if (hash_value_for_key (free_list,reflist) == NULL)
+ hash_add (&free_list,reflist,reflist);
+
reflist = reflist->tail;
}
}
- list_mapcar (free_list, __objc_free);
- list_free (free_list);
+
+ /* apply __objc_free to all objects stored in free_list */
+ for (node = hash_next (free_list, NULL); node;
+ node = hash_next (free_list, node))
+ objc_free ((void *) node->key);
+
+ hash_delete (free_list);
/* empty object reference table */
hash_delete (stream->object_refs);
@@ -1503,7 +1544,7 @@ static void __objc_finish_read_root_object(struct objc_typed_stream* stream)
TypedStream*
objc_open_typed_stream (FILE* physical, int mode)
{
- TypedStream* s = (TypedStream*)__objc_xmalloc(sizeof(TypedStream));
+ TypedStream* s = (TypedStream*)objc_malloc(sizeof(TypedStream));
s->mode = mode;
s->physical = physical;
@@ -1590,7 +1631,7 @@ objc_close_typed_stream (TypedStream* stream)
if (stream->type == (OBJC_MANAGED_STREAM | OBJC_FILE_STREAM))
fclose ((FILE*)stream->physical);
- free (stream);
+ objc_free(stream);
}
BOOL
diff --git a/gnu/usr.bin/gcc/objc/class.c b/gnu/usr.bin/gcc/objc/class.c
index 3617a098803..44aa1b9f98e 100644
--- a/gnu/usr.bin/gcc/objc/class.c
+++ b/gnu/usr.bin/gcc/objc/class.c
@@ -1,5 +1,5 @@
/* GNU Objective C Runtime class related functions
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup and Dennis Glatting.
This file is part of GNU CC.
@@ -27,16 +27,16 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "sarray.h"
/* The table of classname->class. Used for objc_lookup_class and friends */
-static cache_ptr __objc_class_hash = 0;
+static cache_ptr __objc_class_hash = 0; /* !T:MUTEX */
/* This is a hook which is called by objc_get_class and
objc_lookup_class if the runtime is not able to find the class.
This may e.g. try to load in the class using dynamic loading */
-Class (*_objc_lookup_class)(const char* name) = 0;
+Class (*_objc_lookup_class)(const char* name) = 0; /* !T:SAFE */
/* True when class links has been resolved */
-BOOL __objc_class_links_resolved = NO;
+BOOL __objc_class_links_resolved = NO; /* !T:UNUSED */
/* Initial number of buckets size of class hash table. */
@@ -49,10 +49,14 @@ void __objc_init_class_tables()
if(__objc_class_hash)
return;
+ objc_mutex_lock(__objc_runtime_mutex);
+
__objc_class_hash
= hash_new (CLASS_HASH_SIZE,
(hash_func_type) hash_string,
(compare_func_type) compare_strings);
+
+ objc_mutex_unlock(__objc_runtime_mutex);
}
/* This function adds a class to the class hash table, and assigns the
@@ -62,6 +66,8 @@ __objc_add_class_to_hash(Class class)
{
Class h_class;
+ objc_mutex_lock(__objc_runtime_mutex);
+
/* make sure the table is there */
assert(__objc_class_hash);
@@ -82,6 +88,8 @@ __objc_add_class_to_hash(Class class)
++class_number;
hash_add (&__objc_class_hash, class->name, class);
}
+
+ objc_mutex_unlock(__objc_runtime_mutex);
}
/* Get the class object for the class named NAME. If NAME does not
@@ -91,11 +99,15 @@ Class objc_lookup_class (const char* name)
{
Class class;
+ objc_mutex_lock(__objc_runtime_mutex);
+
/* Make sure the class hash table exists. */
assert (__objc_class_hash);
class = hash_value_for_key (__objc_class_hash, name);
+ objc_mutex_unlock(__objc_runtime_mutex);
+
if (class)
return class;
@@ -113,11 +125,15 @@ objc_get_class (const char *name)
{
Class class;
+ objc_mutex_lock(__objc_runtime_mutex);
+
/* Make sure the class hash table exists. */
assert (__objc_class_hash);
class = hash_value_for_key (__objc_class_hash, name);
+ objc_mutex_unlock(__objc_runtime_mutex);
+
if (class)
return class;
@@ -127,8 +143,9 @@ objc_get_class (const char *name)
if(class)
return class;
- fprintf(stderr, "objc runtime: cannot find class %s\n", name);
- abort();
+ objc_error(nil, OBJC_ERR_BAD_CLASS,
+ "objc runtime: cannot find class %s\n", name);
+ return 0;
}
MetaClass
@@ -149,11 +166,16 @@ objc_get_meta_class(const char *name)
Class
objc_next_class(void **enum_state)
{
+ objc_mutex_lock(__objc_runtime_mutex);
+
/* make sure the table is there */
assert(__objc_class_hash);
*(node_ptr*)enum_state =
hash_next(__objc_class_hash, *(node_ptr*)enum_state);
+
+ objc_mutex_unlock(__objc_runtime_mutex);
+
if (*(node_ptr*)enum_state)
return (*(node_ptr*)enum_state)->value;
return (Class)0;
@@ -169,6 +191,8 @@ void __objc_resolve_class_links()
assert(object_class);
+ objc_mutex_lock(__objc_runtime_mutex);
+
/* Assign subclass links */
for (node = hash_next (__objc_class_hash, NULL); node;
node = hash_next (__objc_class_hash, node))
@@ -234,6 +258,8 @@ void __objc_resolve_class_links()
sub_class->class_pointer->super_class = class1->class_pointer;
}
}
+
+ objc_mutex_unlock(__objc_runtime_mutex);
}
@@ -281,7 +307,8 @@ class_pose_as (Class impostor, Class super_class)
if (CLS_ISCLASS (sub))
{
/* meta classes */
- CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list;
+ CLASSOF (sub)->sibling_class =
+ CLASSOF (impostor)->subclass_list;
CLASSOF (sub)->super_class = CLASSOF (impostor);
CLASSOF (impostor)->subclass_list = CLASSOF (sub);
}
@@ -307,6 +334,8 @@ class_pose_as (Class impostor, Class super_class)
what the keys of the hashtable is, change all values that are
superclass into impostor. */
+ objc_mutex_lock(__objc_runtime_mutex);
+
for (node = hash_next (__objc_class_hash, NULL); node;
node = hash_next (__objc_class_hash, node))
{
@@ -317,6 +346,8 @@ class_pose_as (Class impostor, Class super_class)
}
}
+ objc_mutex_unlock(__objc_runtime_mutex);
+
/* next, we update the dispatch tables... */
__objc_update_dispatch_table_for_class (CLASSOF (impostor));
__objc_update_dispatch_table_for_class (impostor);
diff --git a/gnu/usr.bin/gcc/objc/encoding.c b/gnu/usr.bin/gcc/objc/encoding.c
index 9620664746b..acd6b7a7b73 100644
--- a/gnu/usr.bin/gcc/objc/encoding.c
+++ b/gnu/usr.bin/gcc/objc/encoding.c
@@ -1,5 +1,5 @@
/* Encoding of types for Objective C.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@@ -153,7 +153,10 @@ objc_sizeof_type(const char* type)
}
default:
- abort();
+ {
+ objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
+ return 0;
+ }
}
}
@@ -218,6 +221,7 @@ objc_alignof_type(const char* type)
return __alignof__(double);
break;
+ case _C_PTR:
case _C_ATOM:
case _C_CHARPTR:
return __alignof__(char*);
@@ -250,7 +254,10 @@ objc_alignof_type(const char* type)
}
default:
- abort();
+ {
+ objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
+ return 0;
+ }
}
}
@@ -341,6 +348,7 @@ objc_skip_typespec (const char* type)
case _C_FLT:
case _C_DBL:
case _C_VOID:
+ case _C_UNDEF:
return ++type;
break;
@@ -352,7 +360,10 @@ objc_skip_typespec (const char* type)
if (*type == _C_ARY_E)
return ++type;
else
- abort();
+ {
+ objc_error(nil, OBJC_ERR_BAD_TYPE, "bad array type %s\n", type);
+ return 0;
+ }
case _C_STRUCT_B:
/* skip name, and elements until closing '}' */
@@ -374,7 +385,10 @@ objc_skip_typespec (const char* type)
return objc_skip_typespec (++type);
default:
- abort();
+ {
+ objc_error(nil, OBJC_ERR_BAD_TYPE, "unknown type %s\n", type);
+ return 0;
+ }
}
}
diff --git a/gnu/usr.bin/gcc/objc/encoding.h b/gnu/usr.bin/gcc/objc/encoding.h
index c956034108a..141e9fe9e97 100644
--- a/gnu/usr.bin/gcc/objc/encoding.h
+++ b/gnu/usr.bin/gcc/objc/encoding.h
@@ -1,5 +1,5 @@
/* Encoding of types for Objective C.
- Copyright (C) 1993 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1997 Free Software Foundation, Inc.
Author: Kresten Krab Thorup
@@ -57,7 +57,7 @@ const char* objc_skip_typespec (const char* type);
const char* objc_skip_offset (const char* type);
const char* objc_skip_argspec (const char* type);
int method_get_number_of_arguments (struct objc_method*);
-int method_get_size_of_arguments (struct objc_method*);
+int method_get_sizeof_arguments (struct objc_method*);
char* method_get_first_argument (struct objc_method*,
arglist_t argframe,
diff --git a/gnu/usr.bin/gcc/objc/hash.h b/gnu/usr.bin/gcc/objc/hash.h
index 7a83b0854d1..bddb791c820 100644
--- a/gnu/usr.bin/gcc/objc/hash.h
+++ b/gnu/usr.bin/gcc/objc/hash.h
@@ -1,5 +1,5 @@
/* Hash tables for Objective C method dispatch.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */
#define __hash_INCLUDE_GNU
#include <stddef.h>
+#include <objc/objc.h>
/*
* This data structure is used to hold items
@@ -140,6 +141,9 @@ node_ptr hash_next (cache_ptr cache, node_ptr node);
void *hash_value_for_key (cache_ptr cache, const void *key);
+/* Used to determine if the given key exists in the hash table */
+
+BOOL hash_is_key_in_hash (cache_ptr cache, const void *key);
/************************************************
diff --git a/gnu/usr.bin/gcc/objc/init.c b/gnu/usr.bin/gcc/objc/init.c
index 9560dc20234..c900cac65e8 100644
--- a/gnu/usr.bin/gcc/objc/init.c
+++ b/gnu/usr.bin/gcc/objc/init.c
@@ -1,6 +1,7 @@
/* GNU Objective C Runtime initialization
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
+ +load support contributed by Ovidiu Predescu <ovidiu@net-community.com>
This file is part of GNU CC.
@@ -27,17 +28,23 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* The version number of this runtime. This must match the number
defined in gcc (objc-act.c) */
-#define OBJC_VERSION 7
+#define OBJC_VERSION 8
#define PROTOCOL_VERSION 2
/* This list contains all modules currently loaded into the runtime */
-static struct objc_list* __objc_module_list = 0;
+static struct objc_list* __objc_module_list = 0; /* !T:MUTEX */
/* This list contains all proto_list's not yet assigned class links */
-static struct objc_list* unclaimed_proto_list = 0;
+static struct objc_list* unclaimed_proto_list = 0; /* !T:MUTEX */
/* List of unresolved static instances. */
-static struct objc_list *uninitialized_statics;
+static struct objc_list *uninitialized_statics = 0; /* !T:MUTEX */
+
+/* Global runtime "write" mutex. */
+objc_mutex_t __objc_runtime_mutex = 0;
+
+/* Number of threads that are alive. */
+int __objc_runtime_threads_alive = 1; /* !T:MUTEX */
/* Check compiler vs runtime version */
static void init_check_module_version (Module_t);
@@ -52,23 +59,335 @@ static void __objc_class_add_protocols (Class, struct objc_protocol_list*);
or a category is loaded into the runtime. This may e.g. help a
dynamic loader determine the classes that have been loaded when
an object file is dynamically linked in */
-void (*_objc_load_callback)(Class class, Category* category) = 0;
+void (*_objc_load_callback)(Class class, Category* category); /* !T:SAFE */
/* Is all categories/classes resolved? */
-BOOL __objc_dangling_categories = NO;
+BOOL __objc_dangling_categories = NO; /* !T:UNUSED */
extern SEL
__sel_register_typed_name (const char *name, const char *types,
- struct objc_selector *orig);
+ struct objc_selector *orig, BOOL is_const);
+
+/* Sends +load to all classes and categories in certain situations. */
+static void objc_send_load (void);
+
+/* Inserts all the classes defined in module in a tree of classes that
+ resembles the class hierarchy. This tree is traversed in preorder and the
+ classes in its nodes receive the +load message if these methods were not
+ executed before. The algorithm ensures that when the +load method of a class
+ is executed all the superclasses have been already received the +load
+ message. */
+static void __objc_create_classes_tree (Module_t module);
+
+static void __objc_call_callback (Module_t module);
+
+/* A special version that works only before the classes are completely
+ installed in the runtime. */
+static BOOL class_is_subclass_of_class (Class class, Class superclass);
+
+typedef struct objc_class_tree {
+ Class class;
+ struct objc_list *subclasses; /* `head' is pointer to an objc_class_tree */
+} objc_class_tree;
+
+/* This is a linked list of objc_class_tree trees. The head of these trees
+ are root classes (their super class is Nil). These different trees
+ represent different class hierarchies. */
+static struct objc_list *__objc_class_tree_list = NULL;
+
+/* Keeps the +load methods who have been already executed. This hash should
+ not be destroyed during the execution of the program. */
+static cache_ptr __objc_load_methods = NULL;
+
+/* Creates a tree of classes whose topmost class is directly inherited from
+ `upper' and the bottom class in this tree is `bottom_class'. The classes
+ in this tree are super classes of `bottom_class'. `subclasses' member
+ of each tree node point to the next subclass tree node. */
+static objc_class_tree *
+create_tree_of_subclasses_inherited_from (Class bottom_class, Class upper)
+{
+ Class superclass = bottom_class->super_class ?
+ objc_lookup_class ((char*)bottom_class->super_class)
+ : Nil;
+
+ objc_class_tree *tree, *prev;
+
+ DEBUG_PRINTF ("create_tree_of_subclasses_inherited_from:");
+ DEBUG_PRINTF ("bottom_class = %s, upper = %s\n",
+ (bottom_class ? bottom_class->name : NULL),
+ (upper ? upper->name : NULL));
+
+ tree = prev = objc_calloc (1, sizeof (objc_class_tree));
+ prev->class = bottom_class;
+
+ while (superclass != upper)
+ {
+ tree = objc_calloc (1, sizeof (objc_class_tree));
+ tree->class = superclass;
+ tree->subclasses = list_cons (prev, tree->subclasses);
+ superclass = (superclass->super_class ?
+ objc_lookup_class ((char*)superclass->super_class)
+ : Nil);
+ prev = tree;
+ }
+
+ return tree;
+}
+
+/* Insert the `class' into the proper place in the `tree' class hierarchy. This
+ function returns a new tree if the class has been successfully inserted into
+ the tree or NULL if the class is not part of the classes hierarchy described
+ by `tree'. This function is private to objc_tree_insert_class(), you should
+ not call it directly. */
+static objc_class_tree *
+__objc_tree_insert_class (objc_class_tree *tree, Class class)
+{
+ DEBUG_PRINTF ("__objc_tree_insert_class: tree = %x, class = %s\n",
+ tree, class->name);
+
+ if (tree == NULL)
+ return create_tree_of_subclasses_inherited_from (class, NULL);
+ else if (class == tree->class)
+ {
+ /* `class' has been already inserted */
+ DEBUG_PRINTF ("1. class %s was previously inserted\n", class->name);
+ return tree;
+ }
+ else if ((class->super_class ?
+ objc_lookup_class ((char*)class->super_class)
+ : Nil)
+ == tree->class)
+ {
+ /* If class is a direct subclass of tree->class then add class to the
+ list of subclasses. First check to see if it wasn't already
+ inserted. */
+ struct objc_list *list = tree->subclasses;
+ objc_class_tree *node;
+
+ while (list)
+ {
+ /* Class has been already inserted; do nothing just return
+ the tree. */
+ if (((objc_class_tree*)list->head)->class == class)
+ {
+ DEBUG_PRINTF ("2. class %s was previously inserted\n",
+ class->name);
+ return tree;
+ }
+ list = list->tail;
+ }
+
+ /* Create a new node class and insert it into the list of subclasses */
+ node = objc_calloc (1, sizeof (objc_class_tree));
+ node->class = class;
+ tree->subclasses = list_cons (node, tree->subclasses);
+ DEBUG_PRINTF ("3. class %s inserted\n", class->name);
+ return tree;
+ }
+ else
+ {
+ /* The class is not a direct subclass of tree->class. Search for class's
+ superclasses in the list of subclasses. */
+ struct objc_list *subclasses = tree->subclasses;
+
+ /* Precondition: the class must be a subclass of tree->class; otherwise
+ return NULL to indicate our caller that it must take the next tree. */
+ if (!class_is_subclass_of_class (class, tree->class))
+ return NULL;
+
+ for (; subclasses != NULL; subclasses = subclasses->tail)
+ {
+ Class aClass = ((objc_class_tree*)(subclasses->head))->class;
+
+ if (class_is_subclass_of_class (class, aClass))
+ {
+ /* If we found one of class's superclasses we insert the class
+ into its subtree and return the original tree since nothing
+ has been changed. */
+ subclasses->head
+ = __objc_tree_insert_class (subclasses->head, class);
+ DEBUG_PRINTF ("4. class %s inserted\n", class->name);
+ return tree;
+ }
+ }
+
+ /* We haven't found a subclass of `class' in the `subclasses' list.
+ Create a new tree of classes whose topmost class is a direct subclass
+ of tree->class. */
+ {
+ objc_class_tree *new_tree
+ = create_tree_of_subclasses_inherited_from (class, tree->class);
+ tree->subclasses = list_cons (new_tree, tree->subclasses);
+ DEBUG_PRINTF ("5. class %s inserted\n", class->name);
+ return tree;
+ }
+ }
+}
+
+/* This function inserts `class' in the right tree hierarchy classes. */
+static void
+objc_tree_insert_class (Class class)
+{
+ struct objc_list *list_node;
+ objc_class_tree *tree;
+
+ list_node = __objc_class_tree_list;
+ while (list_node)
+ {
+ tree = __objc_tree_insert_class (list_node->head, class);
+ if (tree)
+ {
+ list_node->head = tree;
+ break;
+ }
+ else
+ list_node = list_node->tail;
+ }
+
+ /* If the list was finished but the class hasn't been inserted, insert it
+ here. */
+ if (!list_node)
+ {
+ __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
+ __objc_class_tree_list->head = __objc_tree_insert_class (NULL, class);
+ }
+}
+
+/* Traverse tree in preorder. Used to send +load. */
+static void
+objc_preorder_traverse (objc_class_tree *tree,
+ int level,
+ void (*function)(objc_class_tree*, int))
+{
+ struct objc_list *node;
+
+ (*function) (tree, level);
+ for (node = tree->subclasses; node; node = node->tail)
+ objc_preorder_traverse (node->head, level + 1, function);
+}
+
+/* Traverse tree in postorder. Used to destroy a tree. */
+static void
+objc_postorder_traverse (objc_class_tree *tree,
+ int level,
+ void (*function)(objc_class_tree*, int))
+{
+ struct objc_list *node;
+
+ for (node = tree->subclasses; node; node = node->tail)
+ objc_postorder_traverse (node->head, level + 1, function);
+ (*function) (tree, level);
+}
+
+/* Used to print a tree class hierarchy. */
+static void
+__objc_tree_print (objc_class_tree *tree, int level)
+{
+ int i;
+
+ for (i = 0; i < level; i++)
+ printf (" ");
+ printf ("%s\n", tree->class->name);
+}
+
+/* Walks on a linked list of methods in the reverse order and executes all
+ the methods corresponding to `op' selector. Walking in the reverse order
+ assures the +load of class is executed first and then +load of categories
+ because of the way in which categories are added to the class methods. */
+static void
+__objc_send_message_in_list (MethodList_t method_list, Class class, SEL op)
+{
+ int i;
+
+ if (!method_list)
+ return;
+
+ /* First execute the `op' message in the following method lists */
+ __objc_send_message_in_list (method_list->method_next, class, op);
+
+ /* Search the method list. */
+ for (i = 0; i < method_list->method_count; i++)
+ {
+ Method_t mth = &method_list->method_list[i];
+
+ if (mth->method_name && sel_eq (mth->method_name, op)
+ && !hash_is_key_in_hash (__objc_load_methods, mth->method_name))
+ {
+ /* The method was found and wasn't previously executed. */
+ (*mth->method_imp) ((id)class, mth->method_name);
+
+ /* Add this method into the +load hash table */
+ hash_add (&__objc_load_methods, mth->method_imp, mth->method_imp);
+
+ DEBUG_PRINTF ("sending +load in class: %s\n", class->name);
+
+ break;
+ }
+ }
+}
+
+static void
+__objc_send_load (objc_class_tree *tree, int level)
+{
+ static SEL load_sel = 0;
+ Class class = tree->class;
+ MethodList_t method_list = class->class_pointer->methods;
+
+ if (!load_sel)
+ load_sel = sel_register_name ("load");
+
+ __objc_send_message_in_list (method_list, class, load_sel);
+}
+
+static void
+__objc_destroy_class_tree_node (objc_class_tree *tree, int level)
+{
+ objc_free (tree);
+}
+
+/* This is used to check if the relationship between two classes before the
+ runtime completely installs the classes. */
+static BOOL
+class_is_subclass_of_class (Class class, Class superclass)
+{
+ for (; class != Nil;)
+ {
+ if (class == superclass)
+ return YES;
+ class = (class->super_class ?
+ objc_lookup_class ((char*)class->super_class)
+ : Nil);
+ }
+
+ return NO;
+}
+
+/* This list contains all the classes in the runtime system for whom their
+ superclasses are not yet know to the runtime. */
+static struct objc_list* unresolved_classes = 0;
+
+/* Static function used to reference the Object and NXConstantString classes.
+ */
+static void
+__objc_force_linking (void)
+{
+ extern void __objc_linking (void);
+ __objc_linking ();
+
+ /* Call the function to avoid compiler warning */
+ __objc_force_linking ();
+}
/* Run through the statics list, removing modules as soon as all its statics
have been initialized. */
static void
-objc_init_statics ()
+objc_init_statics (void)
{
struct objc_list **cell = &uninitialized_statics;
struct objc_static_instances **statics_in_module;
+ objc_mutex_lock(__objc_runtime_mutex);
+
while (*cell)
{
int module_initialized = 1;
@@ -109,11 +428,13 @@ objc_init_statics ()
/* Remove this module from the uninitialized list. */
struct objc_list *this = *cell;
*cell = this->tail;
- free (this);
+ objc_free(this);
}
else
cell = &(*cell)->tail;
}
+
+ objc_mutex_unlock(__objc_runtime_mutex);
} /* objc_init_statics */
/* This function is called by constructor functions generated for each
@@ -133,6 +454,10 @@ __objc_exec_class (Module_t module)
/* The symbol table (defined in objc-api.h) generated by gcc */
Symtab_t symtab = module->symtab;
+ /* The statics in this module */
+ struct objc_static_instances **statics
+ = symtab->defs[symtab->cls_def_cnt + symtab->cat_def_cnt];
+
/* Entry used to traverse hash lists */
struct objc_list** cell;
@@ -150,13 +475,22 @@ __objc_exec_class (Module_t module)
/* On the first call of this routine, initialize some data structures. */
if (!previous_constructors)
{
+ /* Initialize thread-safe system */
+ __objc_init_thread_system();
+ __objc_runtime_threads_alive = 1;
+ __objc_runtime_mutex = objc_mutex_allocate();
+
__objc_init_selector_tables();
__objc_init_class_tables();
__objc_init_dispatch_tables();
+ __objc_class_tree_list = list_cons (NULL, __objc_class_tree_list);
+ __objc_load_methods
+ = hash_new (128, (hash_func_type)hash_ptr, compare_ptrs);
previous_constructors = 1;
}
/* Save the module pointer for later processing. (not currently used) */
+ objc_mutex_lock(__objc_runtime_mutex);
__objc_module_list = list_cons(module, __objc_module_list);
/* Replace referenced selectors from names to SEL's. */
@@ -167,8 +501,11 @@ __objc_exec_class (Module_t module)
const char *name, *type;
name = (char*)selectors[i].sel_id;
type = (char*)selectors[i].sel_types;
+ /* Constructors are constant static data so we can safely store
+ pointers to them in the runtime structures. is_const == YES */
__sel_register_typed_name (name, type,
- (struct objc_selector*)&(selectors[i]));
+ (struct objc_selector*)&(selectors[i]),
+ YES);
}
}
@@ -177,12 +514,17 @@ __objc_exec_class (Module_t module)
for (i = 0; i < symtab->cls_def_cnt; ++i)
{
Class class = (Class) symtab->defs[i];
+ const char* superclass = (char*)class->super_class;
/* Make sure we have what we think. */
assert (CLS_ISCLASS(class));
assert (CLS_ISMETA(class->class_pointer));
DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
+ /* Initialize the subclass list to be NULL.
+ In some cases it isn't and this crashes the program. */
+ class->subclass_list = NULL;
+
/* Store the class in the class table and assign class numbers. */
__objc_add_class_to_hash (class);
@@ -194,11 +536,17 @@ __objc_exec_class (Module_t module)
__objc_install_premature_dtable(class);
__objc_install_premature_dtable(class->class_pointer);
+ /* Register the instance methods as class methods, this is
+ only done for root classes. */
+ __objc_register_instance_methods_to_class(class);
+
if (class->protocols)
__objc_init_protocols (class->protocols);
- if (_objc_load_callback)
- _objc_load_callback(class, 0);
+ /* Check to see if the superclass is known in this point. If it's not
+ add the class to the unresolved_classes list. */
+ if (superclass && !objc_lookup_class (superclass))
+ unresolved_classes = list_cons (class, unresolved_classes);
}
/* Process category information from the module. */
@@ -230,8 +578,9 @@ __objc_exec_class (Module_t module)
__objc_class_add_protocols (class, category->protocols);
}
- if (_objc_load_callback)
- _objc_load_callback(class, category);
+ /* Register the instance methods as class methods, this is
+ only done for root classes. */
+ __objc_register_instance_methods_to_class(class);
}
else
{
@@ -241,8 +590,8 @@ __objc_exec_class (Module_t module)
}
}
- if (module->statics)
- uninitialized_statics = list_cons (module->statics, uninitialized_statics);
+ if (statics)
+ uninitialized_statics = list_cons (statics, uninitialized_statics);
if (uninitialized_statics)
objc_init_statics ();
@@ -268,15 +617,16 @@ __objc_exec_class (Module_t module)
if (category->class_methods)
class_add_method_list ((Class) class->class_pointer,
category->class_methods);
-
+
if (category->protocols)
{
__objc_init_protocols (category->protocols);
__objc_class_add_protocols (class, category->protocols);
}
-
- if (_objc_load_callback)
- _objc_load_callback(class, category);
+
+ /* Register the instance methods as class methods, this is
+ only done for root classes. */
+ __objc_register_instance_methods_to_class(class);
}
}
@@ -287,6 +637,119 @@ __objc_exec_class (Module_t module)
unclaimed_proto_list = 0;
}
+ objc_send_load ();
+
+ objc_mutex_unlock(__objc_runtime_mutex);
+}
+
+static void objc_send_load (void)
+{
+ if (!__objc_module_list)
+ return;
+
+ /* Try to find out if all the classes loaded so far also have their
+ superclasses known to the runtime. We suppose that the objects that are
+ allocated in the +load method are in general of a class declared in the
+ same module. */
+ if (unresolved_classes)
+ {
+ Class class = unresolved_classes->head;
+
+ while (objc_lookup_class ((char*)class->super_class))
+ {
+ list_remove_head (&unresolved_classes);
+ if (unresolved_classes)
+ class = unresolved_classes->head;
+ else
+ break;
+ }
+
+ /*
+ * If we still have classes for whom we don't have yet their super
+ * classes known to the runtime we don't send the +load messages.
+ */
+ if (unresolved_classes)
+ return;
+ }
+
+ /* Special check to allow creating and sending messages to constant strings
+ in +load methods. If these classes are not yet known, even if all the
+ other classes are known, delay sending of +load. */
+ if (!objc_lookup_class ("NXConstantString") ||
+ !objc_lookup_class ("Object"))
+ return;
+
+ /* Iterate over all modules in the __objc_module_list and call on them the
+ __objc_create_classes_tree function. This function creates a tree of
+ classes that resembles the class hierarchy. */
+ list_mapcar (__objc_module_list, (void(*)(void*))__objc_create_classes_tree);
+
+ while (__objc_class_tree_list)
+ {
+#ifdef DEBUG
+ objc_preorder_traverse (__objc_class_tree_list->head,
+ 0, __objc_tree_print);
+#endif
+ objc_preorder_traverse (__objc_class_tree_list->head,
+ 0, __objc_send_load);
+ objc_postorder_traverse (__objc_class_tree_list->head,
+ 0, __objc_destroy_class_tree_node);
+ list_remove_head (&__objc_class_tree_list);
+ }
+
+ list_mapcar (__objc_module_list, (void(*)(void*))__objc_call_callback);
+ list_free (__objc_module_list);
+ __objc_module_list = NULL;
+}
+
+static void
+__objc_create_classes_tree (Module_t module)
+{
+ /* The runtime mutex is locked in this point */
+
+ Symtab_t symtab = module->symtab;
+ int i;
+
+ /* Iterate thru classes defined in this module and insert them in the classes
+ tree hierarchy. */
+ for (i = 0; i < symtab->cls_def_cnt; i++)
+ {
+ Class class = (Class) symtab->defs[i];
+
+ objc_tree_insert_class (class);
+ }
+}
+
+static void
+__objc_call_callback (Module_t module)
+{
+ /* The runtime mutex is locked in this point */
+
+ Symtab_t symtab = module->symtab;
+ int i;
+
+ /* Iterate thru classes defined in this module and call the callback for
+ each one. */
+ for (i = 0; i < symtab->cls_def_cnt; i++)
+ {
+ Class class = (Class) symtab->defs[i];
+
+ /* Call the _objc_load_callback for this class. */
+ if (_objc_load_callback)
+ _objc_load_callback(class, 0);
+ }
+
+ /* Call the _objc_load_callback for categories. Don't register the instance
+ methods as class methods for categories to root classes since they were
+ already added in the class. */
+ for (i = 0; i < symtab->cat_def_cnt; i++)
+ {
+ Category_t category = symtab->defs[i + symtab->cls_def_cnt];
+ Class class = objc_lookup_class (category->class_name);
+
+ if (_objc_load_callback)
+ _objc_load_callback(class, category);
+ }
}
/* Sanity check the version of gcc used to compile `module'*/
@@ -294,15 +757,17 @@ static void init_check_module_version(Module_t module)
{
if ((module->version != OBJC_VERSION) || (module->size != sizeof (Module)))
{
- fprintf (stderr, "Module %s version %d doesn't match runtime %d\n",
- module->name, (int)module->version, OBJC_VERSION);
+ int code;
+
if(module->version > OBJC_VERSION)
- fprintf (stderr, "Runtime (libobjc.a) is out of date\n");
+ code = OBJC_ERR_OBJC_VERSION;
else if (module->version < OBJC_VERSION)
- fprintf (stderr, "Compiler (gcc) is out of date\n");
+ code = OBJC_ERR_GCC_VERSION;
else
- fprintf (stderr, "Objective C internal error -- bad Module size\n");
- abort ();
+ code = OBJC_ERR_MODULE_SIZE;
+
+ objc_error(nil, code, "Module %s version %d doesn't match runtime %d\n",
+ module->name, (int)module->version, OBJC_VERSION);
}
}
@@ -315,12 +780,15 @@ __objc_init_protocols (struct objc_protocol_list* protos)
if (! protos)
return;
+ objc_mutex_lock(__objc_runtime_mutex);
+
if (!proto_class)
proto_class = objc_lookup_class("Protocol");
if (!proto_class)
{
unclaimed_proto_list = list_cons (protos, unclaimed_proto_list);
+ objc_mutex_unlock(__objc_runtime_mutex);
return;
}
@@ -341,13 +809,14 @@ __objc_init_protocols (struct objc_protocol_list* protos)
}
else if (protos->list[i]->class_pointer != proto_class)
{
- fprintf (stderr,
- "Version %d doesn't match runtime protocol version %d\n",
- (int)((char*)protos->list[i]->class_pointer-(char*)0),
- PROTOCOL_VERSION);
- abort ();
+ objc_error(nil, OBJC_ERR_PROTOCOL_VERSION,
+ "Version %d doesn't match runtime protocol version %d\n",
+ (int)((char*)protos->list[i]->class_pointer-(char*)0),
+ PROTOCOL_VERSION);
}
}
+
+ objc_mutex_unlock(__objc_runtime_mutex);
}
static void __objc_class_add_protocols (Class class,
diff --git a/gnu/usr.bin/gcc/objc/makefile.dos b/gnu/usr.bin/gcc/objc/makefile.dos
index 5321733a234..3e1b1871e40 100644
--- a/gnu/usr.bin/gcc/objc/makefile.dos
+++ b/gnu/usr.bin/gcc/objc/makefile.dos
@@ -1,5 +1,5 @@
# GNU Objective C Runtime Makefile for compiling with djgpp
-# Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+# Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
#
# This file is part of GNU CC.
#
@@ -37,17 +37,17 @@ SUBDIR_INCLUDES = -I. -I.. -I../config
-c $(GCC_CFLAGS) $(SUBDIR_INCLUDES) $<
OBJC_O = hash.o sarray.o class.o sendmsg.o init.o archive.o \
- selector.o objects.o misc.o object.o protocol.o encoding.o
+ selector.o objects.o misc.o object.o protocol.o encoding.o thread.o
libobjc.a: $(OBJC_O)
-rm -f libobjc.a
ar rc libobjc.a $(OBJC_O)
ranlib libobjc.a
-OBJC_H = hash.h list.h sarray.h objc.h \
+OBJC_H = hash.h objc-list.h sarray.h objc.h \
objc-api.h \
object.h protocol.h mutex.h \
- typedstream.h
+ typedstream.h thread.h
mostlyclean:
-rm -f *.o libobjc.a xforward fflags
diff --git a/gnu/usr.bin/gcc/objc/misc.c b/gnu/usr.bin/gcc/objc/misc.c
index 033018ed484..01f9d3bbafa 100644
--- a/gnu/usr.bin/gcc/objc/misc.c
+++ b/gnu/usr.bin/gcc/objc/misc.c
@@ -1,7 +1,6 @@
/* GNU Objective C Runtime Miscellaneous
- Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
-
-Author: Kresten Krab Thorup
+ Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@@ -26,55 +25,128 @@ Boston, MA 02111-1307, USA. */
however invalidate any other reasons why the executable file might be
covered by the GNU General Public License. */
-#ifdef __alpha__
+#define __USE_FIXED_PROTOTYPES__
#include <stdlib.h>
-extern int write (int, const char*, int);
-extern size_t strlen (const char*);
-#endif
-
#include "runtime.h"
-void objc_error(id object, const char* fmt, va_list);
+/*
+** Error handler function
+** NULL so that default is to just print to stderr
+*/
+static objc_error_handler _objc_error_handler = NULL;
+
+/* Trigger an objc error */
+void
+objc_error(id object, int code, const char* fmt, ...)
+{
+ va_list ap;
-void (*_objc_error)(id, const char*, va_list) = objc_error;
+ va_start(ap, fmt);
+ objc_verror(object, code, fmt, ap);
+ va_end(ap);
+}
+/* Trigger an objc error */
void
-objc_error(id object, const char* fmt, va_list ap)
+objc_verror(id object, int code, const char* fmt, va_list ap)
+{
+ BOOL result = NO;
+
+ /* Call the error handler if its there
+ Otherwise print to stderr */
+ if (_objc_error_handler)
+ result = (*_objc_error_handler)(object, code, fmt, ap);
+ else
+ vfprintf (stderr, fmt, ap);
+
+ /* Continue if the error handler says its ok
+ Otherwise abort the program */
+ if (result)
+ return;
+ else
+ abort();
+}
+
+/* Set the error handler */
+objc_error_handler
+objc_set_error_handler(objc_error_handler func)
+{
+ objc_error_handler temp = _objc_error_handler;
+ _objc_error_handler = func;
+ return temp;
+}
+
+/*
+** Standard functions for memory allocation and disposal.
+** Users should use these functions in their ObjC programs so
+** that they work properly with garbage collectors as well as
+** can take advantage of the exception/error handling available.
+*/
+
+void *
+objc_malloc(size_t size)
{
- vfprintf (stderr, fmt, ap);
- abort ();
+ void* res = (void*) (*_objc_malloc)(size);
+ if(!res)
+ objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+ return res;
}
-volatile void
-objc_fatal(const char* msg)
+void *
+objc_atomic_malloc(size_t size)
{
- write(2, msg, (int)strlen((const char*)msg));
- abort();
+ void* res = (void*) (*_objc_atomic_malloc)(size);
+ if(!res)
+ objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
+ return res;
}
-void*
-__objc_xmalloc(size_t size)
+void *
+objc_valloc(size_t size)
{
- void* res = (void*) malloc(size);
+ void* res = (void*) (*_objc_valloc)(size);
if(!res)
- objc_fatal("Virtual memory exhausted\n");
+ objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res;
}
-void*
-__objc_xrealloc(void* mem, size_t size)
+void *
+objc_realloc(void *mem, size_t size)
{
- void* res = (void*) realloc(mem, size);
+ void* res = (void*) (*_objc_realloc)(mem, size);
if(!res)
- objc_fatal("Virtual memory exhausted\n");
+ objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res;
}
-void*
-__objc_xcalloc(size_t nelem, size_t size)
+void *
+objc_calloc(size_t nelem, size_t size)
{
- void* res = (void*)calloc(nelem, size);
+ void* res = (void*) (*_objc_calloc)(nelem, size);
if(!res)
- objc_fatal("Virtual memory exhausted\n");
+ objc_error(nil, OBJC_ERR_MEMORY, "Virtual memory exhausted\n");
return res;
}
+
+void
+objc_free(void *mem)
+{
+ (*_objc_free)(mem);
+}
+
+/*
+** Hook functions for memory allocation and disposal.
+** This makes it easy to substitute garbage collection systems
+** such as Boehm's GC by assigning these function pointers
+** to the GC's allocation routines. By default these point
+** to the ANSI standard malloc, realloc, free, etc.
+**
+** Users should call the normal objc routines above for
+** memory allocation and disposal within their programs.
+*/
+void *(*_objc_malloc)(size_t) = malloc;
+void *(*_objc_atomic_malloc)(size_t) = malloc;
+void *(*_objc_valloc)(size_t) = malloc;
+void *(*_objc_realloc)(void *, size_t) = realloc;
+void *(*_objc_calloc)(size_t, size_t) = calloc;
+void (*_objc_free)(void *) = free;
diff --git a/gnu/usr.bin/gcc/objc/objc-api.h b/gnu/usr.bin/gcc/objc/objc-api.h
index c801033abe6..860aee4206a 100644
--- a/gnu/usr.bin/gcc/objc/objc-api.h
+++ b/gnu/usr.bin/gcc/objc/objc-api.h
@@ -1,5 +1,5 @@
/* GNU Objective-C Runtime API.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -29,7 +29,9 @@ Boston, MA 02111-1307, USA. */
#include "objc/objc.h"
#include "objc/hash.h"
+#include "objc/thr.h"
#include <stdio.h>
+#include <stdarg.h>
/* For functions which return Method_t */
#define METHOD_NULL (Method_t)0
@@ -73,6 +75,59 @@ struct objc_method_description
#define _C_STRUCT_E '}'
+/*
+** Error handling
+**
+** Call objc_error() or objc_verror() to record an error; this error
+** routine will generally exit the program but not necessarily if the
+** user has installed his own error handler.
+**
+** Call objc_set_error_handler to assign your own function for
+** handling errors. The function should return YES if it is ok
+** to continue execution, or return NO or just abort if the
+** program should be stopped. The default error handler is just to
+** print a message on stderr.
+**
+** The error handler function should be of type objc_error_handler
+** The first parameter is an object instance of relevance.
+** The second parameter is an error code.
+** The third parameter is a format string in the printf style.
+** The fourth parameter is a variable list of arguments.
+*/
+extern void objc_error(id object, int code, const char* fmt, ...);
+extern void objc_verror(id object, int code, const char* fmt, va_list ap);
+typedef BOOL (*objc_error_handler)(id, int code, const char *fmt, va_list ap);
+objc_error_handler objc_set_error_handler(objc_error_handler func);
+
+/*
+** Error codes
+** These are used by the runtime library, and your
+** error handling may use them to determine if the error is
+** hard or soft thus whether execution can continue or abort.
+*/
+#define OBJC_ERR_UNKNOWN 0 /* Generic error */
+
+#define OBJC_ERR_OBJC_VERSION 1 /* Incorrect runtime version */
+#define OBJC_ERR_GCC_VERSION 2 /* Incorrect compiler version */
+#define OBJC_ERR_MODULE_SIZE 3 /* Bad module size */
+#define OBJC_ERR_PROTOCOL_VERSION 4 /* Incorrect protocol version */
+
+#define OBJC_ERR_MEMORY 10 /* Out of memory */
+
+#define OBJC_ERR_RECURSE_ROOT 20 /* Attempt to archive the root
+ object more than once. */
+#define OBJC_ERR_BAD_DATA 21 /* Didn't read expected data */
+#define OBJC_ERR_BAD_KEY 22 /* Bad key for object */
+#define OBJC_ERR_BAD_CLASS 23 /* Unknown class */
+#define OBJC_ERR_BAD_TYPE 24 /* Bad type specification */
+#define OBJC_ERR_NO_READ 25 /* Cannot read stream */
+#define OBJC_ERR_NO_WRITE 26 /* Cannot write stream */
+#define OBJC_ERR_STREAM_VERSION 27 /* Incorrect stream version */
+#define OBJC_ERR_BAD_OPCODE 28 /* Bad opcode */
+
+#define OBJC_ERR_UNIMPLEMENTED 30 /* Method is not implemented */
+
+#define OBJC_ERR_BAD_STATE 40 /* Bad thread state */
/*
** Set this variable nonzero to print a line describing each
@@ -81,6 +136,16 @@ struct objc_method_description
extern BOOL objc_trace;
+/* For every class which happens to have statically allocated instances in
+ this module, one OBJC_STATIC_INSTANCES is allocated by the compiler.
+ INSTANCES is NULL terminated and points to all statically allocated
+ instances of this class. */
+struct objc_static_instances
+{
+ char *class_name;
+ id instances[0];
+};
+
/*
** Whereas a Module (defined further down) is the root (typically) of a file,
** a Symtab is the root of the class and category definitions within the
@@ -97,23 +162,16 @@ typedef struct objc_symtab {
unsigned short cat_def_cnt; /* Number of categories
compiled (defined) in the
module. */
+
void *defs[1]; /* Variable array of pointers.
cls_def_cnt of type Class
followed by cat_def_cnt of
- type Category_t. */
+ type Category_t, followed
+ by a NULL terminated array
+ of objc_static_instances. */
} Symtab, *Symtab_t;
-/* For every class which happens to have statically allocated instances in
- this module, one OBJC_STATIC_INSTANCES is allocated by the compiler.
- INSTANCES is NULL terminated and points to all statically allocated
- instances of this class. */
-struct objc_static_instances
-{
- char *class_name;
- id instances[0];
-};
-
/*
** The compiler generates one of these structures for each module that
** composes the executable (eg main.m).
@@ -130,12 +188,10 @@ typedef struct objc_module {
module was generated. The
name includes the path. */
- /* Pointer to a NULL terminated array of objc_static_instances. */
- struct objc_static_instances **statics;
-
Symtab_t symtab; /* Pointer to the Symtab of
the module. The Symtab
- holds an array of pointers to
+ holds an array of
+ pointers to
the classes and categories
defined in the module. */
} Module, *Module_t;
@@ -308,12 +364,54 @@ extern Class (*_objc_lookup_class)(const char *name);
*/
extern void (*_objc_load_callback)(Class class, Category* category);
+/*
+** Hook functions for allocating, copying and disposing of instances
+*/
extern id (*_objc_object_alloc)(Class class);
-
extern id (*_objc_object_copy)(id object);
-
extern id (*_objc_object_dispose)(id object);
+/*
+** Standard functions for memory allocation and disposal.
+** Users should use these functions in their ObjC programs so
+** that they work properly with garbage collectors as well as
+** can take advantage of the exception/error handling available.
+*/
+void *
+objc_malloc(size_t size);
+
+void *
+objc_atomic_malloc(size_t size);
+
+void *
+objc_valloc(size_t size);
+
+void *
+objc_realloc(void *mem, size_t size);
+
+void *
+objc_calloc(size_t nelem, size_t size);
+
+void
+objc_free(void *mem);
+
+/*
+** Hook functions for memory allocation and disposal.
+** This makes it easy to substitute garbage collection systems
+** such as Boehm's GC by assigning these function pointers
+** to the GC's allocation routines. By default these point
+** to the ANSI standard malloc, realloc, free, etc.
+**
+** Users should call the normal objc routines above for
+** memory allocation and disposal within their programs.
+*/
+extern void *(*_objc_malloc)(size_t);
+extern void *(*_objc_atomic_malloc)(size_t);
+extern void *(*_objc_valloc)(size_t);
+extern void *(*_objc_realloc)(void *, size_t);
+extern void *(*_objc_calloc)(size_t, size_t);
+extern void (*_objc_free)(void *);
+
Method_t class_get_class_method(MetaClass class, SEL aSel);
Method_t class_get_instance_method(Class class, SEL aSel);
@@ -405,6 +503,12 @@ method_get_imp(Method_t method)
IMP get_imp (Class class, SEL sel);
+/* Redefine on NeXTSTEP so as not to conflict with system function */
+#ifdef __NeXT__
+#define object_copy gnu_object_copy
+#define object_dispose gnu_object_dispose
+#endif
+
id object_copy(id object);
id object_dispose(id object);
@@ -471,6 +575,9 @@ object_is_meta_class(id object)
return CLS_ISMETA((Class)object);
}
+struct sarray*
+objc_get_uninstalled_dtable(void);
+
#endif /* not __objc_api_INCLUDE_GNU */
diff --git a/gnu/usr.bin/gcc/objc/objc.h b/gnu/usr.bin/gcc/objc/objc.h
index 979c5c81126..e48b0fd5bfb 100644
--- a/gnu/usr.bin/gcc/objc/objc.h
+++ b/gnu/usr.bin/gcc/objc/objc.h
@@ -1,5 +1,5 @@
/* Basic data types for Objective C.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -36,7 +36,11 @@ extern "C" {
/*
** Definition of the boolean type.
*/
+#ifdef __vxworks
+typedef int BOOL;
+#else
typedef unsigned char BOOL;
+#endif
#define YES (BOOL)1
#define NO (BOOL)0
@@ -103,9 +107,9 @@ struct objc_class {
unsigned long info; /* Bit mask. See class masks
defined above. */
long instance_size; /* Size in bytes of the class.
- The sum of the class definition
- and all super class
- definitions. */
+ The sum of the class
+ definition and all super
+ class definitions. */
struct objc_ivar_list* ivars; /* Pointer to a structure that
describes the instance
variables in the class
diff --git a/gnu/usr.bin/gcc/objc/objects.c b/gnu/usr.bin/gcc/objc/objects.c
index ebaf11765ac..3e68334c924 100644
--- a/gnu/usr.bin/gcc/objc/objects.c
+++ b/gnu/usr.bin/gcc/objc/objects.c
@@ -1,5 +1,5 @@
/* GNU Objective C Runtime class related functions
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@@ -31,9 +31,9 @@ id __objc_object_alloc(Class);
id __objc_object_dispose(id);
id __objc_object_copy(id);
-id (*_objc_object_alloc)(Class) = __objc_object_alloc;
-id (*_objc_object_dispose)(id) = __objc_object_dispose;
-id (*_objc_object_copy)(id) = __objc_object_copy;
+id (*_objc_object_alloc)(Class) = __objc_object_alloc; /* !T:SINGLE */
+id (*_objc_object_dispose)(id) = __objc_object_dispose; /* !T:SINGLE */
+id (*_objc_object_copy)(id) = __objc_object_copy; /* !T:SINGLE */
id
class_create_instance(Class class)
@@ -66,19 +66,19 @@ object_dispose(id object)
if (_objc_object_dispose)
(*_objc_object_dispose)(object);
else
- free(object);
+ objc_free(object);
}
return nil;
}
id __objc_object_alloc(Class class)
{
- return (id)__objc_xmalloc(class->instance_size);
+ return (id)objc_malloc(class->instance_size);
}
id __objc_object_dispose(id object)
{
- free(object);
+ objc_free(object);
return 0;
}
diff --git a/gnu/usr.bin/gcc/objc/runtime.h b/gnu/usr.bin/gcc/objc/runtime.h
index 0f4510f3ac7..b0eae4a222d 100644
--- a/gnu/usr.bin/gcc/objc/runtime.h
+++ b/gnu/usr.bin/gcc/objc/runtime.h
@@ -1,5 +1,5 @@
/* GNU Objective C Runtime internal declarations
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@@ -37,21 +37,29 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "objc/objc.h" /* core data types */
#include "objc/objc-api.h" /* runtime api functions */
+#include "objc/thr.h" /* thread and mutex support */
+
#include "objc/hash.h" /* hash structures */
-#include "objc/list.h" /* linear lists */
+#include "objc/objc-list.h" /* linear lists */
extern void __objc_add_class_to_hash(Class); /* (objc-class.c) */
-extern void __objc_init_selector_tables(); /* (objc-sel.c) */
-extern void __objc_init_class_tables(); /* (objc-class.c) */
-extern void __objc_init_dispatch_tables(); /* (objc-dispatch.c) */
+extern void __objc_init_selector_tables(void); /* (objc-sel.c) */
+extern void __objc_init_class_tables(void); /* (objc-class.c) */
+extern void __objc_init_dispatch_tables(void); /* (objc-dispatch.c) */
extern void __objc_install_premature_dtable(Class); /* (objc-dispatch.c) */
-extern void __objc_resolve_class_links(); /* (objc-class.c) */
+extern void __objc_resolve_class_links(void); /* (objc-class.c) */
extern void __objc_register_selectors_from_class(Class); /* (objc-sel.c) */
extern void __objc_update_dispatch_table_for_class (Class);/* (objc-msg.c) */
+
+extern int __objc_init_thread_system(void); /* thread.c */
+extern int __objc_fini_thread_system(void); /* thread.c */
+extern void __objc_print_dtable_stats(void); /* sendmsg.c */
+
extern void class_add_method_list(Class, MethodList_t);
-extern void objc_error(id object, const char* fmt, va_list);
-extern void (*_objc_error)(id, const char*, va_list);
+/* Registering instance methods as class methods for root classes */
+extern void __objc_register_instance_methods_to_class(Class);
+extern Method_t search_for_method_in_list(MethodList_t list, SEL op);
/* True when class links has been resolved */
extern BOOL __objc_class_links_resolved;
@@ -59,6 +67,12 @@ extern BOOL __objc_class_links_resolved;
/* Number of selectors stored in each of the selector tables */
extern int __objc_selector_max_index;
+/* Mutex locking __objc_selector_max_index and its arrays. */
+extern objc_mutex_t __objc_runtime_mutex;
+
+/* Number of threads which are alive. */
+extern int __objc_runtime_threads_alive;
+
#ifdef DEBUG
#define DEBUG_PRINTF(format, args...) printf (format, ## args)
#else
@@ -67,7 +81,7 @@ extern int __objc_selector_max_index;
BOOL __objc_responds_to (id object, SEL sel); /* for internal use only! */
SEL __sel_register_typed_name (const char*, const char*,
- struct objc_selector*);
+ struct objc_selector*, BOOL is_const);
#endif /* not __objc_runtime_INCLUDE_GNU */
diff --git a/gnu/usr.bin/gcc/objc/sarray.c b/gnu/usr.bin/gcc/objc/sarray.c
index 9ed219681c8..7e40fba750f 100644
--- a/gnu/usr.bin/gcc/objc/sarray.c
+++ b/gnu/usr.bin/gcc/objc/sarray.c
@@ -1,5 +1,5 @@
/* Sparse Arrays for Objective C dispatch tables
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -25,13 +25,16 @@ Boston, MA 02111-1307, USA. */
the executable file might be covered by the GNU General Public License. */
#include "objc/sarray.h"
+#include "objc/runtime.h"
#include <stdio.h>
#include "assert.h"
-int nbuckets = 0;
-int nindices = 0;
-int narrays = 0;
-int idxsize = 0;
+int nbuckets = 0; /* !T:MUTEX */
+int nindices = 0; /* !T:MUTEX */
+int narrays = 0; /* !T:MUTEX */
+int idxsize = 0; /* !T:MUTEX */
+
+static void * first_free_data = NULL; /* !T:MUTEX */
#ifdef OBJC_SPARSE2
const char* __objc_sparse2_id = "2 level sparse indices";
@@ -43,16 +46,62 @@ const char* __objc_sparse3_id = "3 level sparse indices";
#ifdef __alpha__
const void *memcpy (void*, const void*, size_t);
-void free (const void*);
#endif
+/* This function removes any structures left over from free operations
+ that were not safe in a multi-threaded environment. */
+void
+sarray_remove_garbage(void)
+{
+ void **vp;
+ void *np;
+
+ objc_mutex_lock(__objc_runtime_mutex);
+
+ vp = first_free_data;
+ first_free_data = NULL;
+
+ while (vp) {
+ np = *vp;
+ objc_free(vp);
+ vp = np;
+ }
+
+ objc_mutex_unlock(__objc_runtime_mutex);
+}
+
+/* Free a block of dynamically allocated memory. If we are in multi-threaded
+ mode, it is ok to free it. If not, we add it to the garbage heap to be
+ freed later. */
+
+static void
+sarray_free_garbage(void *vp)
+{
+ objc_mutex_lock(__objc_runtime_mutex);
+
+ if (__objc_runtime_threads_alive == 1) {
+ objc_free(vp);
+ if (first_free_data)
+ sarray_remove_garbage();
+ }
+ else {
+ *(void **)vp = first_free_data;
+ first_free_data = vp;
+ }
+
+ objc_mutex_unlock(__objc_runtime_mutex);
+}
+
+/* sarray_at_put : copies data in such a way as to be thread reader safe. */
void
sarray_at_put(struct sarray* array, sidx index, void* element)
{
#ifdef OBJC_SPARSE3
struct sindex** the_index;
+ struct sindex* new_index;
#endif
struct sbucket** the_bucket;
+ struct sbucket* new_bucket;
#ifdef OBJC_SPARSE3
size_t ioffset;
#endif
@@ -96,22 +145,24 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
if ((*the_index) == array->empty_index) {
/* The index was previously empty, allocate a new */
- *the_index = (struct sindex*)__objc_xmalloc(sizeof(struct sindex));
- memcpy(*the_index, array->empty_index, sizeof(struct sindex));
- (*the_index)->version = array->version;
+ new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
+ memcpy(new_index, array->empty_index, sizeof(struct sindex));
+ new_index->version.version = array->version.version;
+ *the_index = new_index; /* Prepared for install. */
the_bucket = &((*the_index)->buckets[boffset]);
- nindices += 1;
- } else if ((*the_index)->version != array->version) {
+ nindices += 1;
+ } else if ((*the_index)->version.version != array->version.version) {
/* This index must be lazy copied */
struct sindex* old_index = *the_index;
- *the_index = (struct sindex*)__objc_xmalloc(sizeof(struct sindex));
- memcpy( *the_index,old_index, sizeof(struct sindex));
- (*the_index)->version = array->version;
+ new_index = (struct sindex*)objc_malloc(sizeof(struct sindex));
+ memcpy( new_index, old_index, sizeof(struct sindex));
+ new_index->version.version = array->version.version;
+ *the_index = new_index; /* Prepared for install. */
the_bucket = &((*the_index)->buckets[boffset]);
- nindices += 1;
+ nindices += 1;
}
#endif /* OBJC_SPARSE3 */
@@ -122,18 +173,23 @@ sarray_at_put(struct sarray* array, sidx index, void* element)
/* The bucket was previously empty (or something like that), */
/* allocate a new. This is the effect of `lazy' allocation */
- *the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket));
- memcpy((void *) *the_bucket, (const void*)array->empty_bucket, sizeof(struct sbucket));
- (*the_bucket)->version = array->version;
+ new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket));
+ memcpy((void *) new_bucket, (const void*)array->empty_bucket,
+ sizeof(struct sbucket));
+ new_bucket->version.version = array->version.version;
+ *the_bucket = new_bucket; /* Prepared for install. */
+
nbuckets += 1;
- } else if ((*the_bucket)->version != array->version) {
+ } else if ((*the_bucket)->version.version != array->version.version) {
/* Perform lazy copy. */
struct sbucket* old_bucket = *the_bucket;
- *the_bucket = (struct sbucket*)__objc_xmalloc(sizeof(struct sbucket));
- memcpy( *the_bucket,old_bucket, sizeof(struct sbucket));
- (*the_bucket)->version = array->version;
+ new_bucket = (struct sbucket*)objc_malloc(sizeof(struct sbucket));
+ memcpy( new_bucket, old_bucket, sizeof(struct sbucket));
+ new_bucket->version.version = array->version.version;
+ *the_bucket = new_bucket; /* Prepared for install. */
+
nbuckets += 1;
}
@@ -151,42 +207,48 @@ sarray_at_put_safe(struct sarray* array, sidx index, void* element)
struct sarray*
sarray_new (int size, void* default_element)
{
+ struct sarray* arr;
#ifdef OBJC_SPARSE3
size_t num_indices = ((size-1)/(INDEX_CAPACITY))+1;
+ struct sindex ** new_indices;
#else /* OBJC_SPARSE2 */
size_t num_indices = ((size-1)/BUCKET_SIZE)+1;
+ struct sbucket ** new_buckets;
#endif
int counter;
- struct sarray* arr;
assert(size > 0);
/* Allocate core array */
- arr = (struct sarray*) __objc_xmalloc(sizeof(struct sarray));
- arr->version = 0;
- narrays += 1;
+ arr = (struct sarray*) objc_malloc(sizeof(struct sarray));
+ arr->version.version = 0;
/* Initialize members */
#ifdef OBJC_SPARSE3
arr->capacity = num_indices*INDEX_CAPACITY;
- arr->indices = (struct sindex**)
- __objc_xmalloc(sizeof(struct sindex*)*num_indices);
- idxsize += num_indices;
+ new_indices = (struct sindex**)
+ objc_malloc(sizeof(struct sindex*)*num_indices);
- arr->empty_index = (struct sindex*) __objc_xmalloc(sizeof(struct sindex));
- arr->empty_index->version = 0;
+ arr->empty_index = (struct sindex*) objc_malloc(sizeof(struct sindex));
+ arr->empty_index->version.version = 0;
+
+ narrays += 1;
+ idxsize += num_indices;
nindices += 1;
#else /* OBJC_SPARSE2 */
arr->capacity = num_indices*BUCKET_SIZE;
- arr->buckets = (struct sbucket**)
- __objc_xmalloc(sizeof(struct sbucket*)*num_indices);
+ new_buckets = (struct sbucket**)
+ objc_malloc(sizeof(struct sbucket*)*num_indices);
+
+ narrays += 1;
idxsize += num_indices;
#endif
- arr->empty_bucket = (struct sbucket*) __objc_xmalloc(sizeof(struct sbucket));
- arr->empty_bucket->version = 0;
+ arr->empty_bucket = (struct sbucket*) objc_malloc(sizeof(struct sbucket));
+ arr->empty_bucket->version.version = 0;
+
nbuckets += 1;
arr->ref_count = 1;
@@ -200,20 +262,28 @@ sarray_new (int size, void* default_element)
arr->empty_index->buckets[counter] = arr->empty_bucket;
for (counter=0; counter<num_indices; counter++)
- arr->indices[counter] = arr->empty_index;
+ new_indices[counter] = arr->empty_index;
#else /* OBJC_SPARSE2 */
for (counter=0; counter<num_indices; counter++)
- arr->buckets[counter] = arr->empty_bucket;
+ new_buckets[counter] = arr->empty_bucket;
#endif
-
+
+#ifdef OBJC_SPARSE3
+ arr->indices = new_indices;
+#else /* OBJC_SPARSE2 */
+ arr->buckets = new_buckets;
+#endif
+
return arr;
}
-/* Reallocate the sparse array to hold `newsize' entries */
+/* Reallocate the sparse array to hold `newsize' entries
+ Note: We really allocate and then free. We have to do this to ensure that
+ any concurrent readers notice the update. */
void
sarray_realloc(struct sarray* array, int newsize)
@@ -223,11 +293,17 @@ sarray_realloc(struct sarray* array, int newsize)
size_t new_max_index = ((newsize-1)/INDEX_CAPACITY);
size_t rounded_size = (new_max_index+1)*INDEX_CAPACITY;
+ struct sindex ** new_indices;
+ struct sindex ** old_indices;
+
#else /* OBJC_SPARSE2 */
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE;
size_t new_max_index = ((newsize-1)/BUCKET_SIZE);
size_t rounded_size = (new_max_index+1)*BUCKET_SIZE;
+ struct sbucket ** new_buckets;
+ struct sbucket ** old_buckets;
+
#endif
int counter;
@@ -235,87 +311,72 @@ sarray_realloc(struct sarray* array, int newsize)
assert(newsize > 0);
/* The size is the same, just ignore the request */
- if(rounded_size == array->capacity)
+ if(rounded_size <= array->capacity)
return;
assert(array->ref_count == 1); /* stop if lazy copied... */
- if(rounded_size < array->capacity)
+ /* We are asked to extend the array -- allocate new bucket table, */
+ /* and insert empty_bucket in newly allocated places. */
+ if(rounded_size > array->capacity)
{
+
+#ifdef OBJC_SPARSE3
+ new_max_index += 4;
+ rounded_size = (new_max_index+1)*INDEX_CAPACITY;
+
+#else /* OBJC_SPARSE2 */
+ new_max_index += 4;
+ rounded_size = (new_max_index+1)*BUCKET_SIZE;
+#endif
+
/* update capacity */
array->capacity = rounded_size;
- /* free buckets above new_max_index */
- for(counter = old_max_index; counter > new_max_index; counter-- ) {
#ifdef OBJC_SPARSE3
- struct sindex* idx = array->indices[counter];
- if((idx != array->empty_index) && (idx->version == array->version)) {
- int c2;
- for(c2=0; c2<INDEX_SIZE; c2++) {
- struct sbucket* bkt = idx->buckets[c2];
- if((bkt != array->empty_bucket) && (bkt->version == array->version))
- {
- free(bkt);
- nbuckets -= 1;
- }
- }
- free(idx);
- nindices -= 1;
- }
+ /* alloc to force re-read by any concurrent readers. */
+ old_indices = array->indices;
+ new_indices = (struct sindex**)
+ objc_malloc((new_max_index+1)*sizeof(struct sindex*));
#else /* OBJC_SPARSE2 */
- struct sbucket* bkt = array->buckets[counter];
- if ((bkt != array->empty_bucket) && (bkt->version == array->version))
- {
- free(bkt);
- nbuckets -= 1;
- }
+ old_buckets = array->buckets;
+ new_buckets = (struct sbucket**)
+ objc_malloc((new_max_index+1)*sizeof(struct sbucket*));
#endif
- }
-
+
+ /* copy buckets below old_max_index (they are still valid) */
+ for(counter = 0; counter <= old_max_index; counter++ ) {
#ifdef OBJC_SPARSE3
- /* realloc to free the space above new_max_index */
- array->indices = (struct sindex**)
- __objc_xrealloc(array->indices,
- (new_max_index+1)*sizeof(struct sindex*));
+ new_indices[counter] = old_indices[counter];
#else /* OBJC_SPARSE2 */
- array->buckets = (struct sbucket**)
- __objc_xrealloc(array->buckets,
- (new_max_index+1)*sizeof(struct sbucket*));
-#endif
- idxsize -= (old_max_index-new_max_index);
-
- return;
- }
-
- /* We are asked to extend the array -- reallocate the bucket table, */
- /* and insert empty_bucket in newly allocated places. */
- if(rounded_size > array->capacity)
- {
- /* update capacity */
- array->capacity = rounded_size;
+ new_buckets[counter] = old_buckets[counter];
+#endif
+ }
#ifdef OBJC_SPARSE3
- /* realloc to make room in table above old_max_index */
- array->indices = (struct sindex**)
- __objc_xrealloc(array->indices,
- (new_max_index+1)*sizeof(struct sindex*));
-
/* reset entries above old_max_index to empty_bucket */
for(counter = old_max_index+1; counter <= new_max_index; counter++)
- array->indices[counter] = array->empty_index;
-
+ new_indices[counter] = array->empty_index;
#else /* OBJC_SPARSE2 */
-
- /* realloc to make room in table above old_max_index */
- array->buckets = (struct sbucket**)
- __objc_xrealloc(array->buckets,
- (new_max_index+1)*sizeof(struct sbucket*));
-
/* reset entries above old_max_index to empty_bucket */
for(counter = old_max_index+1; counter <= new_max_index; counter++)
- array->buckets[counter] = array->empty_bucket;
+ new_buckets[counter] = array->empty_bucket;
+#endif
+
+#ifdef OBJC_SPARSE3
+ /* install the new indices */
+ array->indices = new_indices;
+#else /* OBJC_SPARSE2 */
+ array->buckets = new_buckets;
+#endif
+#ifdef OBJC_SPARSE3
+ /* free the old indices */
+ sarray_free_garbage(old_indices);
+#else /* OBJC_SPARSE2 */
+ sarray_free_garbage(old_buckets);
#endif
+
idxsize += (new_max_index-old_max_index);
return;
}
@@ -326,10 +387,13 @@ sarray_realloc(struct sarray* array, int newsize)
void
sarray_free(struct sarray* array) {
+
#ifdef OBJC_SPARSE3
size_t old_max_index = (array->capacity-1)/INDEX_CAPACITY;
+ struct sindex ** old_indices;
#else
size_t old_max_index = (array->capacity-1)/BUCKET_SIZE;
+ struct sbucket ** old_buckets;
#endif
int counter = 0;
@@ -338,31 +402,40 @@ sarray_free(struct sarray* array) {
if(--(array->ref_count) != 0) /* There exists copies of me */
return;
+#ifdef OBJC_SPARSE3
+ old_indices = array->indices;
+#else
+ old_buckets = array->buckets;
+#endif
+
if((array->is_copy_of) && ((array->is_copy_of->ref_count - 1) == 0))
sarray_free(array->is_copy_of);
/* Free all entries that do not point to empty_bucket */
for(counter = 0; counter <= old_max_index; counter++ ) {
#ifdef OBJC_SPARSE3
- struct sindex* idx = array->indices[counter];
- if((idx != array->empty_index) && (idx->version == array->version)) {
+ struct sindex* idx = old_indices[counter];
+ if((idx != array->empty_index) &&
+ (idx->version.version == array->version.version)) {
int c2;
for(c2=0; c2<INDEX_SIZE; c2++) {
struct sbucket* bkt = idx->buckets[c2];
- if((bkt != array->empty_bucket) && (bkt->version == array->version))
+ if((bkt != array->empty_bucket) &&
+ (bkt->version.version == array->version.version))
{
- free(bkt);
+ sarray_free_garbage(bkt);
nbuckets -= 1;
}
}
- free(idx);
+ sarray_free_garbage(idx);
nindices -= 1;
}
#else /* OBJC_SPARSE2 */
struct sbucket* bkt = array->buckets[counter];
- if ((bkt != array->empty_bucket) && (bkt->version == array->version))
+ if ((bkt != array->empty_bucket) &&
+ (bkt->version.version == array->version.version))
{
- free(bkt);
+ sarray_free_garbage(bkt);
nbuckets -= 1;
}
#endif
@@ -370,33 +443,32 @@ sarray_free(struct sarray* array) {
#ifdef OBJC_SPARSE3
/* free empty_index */
- if(array->empty_index->version == array->version) {
- free(array->empty_index);
+ if(array->empty_index->version.version == array->version.version) {
+ sarray_free_garbage(array->empty_index);
nindices -= 1;
}
#endif
/* free empty_bucket */
- if(array->empty_bucket->version == array->version) {
- free(array->empty_bucket);
+ if(array->empty_bucket->version.version == array->version.version) {
+ sarray_free_garbage(array->empty_bucket);
nbuckets -= 1;
}
+ idxsize -= (old_max_index+1);
+ narrays -= 1;
#ifdef OBJC_SPARSE3
/* free bucket table */
- free(array->indices);
- idxsize -= (old_max_index+1);
+ sarray_free_garbage(array->indices);
#else
/* free bucket table */
- free(array->buckets);
- idxsize -= (old_max_index+1);
+ sarray_free_garbage(array->buckets);
#endif
-
+
/* free array */
- free(array);
- narrays -= 1;
+ sarray_free_garbage(array);
}
/* This is a lazy copy. Only the core of the structure is actually */
@@ -405,37 +477,46 @@ sarray_free(struct sarray* array) {
struct sarray*
sarray_lazy_copy(struct sarray* oarr)
{
+ struct sarray* arr;
+
#ifdef OBJC_SPARSE3
size_t num_indices = ((oarr->capacity-1)/INDEX_CAPACITY)+1;
+ struct sindex ** new_indices;
#else /* OBJC_SPARSE2 */
size_t num_indices = ((oarr->capacity-1)/BUCKET_SIZE)+1;
+ struct sbucket ** new_buckets;
#endif
- struct sarray* arr;
/* Allocate core array */
- arr = (struct sarray*) __objc_xmalloc(sizeof(struct sarray));
- memcpy( arr,oarr, sizeof(struct sarray));
- arr->version = oarr->version + 1;
- arr->is_copy_of = oarr;
- oarr->ref_count += 1;
+ arr = (struct sarray*) objc_malloc(sizeof(struct sarray)); /* !!! */
+ arr->version.version = oarr->version.version + 1;
+#ifdef OBJC_SPARSE3
+ arr->empty_index = oarr->empty_index;
+#endif
+ arr->empty_bucket = oarr->empty_bucket;
arr->ref_count = 1;
+ oarr->ref_count += 1;
+ arr->is_copy_of = oarr;
+ arr->capacity = oarr->capacity;
#ifdef OBJC_SPARSE3
/* Copy bucket table */
- arr->indices = (struct sindex**)
- __objc_xmalloc(sizeof(struct sindex*)*num_indices);
- memcpy( arr->indices,oarr->indices,
+ new_indices = (struct sindex**)
+ objc_malloc(sizeof(struct sindex*)*num_indices);
+ memcpy( new_indices,oarr->indices,
sizeof(struct sindex*)*num_indices);
+ arr->indices = new_indices;
#else
/* Copy bucket table */
- arr->buckets = (struct sbucket**)
- __objc_xmalloc(sizeof(struct sbucket*)*num_indices);
- memcpy( arr->buckets,oarr->buckets,
+ new_buckets = (struct sbucket**)
+ objc_malloc(sizeof(struct sbucket*)*num_indices);
+ memcpy( new_buckets,oarr->buckets,
sizeof(struct sbucket*)*num_indices);
+ arr->buckets = new_buckets;
#endif
idxsize += num_indices;
narrays += 1;
-
+
return arr;
}
diff --git a/gnu/usr.bin/gcc/objc/sarray.h b/gnu/usr.bin/gcc/objc/sarray.h
index a3ec7a98373..74fa38652ba 100644
--- a/gnu/usr.bin/gcc/objc/sarray.h
+++ b/gnu/usr.bin/gcc/objc/sarray.h
@@ -1,7 +1,6 @@
/* Sparse Arrays for Objective C dispatch tables
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
-
-Author: Kresten Krab Thorup
+ Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Kresten Krab Thorup.
This file is part of GNU CC.
@@ -42,6 +41,8 @@ extern const char* __objc_sparse3_id;
#include <stddef.h>
+#include "objc/thr.h"
+
extern int nbuckets; /* for stats */
extern int nindices;
extern int narrays;
@@ -108,19 +109,21 @@ union sofftype {
#endif /* not PRECOMPUTE_SELECTORS */
-void * __objc_xrealloc (void *optr, size_t size);
-void * __objc_xmalloc (size_t size);
+union sversion {
+ int version;
+ void *next_free;
+};
struct sbucket {
void* elems[BUCKET_SIZE]; /* elements stored in array */
- short version; /* used for copy-on-write */
+ union sversion version; /* used for copy-on-write */
};
#ifdef OBJC_SPARSE3
struct sindex {
struct sbucket* buckets[INDEX_SIZE];
- short version;
+ union sversion version; /* used for copy-on-write */
};
#endif /* OBJC_SPARSE3 */
@@ -133,7 +136,7 @@ struct sarray {
struct sbucket** buckets;
#endif /* OBJC_SPARSE2 */
struct sbucket* empty_bucket;
- short version;
+ union sversion version; /* used for copy-on-write */
short ref_count;
struct sarray* is_copy_of;
size_t capacity;
@@ -142,10 +145,12 @@ struct sarray {
struct sarray* sarray_new(int, void* default_element);
void sarray_free(struct sarray*);
struct sarray* sarray_lazy_copy(struct sarray*);
-struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */
void sarray_realloc(struct sarray*, int new_size);
void sarray_at_put(struct sarray*, sidx index, void* elem);
void sarray_at_put_safe(struct sarray*, sidx index, void* elem);
+
+struct sarray* sarray_hard_copy(struct sarray*); /* ... like the name? */
+void sarray_remove_garbage(void);
#ifdef PRECOMPUTE_SELECTORS
diff --git a/gnu/usr.bin/gcc/objc/selector.c b/gnu/usr.bin/gcc/objc/selector.c
index be68f4f1dbb..83c70e4ae0f 100644
--- a/gnu/usr.bin/gcc/objc/selector.c
+++ b/gnu/usr.bin/gcc/objc/selector.c
@@ -1,5 +1,5 @@
/* GNU Objective C Runtime selector related functions
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@@ -31,14 +31,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define SELECTOR_HASH_SIZE 128
/* Tables mapping selector names to uid and opposite */
-static struct sarray* __objc_selector_array = 0; /* uid -> sel */
-static struct sarray* __objc_selector_names = 0; /* uid -> name */
-static cache_ptr __objc_selector_hash = 0; /* name -> uid */
+static struct sarray* __objc_selector_array = 0; /* uid -> sel !T:MUTEX */
+static struct sarray* __objc_selector_names = 0; /* uid -> name !T:MUTEX */
+static cache_ptr __objc_selector_hash = 0; /* name -> uid !T:MUTEX */
static void register_selectors_from_list(MethodList_t);
/* Number of selectors stored in each of the above tables */
-int __objc_selector_max_index = 0;
+int __objc_selector_max_index = 0; /* !T:MUTEX */
void __objc_init_selector_tables()
{
@@ -88,6 +88,71 @@ register_selectors_from_list (MethodList_t method_list)
}
+/* Register instance methods as class methods for root classes */
+void __objc_register_instance_methods_to_class(Class class)
+{
+ MethodList_t method_list;
+ MethodList_t class_method_list;
+ int max_methods_no = 16;
+ MethodList_t new_list;
+ Method_t curr_method;
+
+ /* Only if a root class. */
+ if(class->super_class)
+ return;
+
+ /* Allocate a method list to hold the new class methods */
+ new_list = objc_calloc(sizeof(struct objc_method_list)
+ + sizeof(struct objc_method[max_methods_no]), 1);
+ method_list = class->methods;
+ class_method_list = class->class_pointer->methods;
+ curr_method = &new_list->method_list[0];
+
+ /* Iterate through the method lists for the class */
+ while (method_list)
+ {
+ int i;
+
+ /* Iterate through the methods from this method list */
+ for (i = 0; i < method_list->method_count; i++)
+ {
+ Method_t mth = &method_list->method_list[i];
+ if (mth->method_name
+ && !search_for_method_in_list (class_method_list,
+ mth->method_name))
+ {
+ /* This instance method isn't a class method.
+ Add it into the new_list. */
+ *curr_method = *mth;
+
+ /* Reallocate the method list if necessary */
+ if(++new_list->method_count == max_methods_no)
+ new_list =
+ objc_realloc(new_list, sizeof(struct objc_method_list)
+ + sizeof(struct
+ objc_method[max_methods_no += 16]));
+ curr_method = &new_list->method_list[new_list->method_count];
+ }
+ }
+
+ method_list = method_list->method_next;
+ }
+
+ /* If we created any new class methods
+ then attach the method list to the class */
+ if (new_list->method_count)
+ {
+ new_list =
+ objc_realloc(new_list, sizeof(struct objc_method_list)
+ + sizeof(struct objc_method[new_list->method_count]));
+ new_list->method_next = class->class_pointer->methods;
+ class->class_pointer->methods = new_list;
+ }
+
+ __objc_update_dispatch_table_for_class (class->class_pointer);
+}
+
+
/* Returns YES iff t1 and t2 have same method types, but we ignore
the argframe layout */
BOOL
@@ -122,11 +187,16 @@ sel_get_typed_uid (const char *name, const char *types)
struct objc_list *l;
sidx i;
+ objc_mutex_lock(__objc_runtime_mutex);
+
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (i == 0)
- return 0;
+ {
+ objc_mutex_unlock(__objc_runtime_mutex);
+ return 0;
+ }
- for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
l; l = l->tail)
{
SEL s = (SEL)l->head;
@@ -134,15 +204,18 @@ sel_get_typed_uid (const char *name, const char *types)
{
if (s->sel_types == types)
{
+ objc_mutex_unlock(__objc_runtime_mutex);
return s;
}
}
else if (sel_types_match (s->sel_types, types))
{
+ objc_mutex_unlock(__objc_runtime_mutex);
return s;
}
}
+ objc_mutex_unlock(__objc_runtime_mutex);
return 0;
}
@@ -152,20 +225,29 @@ sel_get_any_typed_uid (const char *name)
{
struct objc_list *l;
sidx i;
- SEL s;
+ SEL s = NULL;
+
+ objc_mutex_lock(__objc_runtime_mutex);
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (i == 0)
- return 0;
+ {
+ objc_mutex_unlock(__objc_runtime_mutex);
+ return 0;
+ }
- for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
l; l = l->tail)
{
s = (SEL) l->head;
if (s->sel_types)
- return s;
+ {
+ objc_mutex_unlock(__objc_runtime_mutex);
+ return s;
+ }
}
+ objc_mutex_unlock(__objc_runtime_mutex);
return s;
}
@@ -176,11 +258,18 @@ sel_get_any_uid (const char *name)
struct objc_list *l;
sidx i;
+ objc_mutex_lock(__objc_runtime_mutex);
+
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (soffset_decode (i) == 0)
- return 0;
+ {
+ objc_mutex_unlock(__objc_runtime_mutex);
+ return 0;
+ }
+
+ l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
+ objc_mutex_unlock(__objc_runtime_mutex);
- l = (struct objc_list*)sarray_get (__objc_selector_array, i);
if (l == 0)
return 0;
@@ -199,11 +288,16 @@ sel_get_uid (const char *name)
const char*
sel_get_name (SEL selector)
{
+ const char *ret;
+
+ objc_mutex_lock(__objc_runtime_mutex);
if ((soffset_decode((sidx)selector->sel_id) > 0)
&& (soffset_decode((sidx)selector->sel_id) <= __objc_selector_max_index))
- return sarray_get (__objc_selector_names, (sidx) selector->sel_id);
+ ret = sarray_get_safe (__objc_selector_names, (sidx) selector->sel_id);
else
- return 0;
+ ret = 0;
+ objc_mutex_unlock(__objc_runtime_mutex);
+ return ret;
}
BOOL
@@ -227,10 +321,15 @@ sel_get_type (SEL selector)
extern struct sarray* __objc_uninstalled_dtable;
/* Store the passed selector name in the selector record and return its
- selector value (value returned by sel_get_uid). */
+ selector value (value returned by sel_get_uid).
+ Assumes that the calling function has locked down __objc_runtime_mutex. */
+/* is_const parameter tells us if the name and types parameters
+ are really constant or not. If YES then they are constant and
+ we can just store the pointers. If NO then we need to copy
+ name and types because the pointers may disappear later on. */
SEL
__sel_register_typed_name (const char *name, const char *types,
- struct objc_selector *orig)
+ struct objc_selector *orig, BOOL is_const)
{
struct objc_selector* j;
sidx i;
@@ -239,7 +338,7 @@ __sel_register_typed_name (const char *name, const char *types,
i = (sidx) hash_value_for_key (__objc_selector_hash, name);
if (soffset_decode (i) != 0)
{
- for (l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ for (l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
l; l = l->tail)
{
SEL s = (SEL)l->head;
@@ -270,11 +369,17 @@ __sel_register_typed_name (const char *name, const char *types,
if (orig)
j = orig;
else
- j = __objc_xmalloc (sizeof (struct objc_selector));
+ j = objc_malloc (sizeof (struct objc_selector));
j->sel_id = (void*)i;
- j->sel_types = (const char*)types;
- l = (struct objc_list*)sarray_get (__objc_selector_array, i);
+ /* Can we use the pointer or must copy types? Don't copy if NULL */
+ if ((is_const) || (types == 0))
+ j->sel_types = (const char*)types;
+ else {
+ j->sel_types = (char *) objc_malloc(strlen(types)+1);
+ strcpy((char *)j->sel_types, types);
+ }
+ l = (struct objc_list*)sarray_get_safe (__objc_selector_array, i);
}
else
{
@@ -283,10 +388,16 @@ __sel_register_typed_name (const char *name, const char *types,
if (orig)
j = orig;
else
- j = __objc_xmalloc (sizeof (struct objc_selector));
+ j = objc_malloc (sizeof (struct objc_selector));
j->sel_id = (void*)i;
- j->sel_types = (const char*)types;
+ /* Can we use the pointer or must copy types? Don't copy if NULL */
+ if ((is_const) || (types == 0))
+ j->sel_types = (const char*)types;
+ else {
+ j->sel_types = (char *) objc_malloc(strlen(types)+1);
+ strcpy((char *)j->sel_types, types);
+ }
l = 0;
}
@@ -295,11 +406,21 @@ __sel_register_typed_name (const char *name, const char *types,
{
int is_new = (l == 0);
+ const char *new_name;
+
+ /* Can we use the pointer or must copy name? Don't copy if NULL */
+ if ((is_const) || (name == 0))
+ new_name = name;
+ else {
+ new_name = (char *) objc_malloc(strlen(name)+1);
+ strcpy((char *)new_name, name);
+ }
+
l = list_cons ((void*)j, l);
- sarray_at_put_safe (__objc_selector_names, i, (void *) name);
+ sarray_at_put_safe (__objc_selector_names, i, (void *) new_name);
sarray_at_put_safe (__objc_selector_array, i, (void *) l);
if (is_new)
- hash_add (&__objc_selector_hash, (void *) name, (void *) i);
+ hash_add (&__objc_selector_hash, (void *) new_name, (void *) i);
}
sarray_realloc(__objc_uninstalled_dtable, __objc_selector_max_index+1);
@@ -310,12 +431,28 @@ __sel_register_typed_name (const char *name, const char *types,
SEL
sel_register_name (const char *name)
{
- return __sel_register_typed_name (name, 0, 0);
+ SEL ret;
+
+ objc_mutex_lock(__objc_runtime_mutex);
+ /* Assume that name is not constant static memory and needs to be
+ copied before put into a runtime structure. is_const == NO */
+ ret = __sel_register_typed_name (name, 0, 0, NO);
+ objc_mutex_unlock(__objc_runtime_mutex);
+
+ return ret;
}
SEL
sel_register_typed_name (const char *name, const char *type)
{
- return __sel_register_typed_name (name, type, 0);
+ SEL ret;
+
+ objc_mutex_lock(__objc_runtime_mutex);
+ /* Assume that name and type are not constant static memory and need to
+ be copied before put into a runtime structure. is_const == NO */
+ ret = __sel_register_typed_name (name, type, 0, NO);
+ objc_mutex_unlock(__objc_runtime_mutex);
+
+ return ret;
}
diff --git a/gnu/usr.bin/gcc/objc/sendmsg.c b/gnu/usr.bin/gcc/objc/sendmsg.c
index 79d4a6b5d5b..6f3487c260e 100644
--- a/gnu/usr.bin/gcc/objc/sendmsg.c
+++ b/gnu/usr.bin/gcc/objc/sendmsg.c
@@ -1,5 +1,5 @@
/* GNU Objective C Runtime message lookup
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc.
Contributed by Kresten Krab Thorup
This file is part of GNU CC.
@@ -28,19 +28,20 @@ Boston, MA 02111-1307, USA. */
#include "runtime.h"
#include "sarray.h"
#include "encoding.h"
+#include "runtime-info.h"
/* this is how we hack STRUCT_VALUE to be 1 or 0 */
#define gen_rtx(args...) 1
#define rtx int
-#if STRUCT_VALUE == 0
+#if !defined(STRUCT_VALUE) || STRUCT_VALUE == 0
#define INVISIBLE_STRUCT_RETURN 1
#else
#define INVISIBLE_STRUCT_RETURN 0
#endif
/* The uninstalled dispatch table */
-struct sarray* __objc_uninstalled_dtable = 0;
+struct sarray* __objc_uninstalled_dtable = 0; /* !T:MUTEX */
/* Send +initialize to class */
static void __objc_send_initialize(Class);
@@ -49,6 +50,14 @@ static void __objc_install_dispatch_table_for_class (Class);
/* Forward declare some functions */
static void __objc_init_install_dtable(id, SEL);
+
+/* Various forwarding functions that are used based upon the
+ return type for the selector.
+ __objc_block_forward for structures.
+ __objc_double_forward for floats/doubles.
+ __objc_word_forward for pointers or types that fit in registers.
+ */
+static double __objc_double_forward(id, SEL, ...);
static id __objc_word_forward(id, SEL, ...);
typedef struct { id many[8]; } __big;
#if INVISIBLE_STRUCT_RETURN
@@ -58,13 +67,26 @@ static id
#endif
__objc_block_forward(id, SEL, ...);
static Method_t search_for_method_in_hierarchy (Class class, SEL sel);
-static Method_t search_for_method_in_list(MethodList_t list, SEL op);
+Method_t search_for_method_in_list(MethodList_t list, SEL op);
id nil_method(id, SEL, ...);
-id
-nil_method(id receiver, SEL op, ...)
+/* Given a selector, return the proper forwarding implementation. */
+__inline__
+IMP
+__objc_get_forward_imp (SEL sel)
{
- return receiver;
+ const char *t = sel->sel_types;
+
+ if (t && (*t == '[' || *t == '(' || *t == '{')
+#ifdef OBJC_MAX_STRUCT_BY_VALUE
+ && objc_sizeof_type(t) > OBJC_MAX_STRUCT_BY_VALUE
+#endif
+ )
+ return (IMP)__objc_block_forward;
+ else if (t && (*t == 'f' || *t == 'd'))
+ return (IMP)__objc_double_forward;
+ else
+ return (IMP)__objc_word_forward;
}
/* Given a class and selector, return the selector's implementation. */
@@ -72,54 +94,84 @@ __inline__
IMP
get_imp (Class class, SEL sel)
{
- IMP impl;
- void* res = sarray_get (class->dtable, (size_t) sel->sel_id);
- if(res == __objc_init_install_dtable)
- {
- __objc_install_dispatch_table_for_class (class);
- res = sarray_get (class->dtable, (size_t) sel->sel_id);
- }
+ void* res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
if (res == 0)
{
- const char *t = sel->sel_types;
- if (t && (*t == '[' || *t == '(' || *t == '{'))
- res = (IMP)__objc_block_forward;
+ /* Not a valid method */
+ if(class->dtable == __objc_uninstalled_dtable)
+ {
+ /* The dispatch table needs to be installed. */
+ objc_mutex_lock(__objc_runtime_mutex);
+ __objc_install_dispatch_table_for_class (class);
+ objc_mutex_unlock(__objc_runtime_mutex);
+ /* Call ourselves with the installed dispatch table
+ and get the real method */
+ res = get_imp(class, sel);
+ }
else
- res = (IMP)__objc_word_forward;
+ {
+ /* The dispatch table has been installed so the
+ method just doesn't exist for the class.
+ Return the forwarding implementation. */
+ res = __objc_get_forward_imp(sel);
+ }
}
return res;
}
-__inline__ BOOL
+/* Query if an object can respond to a selector, returns YES if the
+object implements the selector otherwise NO. Does not check if the
+method can be forwarded. */
+__inline__
+BOOL
__objc_responds_to (id object, SEL sel)
{
- void* res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id);
- if(res == __objc_init_install_dtable)
+ void* res;
+
+ /* Install dispatch table if need be */
+ if (object->class_pointer->dtable == __objc_uninstalled_dtable)
{
+ objc_mutex_lock(__objc_runtime_mutex);
__objc_install_dispatch_table_for_class (object->class_pointer);
- res = sarray_get (object->class_pointer->dtable, (size_t) sel->sel_id);
+ objc_mutex_unlock(__objc_runtime_mutex);
}
+
+ /* Get the method from the dispatch table */
+ res = sarray_get_safe (object->class_pointer->dtable, (size_t) sel->sel_id);
return (res != 0);
}
/* This is the lookup function. All entries in the table are either a
- valid method *or* one of `__objc_missing_method' which calls
- forward:: etc, or `__objc_init_install_dtable' which installs the
- real dtable */
-__inline__ IMP
+ valid method *or* zero. If zero then either the dispatch table
+ needs to be installed or it doesn't exist and forwarding is attempted. */
+__inline__
+IMP
objc_msg_lookup(id receiver, SEL op)
{
IMP result;
if(receiver)
{
- result = sarray_get(receiver->class_pointer->dtable, (sidx)op->sel_id);
+ result = sarray_get_safe (receiver->class_pointer->dtable,
+ (sidx)op->sel_id);
if (result == 0)
{
- const char *t = op->sel_types;
- if (t && (*t == '[' || *t == '(' || *t == '{'))
- result = (IMP)__objc_block_forward;
+ /* Not a valid method */
+ if(receiver->class_pointer->dtable == __objc_uninstalled_dtable)
+ {
+ /* The dispatch table needs to be installed.
+ This happens on the very first method call to the class. */
+ __objc_init_install_dtable(receiver, op);
+
+ /* Get real method for this in newly installed dtable */
+ result = get_imp(receiver->class_pointer, op);
+ }
else
- result = (IMP)__objc_word_forward;
+ {
+ /* The dispatch table has been installed so the
+ method just doesn't exist for the class.
+ Attempt to forward the method. */
+ result = __objc_get_forward_imp(op);
+ }
}
return result;
}
@@ -150,27 +202,25 @@ objc_msg_sendv(id object, SEL op, arglist_t arg_frame)
method_get_sizeof_arguments (m));
}
-void __objc_init_dispatch_tables()
+void
+__objc_init_dispatch_tables()
{
__objc_uninstalled_dtable
- = sarray_new(200, __objc_init_install_dtable);
+ = sarray_new(200, 0);
}
-/* This one is a bit hairy. This function is installed in the
- premature dispatch table, and thus called once for each class,
- namely when the very first message is send to it. */
-
-static void __objc_init_install_dtable(id receiver, SEL op)
+/* This function is called by objc_msg_lookup when the
+ dispatch table needs to be installed; thus it is called once
+ for each class, namely when the very first message is sent to it. */
+static void
+__objc_init_install_dtable(id receiver, SEL op)
{
- __label__ already_initialized;
- IMP imp;
- void* args;
- void* result;
-
/* This may happen, if the programmer has taken the address of a
method before the dtable was initialized... too bad for him! */
if(receiver->class_pointer->dtable != __objc_uninstalled_dtable)
- goto already_initialized;
+ return;
+
+ objc_mutex_lock(__objc_runtime_mutex);
if(CLS_ISCLASS(receiver->class_pointer))
{
@@ -198,31 +248,21 @@ static void __objc_init_install_dtable(id receiver, SEL op)
else
CLS_SETINITIALIZED((Class)receiver);
}
-
-already_initialized:
-
- /* Get real method for this in newly installed dtable */
- imp = get_imp(receiver->class_pointer, op);
-
- args = __builtin_apply_args();
- result = __builtin_apply((apply_t)imp, args, 96);
- if (result)
- __builtin_return (result);
- else
- return;
-
+ objc_mutex_unlock(__objc_runtime_mutex);
}
/* Install dummy table for class which causes the first message to
that class (or instances hereof) to be initialized properly */
-void __objc_install_premature_dtable(Class class)
+void
+__objc_install_premature_dtable(Class class)
{
assert(__objc_uninstalled_dtable);
class->dtable = __objc_uninstalled_dtable;
}
/* Send +initialize to class if not already done */
-static void __objc_send_initialize(Class class)
+static void
+__objc_send_initialize(Class class)
{
/* This *must* be a class object */
assert(CLS_ISCLASS(class));
@@ -250,7 +290,8 @@ static void __objc_send_initialize(Class class)
for (i=0;i<method_list->method_count;i++) {
method = &(method_list->method_list[i]);
- if (method->method_name->sel_id == op->sel_id) {
+ if (method->method_name
+ && method->method_name->sel_id == op->sel_id) {
imp = method->method_imp;
break;
}
@@ -267,14 +308,39 @@ static void __objc_send_initialize(Class class)
}
}
-}
+}
+
+/* Walk on the methods list of class and install the methods in the reverse
+ order of the lists. Since methods added by categories are before the methods
+ of class in the methods list, this allows categories to substitute methods
+ declared in class. However if more than one category replaces the same
+ method nothing is guaranteed about what method will be used.
+ Assumes that __objc_runtime_mutex is locked down. */
+static void
+__objc_install_methods_in_dtable (Class class, MethodList_t method_list)
+{
+ int i;
+
+ if (!method_list)
+ return;
+
+ if (method_list->method_next)
+ __objc_install_methods_in_dtable (class, method_list->method_next);
+
+ for (i = 0; i < method_list->method_count; i++)
+ {
+ Method_t method = &(method_list->method_list[i]);
+ sarray_at_put_safe (class->dtable,
+ (sidx) method->method_name->sel_id,
+ method->method_imp);
+ }
+}
+/* Assumes that __objc_runtime_mutex is locked down. */
static void
__objc_install_dispatch_table_for_class (Class class)
{
Class super;
- MethodList_t mlist;
- int counter;
/* If the class has not yet had it's class links resolved, we must
re-compute all class links */
@@ -289,47 +355,46 @@ __objc_install_dispatch_table_for_class (Class class)
/* Allocate dtable if necessary */
if (super == 0)
{
+ objc_mutex_lock(__objc_runtime_mutex);
class->dtable = sarray_new (__objc_selector_max_index, 0);
+ objc_mutex_unlock(__objc_runtime_mutex);
}
else
class->dtable = sarray_lazy_copy (super->dtable);
- for (mlist = class->methods; mlist; mlist = mlist->method_next)
- {
- counter = mlist->method_count - 1;
- while (counter >= 0)
- {
- Method_t method = &(mlist->method_list[counter]);
- sarray_at_put_safe (class->dtable,
- (sidx) method->method_name->sel_id,
- method->method_imp);
- counter -= 1;
- }
- }
+ __objc_install_methods_in_dtable (class, class->methods);
}
-void __objc_update_dispatch_table_for_class (Class class)
+void
+__objc_update_dispatch_table_for_class (Class class)
{
Class next;
+ struct sarray *arr;
/* not yet installed -- skip it */
if (class->dtable == __objc_uninstalled_dtable)
return;
- sarray_free (class->dtable); /* release memory */
+ objc_mutex_lock(__objc_runtime_mutex);
+
+ arr = class->dtable;
__objc_install_premature_dtable (class); /* someone might require it... */
- __objc_install_dispatch_table_for_class (class); /* could have been lazy... */
+ sarray_free (arr); /* release memory */
+
+ /* could have been lazy... */
+ __objc_install_dispatch_table_for_class (class);
if (class->subclass_list) /* Traverse subclasses */
for (next = class->subclass_list; next; next = next->sibling_class)
__objc_update_dispatch_table_for_class (next);
+ objc_mutex_unlock(__objc_runtime_mutex);
}
/* This function adds a method list to a class. This function is
typically called by another function specific to the run-time. As
- such this function does not worry about thread safe issued.
+ such this function does not worry about thread safe issues.
This one is only called for categories. Class objects have their
methods installed right away, and their selectors are made into
@@ -338,9 +403,6 @@ void
class_add_method_list (Class class, MethodList_t list)
{
int i;
- static SEL initialize_sel = 0;
- if (!initialize_sel)
- initialize_sel = sel_register_name ("initialize");
/* Passing of a linked list is not allowed. Do multiple calls. */
assert (!list->method_next);
@@ -356,24 +418,16 @@ class_add_method_list (Class class, MethodList_t list)
method->method_name =
sel_register_typed_name ((const char*)method->method_name,
method->method_types);
-
- if (search_for_method_in_list (class->methods, method->method_name)
- && method->method_name->sel_id != initialize_sel->sel_id)
- {
- /* Duplication. Print a error message an change the method name
- to NULL. */
- fprintf (stderr, "attempt to add a existing method: %s\n",
- sel_get_name(method->method_name));
- method->method_name = 0;
- }
}
}
/* Add the methods to the class's method list. */
list->method_next = class->methods;
class->methods = list;
-}
+ /* Update the dispatch table of class */
+ __objc_update_dispatch_table_for_class (class);
+}
Method_t
class_get_instance_method(Class class, SEL op)
@@ -414,7 +468,7 @@ search_for_method_in_hierarchy (Class cls, SEL sel)
/* Given a linked list of method and a method's name. Search for the named
method's method structure. Return a pointer to the method's method
structure if found. NULL otherwise. */
-static Method_t
+Method_t
search_for_method_in_list (MethodList_t list, SEL op)
{
MethodList_t method_list = list;
@@ -447,6 +501,7 @@ search_for_method_in_list (MethodList_t list, SEL op)
static retval_t __objc_forward (id object, SEL sel, arglist_t args);
+/* Forwarding pointers/integers through the normal registers */
static id
__objc_word_forward (id rcv, SEL op, ...)
{
@@ -460,6 +515,21 @@ __objc_word_forward (id rcv, SEL op, ...)
return res;
}
+/* Specific routine for forwarding floats/double because of
+ architectural differences on some processors. i386s for
+ example which uses a floating point stack versus general
+ registers for floating point numbers. This forward routine
+ makes sure that GCC restores the proper return values */
+static double
+__objc_double_forward (id rcv, SEL op, ...)
+{
+ void *args, *res;
+
+ args = __builtin_apply_args ();
+ res = __objc_forward (rcv, op, args);
+ __builtin_return (res);
+}
+
#if INVISIBLE_STRUCT_RETURN
static __big
#else
@@ -473,6 +543,12 @@ __objc_block_forward (id rcv, SEL op, ...)
res = __objc_forward (rcv, op, args);
if (res)
__builtin_return (res);
+ else
+#if INVISIBLE_STRUCT_RETURN
+ return (__big) {0};
+#else
+ return nil;
+#endif
}
@@ -482,7 +558,7 @@ static retval_t
__objc_forward (id object, SEL sel, arglist_t args)
{
IMP imp;
- static SEL frwd_sel = 0;
+ static SEL frwd_sel = 0; /* !T:SAFE2 */
SEL err_sel;
/* first try if the object understands forward:: */
@@ -526,14 +602,19 @@ __objc_forward (id object, SEL sel, arglist_t args)
/* The object doesn't respond to doesNotRecognize: or error:; Therefore,
a default action is taken. */
- fprintf (stderr, "fatal: %s\n", msg);
- abort ();
+ objc_error (object, OBJC_ERR_UNIMPLEMENTED, "%s\n", msg);
+
+ return 0;
}
}
-void __objc_print_dtable_stats()
+void
+__objc_print_dtable_stats()
{
int total = 0;
+
+ objc_mutex_lock(__objc_runtime_mutex);
+
printf("memory usage: (%s)\n",
#ifdef OBJC_SPARSE2
"2-level sparse arrays"
@@ -542,17 +623,28 @@ void __objc_print_dtable_stats()
#endif
);
- printf("arrays: %d = %ld bytes\n", narrays, (int)narrays*sizeof(struct sarray));
+ printf("arrays: %d = %ld bytes\n", narrays,
+ (long)narrays*sizeof(struct sarray));
total += narrays*sizeof(struct sarray);
- printf("buckets: %d = %ld bytes\n", nbuckets, (int)nbuckets*sizeof(struct sbucket));
+ printf("buckets: %d = %ld bytes\n", nbuckets,
+ (long)nbuckets*sizeof(struct sbucket));
total += nbuckets*sizeof(struct sbucket);
- printf("idxtables: %d = %ld bytes\n", idxsize, (int)idxsize*sizeof(void*));
+ printf("idxtables: %d = %ld bytes\n", idxsize, (long)idxsize*sizeof(void*));
total += idxsize*sizeof(void*);
printf("-----------------------------------\n");
printf("total: %d bytes\n", total);
printf("===================================\n");
-}
-
+ objc_mutex_unlock(__objc_runtime_mutex);
+}
+/* Returns the uninstalled dispatch table indicator.
+ If a class' dispatch table points to __objc_uninstalled_dtable
+ then that means it needs its dispatch table to be installed. */
+__inline__
+struct sarray*
+objc_get_uninstalled_dtable()
+{
+ return __objc_uninstalled_dtable;
+}
diff --git a/gnu/usr.bin/gcc/obstack.c b/gnu/usr.bin/gcc/obstack.c
index 3853c8c2f42..fb66d0c95cb 100644
--- a/gnu/usr.bin/gcc/obstack.c
+++ b/gnu/usr.bin/gcc/obstack.c
@@ -1,19 +1,29 @@
/* obstack.c - subroutines used implicitly by object stack macros
- Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Copyright (C) 1988,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
+ the C library, however. The master source lives in /gd/gnu/lib.
-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.
+ NOTE: The canonical source of this file is maintained with the GNU C Library.
+ Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
#include "obstack.h"
@@ -52,7 +62,7 @@ Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Determine default alignment. */
struct fooalign {char x; double d;};
#define DEFAULT_ALIGNMENT \
- ((PTR_INT_TYPE) ((char *)&((struct fooalign *) 0)->d - (char *)0))
+ ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
@@ -67,6 +77,28 @@ union fooround {long x; double d;};
#define COPYING_UNIT int
#endif
+
+/* The functions allocating more room by calling `obstack_chunk_alloc'
+ jump to the handler pointed to by `obstack_alloc_failed_handler'.
+ This variable by default points to the internal function
+ `print_and_abort'. */
+#if defined (__STDC__) && __STDC__
+static void print_and_abort (void);
+void (*obstack_alloc_failed_handler) (void) = print_and_abort;
+#else
+static void print_and_abort ();
+void (*obstack_alloc_failed_handler) () = print_and_abort;
+#endif
+
+/* Exit value used when `print_and_abort' is used. */
+#if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+int obstack_exit_failure = EXIT_FAILURE;
+
/* The non-GNU-C macros copy the obstack into this global variable
to avoid multiple evaluation. */
@@ -78,18 +110,33 @@ struct obstack *_obstack;
For free, do not use ?:, since some compilers, like the MIPS compilers,
do not allow (expr) ? void : void. */
+#if defined (__STDC__) && __STDC__
#define CALL_CHUNKFUN(h, size) \
(((h) -> use_extra_arg) \
? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
- : (*(h)->chunkfun) ((size)))
+ : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
#define CALL_FREEFUN(h, old_chunk) \
do { \
if ((h) -> use_extra_arg) \
(*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
else \
- (*(h)->freefun) ((old_chunk)); \
+ (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
} while (0)
+#else
+#define CALL_CHUNKFUN(h, size) \
+ (((h) -> use_extra_arg) \
+ ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
+ : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
+
+#define CALL_FREEFUN(h, old_chunk) \
+ do { \
+ if ((h) -> use_extra_arg) \
+ (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
+ else \
+ (*(void (*) ()) (h)->freefun) ((old_chunk)); \
+ } while (0)
+#endif
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
@@ -106,13 +153,18 @@ _obstack_begin (h, size, alignment, chunkfun, freefun)
struct obstack *h;
int size;
int alignment;
+#if defined (__STDC__) && __STDC__
+ POINTER (*chunkfun) (long);
+ void (*freefun) (void *);
+#else
POINTER (*chunkfun) ();
void (*freefun) ();
+#endif
{
- register struct _obstack_chunk* chunk; /* points to new chunk */
+ register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
- alignment = DEFAULT_ALIGNMENT;
+ alignment = (int) DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
@@ -130,25 +182,27 @@ _obstack_begin (h, size, alignment, chunkfun, freefun)
size = 4096 - extra;
}
+#if defined (__STDC__) && __STDC__
+ h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
h->freefun = freefun;
+#endif
h->chunk_size = size;
h->alignment_mask = alignment - 1;
h->use_extra_arg = 0;
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
- {
- h->alloc_failed = 1;
- return 0;
- }
- h->alloc_failed = 0;
+ (*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
/* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
return 1;
}
@@ -157,14 +211,19 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
struct obstack *h;
int size;
int alignment;
+#if defined (__STDC__) && __STDC__
+ POINTER (*chunkfun) (POINTER, long);
+ void (*freefun) (POINTER, POINTER);
+#else
POINTER (*chunkfun) ();
void (*freefun) ();
+#endif
POINTER arg;
{
- register struct _obstack_chunk* chunk; /* points to new chunk */
+ register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
- alignment = DEFAULT_ALIGNMENT;
+ alignment = (int) DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
@@ -182,8 +241,13 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
size = 4096 - extra;
}
+#if defined(__STDC__) && __STDC__
+ h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
+ h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+#else
h->chunkfun = (struct _obstack_chunk * (*)()) chunkfun;
h->freefun = freefun;
+#endif
h->chunk_size = size;
h->alignment_mask = alignment - 1;
h->extra_arg = arg;
@@ -191,17 +255,14 @@ _obstack_begin_1 (h, size, alignment, chunkfun, freefun, arg)
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
- {
- h->alloc_failed = 1;
- return 0;
- }
- h->alloc_failed = 0;
+ (*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = chunk->contents;
h->chunk_limit = chunk->limit
= (char *) chunk + h->chunk_size;
chunk->prev = 0;
/* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0;
+ h->alloc_failed = 0;
return 1;
}
@@ -216,12 +277,12 @@ _obstack_newchunk (h, length)
struct obstack *h;
int length;
{
- register struct _obstack_chunk* old_chunk = h->chunk;
- register struct _obstack_chunk* new_chunk;
+ register struct _obstack_chunk *old_chunk = h->chunk;
+ register struct _obstack_chunk *new_chunk;
register long new_size;
- register int obj_size = h->next_free - h->object_base;
- register int i;
- int already;
+ register long obj_size = h->next_free - h->object_base;
+ register long i;
+ long already;
/* Compute size for new chunk. */
new_size = (obj_size + length) + (obj_size >> 3) + 100;
@@ -231,11 +292,7 @@ _obstack_newchunk (h, length)
/* Allocate and initialize the new chunk. */
new_chunk = CALL_CHUNKFUN (h, new_size);
if (!new_chunk)
- {
- h->alloc_failed = 1;
- return;
- }
- h->alloc_failed = 0;
+ (*obstack_alloc_failed_handler) ();
h->chunk = new_chunk;
new_chunk->prev = old_chunk;
new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
@@ -290,14 +347,14 @@ _obstack_allocated_p (h, obj)
struct obstack *h;
POINTER obj;
{
- register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk* plp; /* point to previous chunk if any */
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = (h)->chunk;
/* We use >= rather than > since the object cannot be exactly at
the beginning of the chunk but might be an empty object exactly
- at the end of an adjacent chunk. */
- while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ at the end of an adjacent chunk. */
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
{
plp = lp->prev;
lp = plp;
@@ -318,14 +375,14 @@ _obstack_free (h, obj)
struct obstack *h;
POINTER obj;
{
- register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk* plp; /* point to previous chunk if any */
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = h->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk.
But there can be an empty object at that address
at the end of another chunk. */
- while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
{
plp = lp->prev;
CALL_FREEFUN (h, lp);
@@ -336,7 +393,7 @@ _obstack_free (h, obj)
}
if (lp)
{
- h->object_base = h->next_free = (char *)(obj);
+ h->object_base = h->next_free = (char *) (obj);
h->chunk_limit = lp->limit;
h->chunk = lp;
}
@@ -352,14 +409,14 @@ obstack_free (h, obj)
struct obstack *h;
POINTER obj;
{
- register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
- register struct _obstack_chunk* plp; /* point to previous chunk if any */
+ register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
+ register struct _obstack_chunk *plp; /* point to previous chunk if any */
lp = h->chunk;
/* We use >= because there cannot be an object at the beginning of a chunk.
But there can be an empty object at that address
at the end of another chunk. */
- while (lp != 0 && ((POINTER)lp >= obj || (POINTER)(lp)->limit < obj))
+ while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
{
plp = lp->prev;
CALL_FREEFUN (h, lp);
@@ -370,7 +427,7 @@ obstack_free (h, obj)
}
if (lp)
{
- h->object_base = h->next_free = (char *)(obj);
+ h->object_base = h->next_free = (char *) (obj);
h->chunk_limit = lp->limit;
h->chunk = lp;
}
@@ -379,6 +436,39 @@ obstack_free (h, obj)
abort ();
}
+int
+_obstack_memory_used (h)
+ struct obstack *h;
+{
+ register struct _obstack_chunk* lp;
+ register int nbytes = 0;
+
+ for (lp = h->chunk; lp != 0; lp = lp->prev)
+ {
+ nbytes += lp->limit - (char *) lp;
+ }
+ return nbytes;
+}
+
+/* Define the error handler. */
+#ifndef _
+# ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# ifndef _
+# define _(Str) gettext (Str)
+# endif
+# else
+# define _(Str) (Str)
+# endif
+#endif
+
+static void
+print_and_abort ()
+{
+ fputs (_("memory exhausted\n"), stderr);
+ exit (obstack_exit_failure);
+}
+
#if 0
/* These are now turned off because the applications do not use it
and it uses bcopy via obstack_grow, which causes trouble on sysV. */
@@ -417,6 +507,13 @@ int (obstack_room) (obstack)
return obstack_room (obstack);
}
+int (obstack_make_room) (obstack, length)
+ struct obstack *obstack;
+ int length;
+{
+ return obstack_make_room (obstack, length);
+}
+
void (obstack_grow) (obstack, pointer, length)
struct obstack *obstack;
POINTER pointer;
diff --git a/gnu/usr.bin/gcc/obstack.h b/gnu/usr.bin/gcc/obstack.h
index 28bcd44dba8..3edd3f4285e 100644
--- a/gnu/usr.bin/gcc/obstack.h
+++ b/gnu/usr.bin/gcc/obstack.h
@@ -1,19 +1,25 @@
/* obstack.h - object stack macros
- Copyright (C) 1988, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc.
+ Copyright (C) 1988,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
-This program is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
+ the C library, however. The master source lives in /gd/gnu/lib.
-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.
+ NOTE: The canonical source of this file is maintained with the GNU C Library.
+ Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ USA. */
/* Summary:
@@ -100,19 +106,23 @@ Summary:
/* Don't do the contents of this file more than once. */
-#ifndef __OBSTACK_H__
-#define __OBSTACK_H__
+#ifndef _OBSTACK_H
+#define _OBSTACK_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
-/* We use subtraction of (char *)0 instead of casting to int
+/* We use subtraction of (char *) 0 instead of casting to int
because on word-addressable machines a simple cast to int
may ignore the byte-within-word field of the pointer. */
#ifndef __PTR_TO_INT
-#define __PTR_TO_INT(P) ((P) - (char *)0)
+#define __PTR_TO_INT(P) ((P) - (char *) 0)
#endif
#ifndef __INT_TO_PTR
-#define __INT_TO_PTR(P) ((P) + (char *)0)
+#define __INT_TO_PTR(P) ((P) + (char *) 0)
#endif
/* We need the type of the resulting object. In ANSI C it is ptrdiff_t
@@ -138,6 +148,17 @@ Summary:
#define PTR_INT_TYPE long
#endif
+#if defined (_LIBC) || defined (HAVE_STRING_H)
+#include <string.h>
+#define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
+#else
+#ifdef memcpy
+#define _obstack_memcpy(To, From, N) memcpy ((To), (From), (N))
+#else
+#define _obstack_memcpy(To, From, N) bcopy ((From), (To), (N))
+#endif
+#endif
+
struct _obstack_chunk /* Lives at front of each chunk. */
{
char *limit; /* 1 past end of this chunk */
@@ -148,21 +169,32 @@ struct _obstack_chunk /* Lives at front of each chunk. */
struct obstack /* control current object in current chunk */
{
long chunk_size; /* preferred size to allocate chunks in */
- struct _obstack_chunk* chunk; /* address of current struct obstack_chunk */
+ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */
PTR_INT_TYPE temp; /* Temporary for some macros. */
int alignment_mask; /* Mask of alignment for each object. */
+#if defined (__STDC__) && __STDC__
+ /* These prototypes vary based on `use_extra_arg', and we use
+ casts to the prototypeless function type in all assignments,
+ but having prototypes here quiets -Wstrict-prototypes. */
+ struct _obstack_chunk *(*chunkfun) (void *, long);
+ void (*freefun) (void *, struct _obstack_chunk *);
+ void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+#else
struct _obstack_chunk *(*chunkfun) (); /* User's fcn to allocate a chunk. */
void (*freefun) (); /* User's function to free a chunk. */
char *extra_arg; /* first arg for chunk alloc/dealloc funcs */
+#endif
unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */
unsigned maybe_empty_object:1;/* There is a possibility that the current
chunk contains a zero-length object. This
prevents freeing the chunk if we allocate
a bigger chunk to replace it. */
- unsigned alloc_failed:1; /* chunk alloc func returned 0 */
+ unsigned alloc_failed:1; /* No longer used, as we now call the failed
+ handler on error, but retained for binary
+ compatibility. */
};
/* Declare the external functions we use; they are in obstack.c. */
@@ -171,14 +203,17 @@ struct obstack /* control current object in current chunk */
extern void _obstack_newchunk (struct obstack *, int);
extern void _obstack_free (struct obstack *, void *);
extern int _obstack_begin (struct obstack *, int, int,
- void *(*) (), void (*) ());
+ void *(*) (long), void (*) (void *));
extern int _obstack_begin_1 (struct obstack *, int, int,
- void *(*) (), void (*) (), void *);
+ void *(*) (void *, long),
+ void (*) (void *, void *), void *);
+extern int _obstack_memory_used (struct obstack *);
#else
extern void _obstack_newchunk ();
extern void _obstack_free ();
extern int _obstack_begin ();
extern int _obstack_begin_1 ();
+extern int _obstack_memory_used ();
#endif
#if defined (__STDC__) && __STDC__
@@ -209,6 +244,7 @@ void * obstack_finish (struct obstack *obstack);
int obstack_object_size (struct obstack *obstack);
int obstack_room (struct obstack *obstack);
+void obstack_make_room (struct obstack *obstack, int size);
void obstack_1grow_fast (struct obstack *obstack, int data_char);
void obstack_ptr_grow_fast (struct obstack *obstack, void *data);
void obstack_int_grow_fast (struct obstack *obstack, int data);
@@ -218,17 +254,30 @@ void * obstack_base (struct obstack *obstack);
void * obstack_next_free (struct obstack *obstack);
int obstack_alignment_mask (struct obstack *obstack);
int obstack_chunk_size (struct obstack *obstack);
+int obstack_memory_used (struct obstack *obstack);
#endif /* __STDC__ */
/* Non-ANSI C cannot really support alternative functions for these macros,
so we do not declare them. */
+
+/* Error handler called when `obstack_chunk_alloc' failed to allocate
+ more memory. This can be set to a user defined function. The
+ default action is to print a message and abort. */
+#if defined (__STDC__) && __STDC__
+extern void (*obstack_alloc_failed_handler) (void);
+#else
+extern void (*obstack_alloc_failed_handler) ();
+#endif
+
+/* Exit value used when `print_and_abort' is used. */
+extern int obstack_exit_failure;
/* Pointer to beginning of object being allocated or to be allocated next.
Note that this might not be the final address of the object
because a new chunk might be needed to hold the final size. */
-#define obstack_base(h) ((h)->alloc_failed ? 0 : (h)->object_base)
+#define obstack_base(h) ((h)->object_base)
/* Size for allocating ordinary chunks. */
@@ -236,12 +285,41 @@ int obstack_chunk_size (struct obstack *obstack);
/* Pointer to next byte not yet allocated in current chunk. */
-#define obstack_next_free(h) ((h)->alloc_failed ? 0 : (h)->next_free)
+#define obstack_next_free(h) ((h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */
#define obstack_alignment_mask(h) ((h)->alignment_mask)
+/* To prevent prototype warnings provide complete argument list in
+ standard C version. */
+#if defined (__STDC__) && __STDC__
+
+#define obstack_init(h) \
+ _obstack_begin ((h), 0, 0, \
+ (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free)
+
+#define obstack_begin(h, size) \
+ _obstack_begin ((h), (size), 0, \
+ (void *(*) (long)) obstack_chunk_alloc, (void (*) (void *)) obstack_chunk_free)
+
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+ _obstack_begin ((h), (size), (alignment), \
+ (void *(*) (long)) (chunkfun), (void (*) (void *)) (freefun))
+
+#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
+ _obstack_begin_1 ((h), (size), (alignment), \
+ (void *(*) (void *, long)) (chunkfun), \
+ (void (*) (void *, void *)) (freefun), (arg))
+
+#define obstack_chunkfun(h, newchunkfun) \
+ ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun))
+
+#define obstack_freefun(h, newfreefun) \
+ ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
+
+#else
+
#define obstack_init(h) \
_obstack_begin ((h), 0, 0, \
(void *(*) ()) obstack_chunk_alloc, (void (*) ()) obstack_chunk_free)
@@ -264,9 +342,13 @@ int obstack_chunk_size (struct obstack *obstack);
#define obstack_freefun(h, newfreefun) \
((h) -> freefun = (void (*)()) (newfreefun))
+#endif
+
#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = achar)
#define obstack_blank_fast(h,n) ((h)->next_free += (n))
+
+#define obstack_memory_used(h) _obstack_memory_used (h)
#if defined (__GNUC__) && defined (__STDC__) && __STDC__
/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
@@ -284,7 +366,6 @@ int obstack_chunk_size (struct obstack *obstack);
#define obstack_object_size(OBSTACK) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
- __o->alloc_failed ? 0 : \
(unsigned) (__o->next_free - __o->object_base); })
#define obstack_room(OBSTACK) \
@@ -292,17 +373,27 @@ int obstack_chunk_size (struct obstack *obstack);
({ struct obstack *__o = (OBSTACK); \
(unsigned) (__o->chunk_limit - __o->next_free); })
+#define obstack_make_room(OBSTACK,length) \
+__extension__ \
+({ struct obstack *__o = (OBSTACK); \
+ int __len = (length); \
+ if (__o->chunk_limit - __o->next_free < __len) \
+ _obstack_newchunk (__o, __len); \
+ (void) 0; })
+
+#define obstack_empty_p(OBSTACK) \
+ __extension__ \
+ ({ struct obstack *__o = (OBSTACK); \
+ (__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
+
#define obstack_grow(OBSTACK,where,length) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
int __len = (length); \
if (__o->next_free + __len > __o->chunk_limit) \
_obstack_newchunk (__o, __len); \
- if (!__o->alloc_failed) \
- { \
- bcopy ((char *) (where), __o->next_free, __len); \
- __o->next_free += __len; \
- } \
+ _obstack_memcpy (__o->next_free, (char *) (where), __len); \
+ __o->next_free += __len; \
(void) 0; })
#define obstack_grow0(OBSTACK,where,length) \
@@ -311,12 +402,9 @@ __extension__ \
int __len = (length); \
if (__o->next_free + __len + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, __len + 1); \
- if (!__o->alloc_failed) \
- { \
- bcopy ((char *) (where), __o->next_free, __len); \
- __o->next_free += __len; \
- *(__o->next_free)++ = 0; \
- } \
+ _obstack_memcpy (__o->next_free, (char *) (where), __len); \
+ __o->next_free += __len; \
+ *(__o->next_free)++ = 0; \
(void) 0; })
#define obstack_1grow(OBSTACK,datum) \
@@ -324,21 +412,19 @@ __extension__ \
({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, 1); \
- if (!__o->alloc_failed) \
- *(__o->next_free)++ = (datum); \
+ *(__o->next_free)++ = (datum); \
(void) 0; })
/* These assume that the obstack alignment is good enough for pointers or ints,
and that the data added so far to the current object
shares that much alignment. */
-
+
#define obstack_ptr_grow(OBSTACK,datum) \
__extension__ \
({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (void *)); \
- if (!__o->alloc_failed) \
- *((void **)__o->next_free)++ = ((void *)datum); \
+ *((void **)__o->next_free)++ = ((void *)datum); \
(void) 0; })
#define obstack_int_grow(OBSTACK,datum) \
@@ -346,12 +432,11 @@ __extension__ \
({ struct obstack *__o = (OBSTACK); \
if (__o->next_free + sizeof (int) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (int)); \
- if (!__o->alloc_failed) \
- *((int *)__o->next_free)++ = ((int)datum); \
+ *((int *)__o->next_free)++ = ((int)datum); \
(void) 0; })
-#define obstack_ptr_grow_fast(h,aptr) (*((void **)(h)->next_free)++ = (void *)aptr)
-#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
+#define obstack_ptr_grow_fast(h,aptr) (*((void **) (h)->next_free)++ = (void *)aptr)
+#define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint)
#define obstack_blank(OBSTACK,length) \
__extension__ \
@@ -359,8 +444,7 @@ __extension__ \
int __len = (length); \
if (__o->chunk_limit - __o->next_free < __len) \
_obstack_newchunk (__o, __len); \
- if (!__o->alloc_failed) \
- __o->next_free += __len; \
+ __o->next_free += __len; \
(void) 0; })
#define obstack_alloc(OBSTACK,length) \
@@ -387,21 +471,16 @@ __extension__ \
__extension__ \
({ struct obstack *__o1 = (OBSTACK); \
void *value; \
- if (__o1->alloc_failed) \
- value = 0; \
- else \
- { \
- value = (void *) __o1->object_base; \
- if (__o1->next_free == value) \
- __o1->maybe_empty_object = 1; \
- __o1->next_free \
- = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
- & ~ (__o1->alignment_mask)); \
- if (__o1->next_free - (char *)__o1->chunk \
- > __o1->chunk_limit - (char *)__o1->chunk) \
- __o1->next_free = __o1->chunk_limit; \
- __o1->object_base = __o1->next_free; \
- } \
+ value = (void *) __o1->object_base; \
+ if (__o1->next_free == value) \
+ __o1->maybe_empty_object = 1; \
+ __o1->next_free \
+ = __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
+ & ~ (__o1->alignment_mask)); \
+ if (__o1->next_free - (char *)__o1->chunk \
+ > __o1->chunk_limit - (char *)__o1->chunk) \
+ __o1->next_free = __o1->chunk_limit; \
+ __o1->object_base = __o1->next_free; \
value; })
#define obstack_free(OBSTACK, OBJ) \
@@ -415,61 +494,63 @@ __extension__ \
#else /* not __GNUC__ or not __STDC__ */
#define obstack_object_size(h) \
- (unsigned) ((h)->alloc_failed ? 0 : (h)->next_free - (h)->object_base)
+ (unsigned) ((h)->next_free - (h)->object_base)
#define obstack_room(h) \
(unsigned) ((h)->chunk_limit - (h)->next_free)
+#define obstack_empty_p(h) \
+ ((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
+
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
so that we can avoid having void expressions
in the arms of the conditional expression.
Casting the third operand to void was tried before,
but some compilers won't accept it. */
+#define obstack_make_room(h,length) \
+( (h)->temp = (length), \
+ (((h)->next_free + (h)->temp > (h)->chunk_limit) \
+ ? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
+
#define obstack_grow(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
- ((h)->alloc_failed ? 0 : \
- (bcopy ((char *) (where), (h)->next_free, (h)->temp), \
- (h)->next_free += (h)->temp)))
+ _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \
+ (h)->next_free += (h)->temp)
#define obstack_grow0(h,where,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
- ((h)->alloc_failed ? 0 : \
- (bcopy ((char *) (where), (h)->next_free, (h)->temp), \
+ _obstack_memcpy ((h)->next_free, (char *) (where), (h)->temp), \
(h)->next_free += (h)->temp, \
- *((h)->next_free)++ = 0)))
+ *((h)->next_free)++ = 0)
#define obstack_1grow(h,datum) \
( (((h)->next_free + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), 1), 0) : 0), \
- ((h)->alloc_failed ? 0 : \
- (*((h)->next_free)++ = (datum))))
+ (*((h)->next_free)++ = (datum)))
#define obstack_ptr_grow(h,datum) \
( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
- ((h)->alloc_failed ? 0 : \
- (*((char **)(((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *)datum))))
+ (*((char **) (((h)->next_free+=sizeof(char *))-sizeof(char *))) = ((char *) datum)))
#define obstack_int_grow(h,datum) \
( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
- ((h)->alloc_failed ? 0 : \
- (*((int *)(((h)->next_free+=sizeof(int))-sizeof(int))) = ((int)datum))))
+ (*((int *) (((h)->next_free+=sizeof(int))-sizeof(int))) = ((int) datum)))
-#define obstack_ptr_grow_fast(h,aptr) (*((char **)(h)->next_free)++ = (char *)aptr)
-#define obstack_int_grow_fast(h,aint) (*((int *)(h)->next_free)++ = (int)aint)
+#define obstack_ptr_grow_fast(h,aptr) (*((char **) (h)->next_free)++ = (char *) aptr)
+#define obstack_int_grow_fast(h,aint) (*((int *) (h)->next_free)++ = (int) aint)
#define obstack_blank(h,length) \
( (h)->temp = (length), \
(((h)->chunk_limit - (h)->next_free < (h)->temp) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
- ((h)->alloc_failed ? 0 : \
- ((h)->next_free += (h)->temp)))
+ ((h)->next_free += (h)->temp))
#define obstack_alloc(h,length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
@@ -481,30 +562,29 @@ __extension__ \
(obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
#define obstack_finish(h) \
-( (h)->alloc_failed ? 0 : \
- (((h)->next_free == (h)->object_base \
+( ((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \
: 0), \
(h)->temp = __PTR_TO_INT ((h)->object_base), \
(h)->next_free \
= __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
& ~ ((h)->alignment_mask)), \
- (((h)->next_free - (char *)(h)->chunk \
- > (h)->chunk_limit - (char *)(h)->chunk) \
+ (((h)->next_free - (char *) (h)->chunk \
+ > (h)->chunk_limit - (char *) (h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \
- __INT_TO_PTR ((h)->temp)))
+ __INT_TO_PTR ((h)->temp))
#if defined (__STDC__) && __STDC__
#define obstack_free(h,obj) \
-( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
#else
#define obstack_free(h,obj) \
-( (h)->temp = (char *)(obj) - (char *) (h)->chunk, \
+( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
@@ -513,4 +593,8 @@ __extension__ \
#endif /* not __GNUC__ or not __STDC__ */
-#endif /* not __OBSTACK_H__ */
+#ifdef __cplusplus
+} /* C++ */
+#endif
+
+#endif /* obstack.h */
diff --git a/gnu/usr.bin/gcc/optabs.c b/gnu/usr.bin/gcc/optabs.c
index 2732ebed107..55c092f9532 100644
--- a/gnu/usr.bin/gcc/optabs.c
+++ b/gnu/usr.bin/gcc/optabs.c
@@ -1,5 +1,5 @@
/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,6 +20,7 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "tree.h"
#include "flags.h"
@@ -88,7 +89,7 @@ optab strlen_optab;
/* Tables of patterns for extending one integer mode to another. */
enum insn_code extendtab[MAX_MACHINE_MODE][MAX_MACHINE_MODE][2];
-/* Tables of patterns for converting between fixed and floating point. */
+/* Tables of patterns for converting between fixed and floating point. */
enum insn_code fixtab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
enum insn_code fixtrunctab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
enum insn_code floattab[NUM_MACHINE_MODES][NUM_MACHINE_MODES][2];
@@ -118,6 +119,14 @@ rtx bcmp_libfunc;
rtx memset_libfunc;
rtx bzero_libfunc;
+rtx throw_libfunc;
+rtx sjthrow_libfunc;
+rtx sjpopnthrow_libfunc;
+rtx terminate_libfunc;
+rtx setjmp_libfunc;
+rtx longjmp_libfunc;
+rtx get_dynamic_handler_chain_libfunc;
+
rtx eqhf2_libfunc;
rtx nehf2_libfunc;
rtx gthf2_libfunc;
@@ -201,6 +210,12 @@ rtx fixunstfsi_libfunc;
rtx fixunstfdi_libfunc;
rtx fixunstfti_libfunc;
+rtx chkr_check_addr_libfunc;
+rtx chkr_set_right_libfunc;
+rtx chkr_copy_bitmap_libfunc;
+rtx chkr_check_exec_libfunc;
+rtx chkr_check_str_libfunc;
+
/* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
gives the gen_function to make a branch to test that condition. */
@@ -438,7 +453,7 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
temp = gen_reg_rtx (mode);
/* If it is a commutative operator and the modes would match
- if we would swap the operands, we can save the conversions. */
+ if we would swap the operands, we can save the conversions. */
if (commutative_op)
{
if (GET_MODE (op0) != mode0 && GET_MODE (op1) != mode1
@@ -919,12 +934,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
{
/* Store carry from main add/subtract. */
carry_out = gen_reg_rtx (word_mode);
- carry_out = emit_store_flag (carry_out,
- binoptab == add_optab ? LTU : GTU,
- x, op0_piece,
- word_mode, 1, normalizep);
- if (carry_out == 0)
- break;
+ carry_out = emit_store_flag_force (carry_out,
+ (binoptab == add_optab
+ ? LTU : GTU),
+ x, op0_piece,
+ word_mode, 1, normalizep);
}
if (i > 0)
@@ -943,11 +957,11 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
{
/* THIS CODE HAS NOT BEEN TESTED. */
/* Get out carry from adding/subtracting carry in. */
- carry_tmp = emit_store_flag (carry_tmp,
- binoptab == add_optab
- ? LTU : GTU,
- x, carry_in,
- word_mode, 1, normalizep);
+ carry_tmp = emit_store_flag_force (carry_tmp,
+ binoptab == add_optab
+ ? LTU : GTU,
+ x, carry_in,
+ word_mode, 1, normalizep);
/* Logical-ior the two poss. carry together. */
carry_out = expand_binop (word_mode, ior_optab,
@@ -963,13 +977,16 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (i == GET_MODE_BITSIZE (mode) / BITS_PER_WORD)
{
- rtx temp = emit_move_insn (target, target);
+ if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ {
+ rtx temp = emit_move_insn (target, target);
- REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (binoptab->code, mode,
- copy_rtx (xop0),
- copy_rtx (xop1)),
- REG_NOTES (temp));
+ REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
+ gen_rtx (binoptab->code, mode,
+ copy_rtx (xop0),
+ copy_rtx (xop1)),
+ REG_NOTES (temp));
+ }
return target;
}
else
@@ -1143,12 +1160,15 @@ expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
if (temp != 0)
{
- temp = emit_move_insn (product, product);
- REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (MULT, mode, copy_rtx (op0),
- copy_rtx (op1)),
- REG_NOTES (temp));
-
+ if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
+ {
+ temp = emit_move_insn (product, product);
+ REG_NOTES (temp) = gen_rtx (EXPR_LIST, REG_EQUAL,
+ gen_rtx (MULT, mode,
+ copy_rtx (op0),
+ copy_rtx (op1)),
+ REG_NOTES (temp));
+ }
return product;
}
}
@@ -2116,6 +2136,13 @@ expand_abs (mode, op0, target, unsignedp, safe)
}
/* If that does not win, use conditional jump and negate. */
+
+ /* It is safe to use the target if it is the same
+ as the source if this is also a pseudo register */
+ if (op0 == target && GET_CODE (op0) == REG
+ && REGNO (op0) >= FIRST_PSEUDO_REGISTER)
+ safe = 1;
+
op1 = gen_label_rtx ();
if (target == 0 || ! safe
|| GET_MODE (target) != mode
@@ -2374,7 +2401,10 @@ emit_unop_insn (icode, target, op0, code)
op0 = protect_from_queue (op0, 0);
- if (flag_force_mem)
+ /* Sign and zero extension from memory is often done specially on
+ RISC machines, so forcing into a register here can pessimize
+ code. */
+ if (flag_force_mem && code != SIGN_EXTEND && code != ZERO_EXTEND)
op0 = force_not_mem (op0);
/* Now, if insn does not accept our operands, put them into pseudos. */
@@ -2603,8 +2633,10 @@ emit_libcall_block (insns, target, result, equiv)
}
last = emit_move_insn (target, result);
- REG_NOTES (last) = gen_rtx (EXPR_LIST,
- REG_EQUAL, copy_rtx (equiv), REG_NOTES (last));
+ if (mov_optab->handlers[(int) GET_MODE (target)].insn_code
+ != CODE_FOR_nothing)
+ REG_NOTES (last) = gen_rtx (EXPR_LIST,
+ REG_EQUAL, copy_rtx (equiv), REG_NOTES (last));
if (prev == 0)
first = get_insns ();
@@ -2741,18 +2773,32 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
else
#endif
{
+ rtx result;
+
#ifdef TARGET_MEM_FUNCTIONS
emit_library_call (memcmp_libfunc, 0,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- size, Pmode);
+ convert_to_mode (TYPE_MODE (sizetype), size,
+ TREE_UNSIGNED (sizetype)),
+ TYPE_MODE (sizetype));
#else
emit_library_call (bcmp_libfunc, 0,
TYPE_MODE (integer_type_node), 3,
XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- size, Pmode);
+ convert_to_mode (TYPE_MODE (integer_type_node),
+ size,
+ TREE_UNSIGNED (integer_type_node)),
+ TYPE_MODE (integer_type_node));
#endif
- emit_cmp_insn (hard_libcall_value (TYPE_MODE (integer_type_node)),
+
+ /* Immediately move the result of the libcall into a pseudo
+ register so reload doesn't clobber the value if it needs
+ the return register for a spill reg. */
+ result = gen_reg_rtx (TYPE_MODE (integer_type_node));
+ emit_move_insn (result,
+ hard_libcall_value (TYPE_MODE (integer_type_node)));
+ emit_cmp_insn (result,
const0_rtx, comparison, NULL_RTX,
TYPE_MODE (integer_type_node), 0, 0);
}
@@ -2829,6 +2875,8 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
&& class != MODE_FLOAT)
{
rtx libfunc = cmp_optab->handlers[(int) mode].libfunc;
+ rtx result;
+
/* If we want unsigned, and this mode has a distinct unsigned
comparison routine, use that. */
if (unsignedp && ucmp_optab->handlers[(int) mode].libfunc)
@@ -2837,11 +2885,16 @@ emit_cmp_insn (x, y, comparison, size, mode, unsignedp, align)
emit_library_call (libfunc, 1,
word_mode, 2, x, mode, y, mode);
+ /* Immediately move the result of the libcall into a pseudo
+ register so reload doesn't clobber the value if it needs
+ the return register for a spill reg. */
+ result = gen_reg_rtx (word_mode);
+ emit_move_insn (result, hard_libcall_value (word_mode));
+
/* Integer comparison returns a result that must be compared against 1,
so that even if we do an unsigned compare afterward,
there is still a value that can represent the result "less than". */
-
- emit_cmp_insn (hard_libcall_value (word_mode), const1_rtx,
+ emit_cmp_insn (result, const1_rtx,
comparison, NULL_RTX, word_mode, unsignedp, 0);
return;
}
@@ -2880,6 +2933,7 @@ emit_float_lib_cmp (x, y, comparison)
{
enum machine_mode mode = GET_MODE (x);
rtx libfunc = 0;
+ rtx result;
if (mode == HFmode)
switch (comparison)
@@ -2907,6 +2961,9 @@ emit_float_lib_cmp (x, y, comparison)
case LE:
libfunc = lehf2_libfunc;
break;
+
+ default:
+ break;
}
else if (mode == SFmode)
switch (comparison)
@@ -2934,6 +2991,9 @@ emit_float_lib_cmp (x, y, comparison)
case LE:
libfunc = lesf2_libfunc;
break;
+
+ default:
+ break;
}
else if (mode == DFmode)
switch (comparison)
@@ -2961,6 +3021,9 @@ emit_float_lib_cmp (x, y, comparison)
case LE:
libfunc = ledf2_libfunc;
break;
+
+ default:
+ break;
}
else if (mode == XFmode)
switch (comparison)
@@ -2988,6 +3051,9 @@ emit_float_lib_cmp (x, y, comparison)
case LE:
libfunc = lexf2_libfunc;
break;
+
+ default:
+ break;
}
else if (mode == TFmode)
switch (comparison)
@@ -3015,6 +3081,9 @@ emit_float_lib_cmp (x, y, comparison)
case LE:
libfunc = letf2_libfunc;
break;
+
+ default:
+ break;
}
else
{
@@ -3044,7 +3113,13 @@ emit_float_lib_cmp (x, y, comparison)
emit_library_call (libfunc, 1,
word_mode, 2, x, mode, y, mode);
- emit_cmp_insn (hard_libcall_value (word_mode), const0_rtx, comparison,
+ /* Immediately move the result of the libcall into a pseudo
+ register so reload doesn't clobber the value if it needs
+ the return register for a spill reg. */
+ result = gen_reg_rtx (word_mode);
+ emit_move_insn (result, hard_libcall_value (word_mode));
+
+ emit_cmp_insn (result, const0_rtx, comparison,
NULL_RTX, word_mode, 0, 0);
}
@@ -3487,7 +3562,7 @@ expand_float (to, from, unsignedp)
/* There is no such mode. Pretend the target is wide enough. */
fmode = GET_MODE (to);
- /* Avoid double-rounding when TO is narrower than FROM. */
+ /* Avoid double-rounding when TO is narrower than FROM. */
if ((significand_size (fmode) + 1)
< GET_MODE_BITSIZE (GET_MODE (from)))
{
@@ -3785,13 +3860,16 @@ expand_fix (to, from, unsignedp)
emit_label (lab2);
- /* Make a place for a REG_NOTE and add it. */
- insn = emit_move_insn (to, to);
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (UNSIGNED_FIX, GET_MODE (to),
- copy_rtx (from)),
- REG_NOTES (insn));
-
+ if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
+ != CODE_FOR_nothing)
+ {
+ /* Make a place for a REG_NOTE and add it. */
+ insn = emit_move_insn (to, to);
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
+ gen_rtx (UNSIGNED_FIX, GET_MODE (to),
+ copy_rtx (from)),
+ REG_NOTES (insn));
+ }
return;
}
#endif
@@ -3877,10 +3955,13 @@ expand_fix (to, from, unsignedp)
GET_MODE (to), from));
}
- if (GET_MODE (to) == GET_MODE (target))
- emit_move_insn (to, target);
- else
- convert_move (to, target, 0);
+ if (target != to)
+ {
+ if (GET_MODE (to) == GET_MODE (target))
+ emit_move_insn (to, target);
+ else
+ convert_move (to, target, 0);
+ }
}
static optab
@@ -4079,6 +4160,7 @@ init_optabs ()
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
movstr_optab[i] = CODE_FOR_nothing;
+ clrstr_optab[i] = CODE_FOR_nothing;
#ifdef HAVE_SECONDARY_RELOADS
reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
@@ -4213,6 +4295,19 @@ init_optabs ()
memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
+ throw_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__throw");
+ sjthrow_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__sjthrow");
+ sjpopnthrow_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__sjpopnthrow");
+ terminate_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__terminate");
+#ifndef DONT_USE_BUILTIN_SETJMP
+ setjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__builtin_setjmp");
+ longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__builtin_longjmp");
+#else
+ setjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "setjmp");
+ longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "longjmp");
+#endif
+ get_dynamic_handler_chain_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_dynamic_handler_chain");
+
eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
gthf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gthf2");
@@ -4296,6 +4391,13 @@ init_optabs ()
fixunstfdi_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfdi");
fixunstfti_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__fixunstfti");
+ /* For check-memory-usage. */
+ chkr_check_addr_libfunc = gen_rtx (SYMBOL_REF, VOIDmode, "chkr_check_addr");
+ chkr_set_right_libfunc = gen_rtx (SYMBOL_REF, VOIDmode, "chkr_set_right");
+ chkr_copy_bitmap_libfunc = gen_rtx (SYMBOL_REF, VOIDmode, "chkr_copy_bitmap");
+ chkr_check_exec_libfunc = gen_rtx (SYMBOL_REF, VOIDmode, "chkr_check_exec");
+ chkr_check_str_libfunc = gen_rtx (SYMBOL_REF, VOIDmode, "chkr_check_str");
+
#ifdef INIT_TARGET_OPTABS
/* Allow the target to add more libcalls or rename some, etc. */
INIT_TARGET_OPTABS;
@@ -4304,7 +4406,7 @@ init_optabs ()
#ifdef BROKEN_LDEXP
-/* SCO 3.2 apparently has a broken ldexp. */
+/* SCO 3.2 apparently has a broken ldexp. */
double
ldexp(x,n)
diff --git a/gnu/usr.bin/gcc/output.h b/gnu/usr.bin/gcc/output.h
index 7ef8b2c61b1..f1725b027b9 100644
--- a/gnu/usr.bin/gcc/output.h
+++ b/gnu/usr.bin/gcc/output.h
@@ -1,6 +1,6 @@
/* Declarations for insn-output.c. These functions are defined in recog.c,
final.c, and varasm.c.
- Copyright (C) 1987, 1991, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991, 1994, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -56,20 +56,20 @@ extern void shorten_branches PROTO((rtx));
for the new function. The label for the function and associated
assembler pseudo-ops have already been output in
`assemble_start_function'. */
-extern void final_start_function STDIO_PROTO((rtx, FILE *, int));
+extern void final_start_function PROTO((rtx, FILE *, int));
/* Output assembler code for the end of a function.
For clarity, args are same as those of `final_start_function'
even though not all of them are needed. */
-extern void final_end_function STDIO_PROTO((rtx, FILE *, int));
+extern void final_end_function PROTO((rtx, FILE *, int));
/* Output assembler code for some insns: all or part of a function. */
-extern void final STDIO_PROTO((rtx, FILE *, int, int));
+extern void final PROTO((rtx, FILE *, int, int));
/* The final scan for one insn, INSN. Args are same as in `final', except
that INSN is the insn being scanned. Value returned is the next insn to
be scanned. */
-extern rtx final_scan_insn STDIO_PROTO((rtx, FILE *, int, int, int));
+extern rtx final_scan_insn PROTO((rtx, FILE *, int, int, int));
/* Replace a SUBREG with a REG or a MEM, based on the thing it is a
subreg of. */
@@ -93,12 +93,11 @@ extern void output_address PROTO((rtx));
/* Print an integer constant expression in assembler syntax.
Addition and subtraction are the only arithmetic
that may appear in these expressions. */
-extern void output_addr_const STDIO_PROTO((FILE *, rtx));
+extern void output_addr_const PROTO((FILE *, rtx));
/* Output a string of assembler code, substituting numbers, strings
and fixed syntactic prefixes. */
-extern void asm_fprintf STDIO_PROTO(PVPROTO((FILE *file,
- char *p, ...)));
+extern void asm_fprintf PROTO(PVPROTO((FILE *file, char *p, ...)));
/* Split up a CONST_DOUBLE or integer constant rtx into two rtx's for single
words. */
@@ -114,6 +113,13 @@ extern int only_leaf_regs_used PROTO((void));
/* Scan IN_RTX and its subexpressions, and renumber all regs into those
available in leaf functions. */
extern void leaf_renumber_regs_insn PROTO((rtx));
+
+/* Functions in flow.c */
+extern void allocate_for_life_analysis PROTO((void));
+extern int regno_uninitialized PROTO((int));
+extern int regno_clobbered_at_setjmp PROTO((int));
+extern void dump_flow_info PROTO((FILE *));
+extern void flow_analysis PROTO((rtx, int, FILE *));
#endif
/* Functions in varasm.c. */
@@ -134,12 +140,16 @@ extern int in_text_section PROTO((void));
#ifdef TREE_CODE
/* Tell assembler to change to section NAME for DECL.
If DECL is NULL, just switch to section NAME.
- If NAME is NULL, get the name from DECL. */
-extern void named_section PROTO((tree, char *));
+ If NAME is NULL, get the name from DECL.
+ If RELOC is 1, the initializer for DECL contains relocs. */
+extern void named_section PROTO((tree, char *, int));
/* Tell assembler to switch to the section for function DECL. */
extern void function_section PROTO((tree));
+/* Tell assembler to switch to the section for the exception table. */
+extern void exception_section PROTO((void));
+
/* Create the rtl to represent a function, for a function definition.
DECL is a FUNCTION_DECL node which describes which function.
The rtl is stored into DECL. */
@@ -246,7 +256,7 @@ extern void assemble_label PROTO((char *));
Otherwise NAME is transformed in an implementation-defined way
(usually by the addition of an underscore).
Many macros in the tm file are defined to call this function. */
-extern void assemble_name STDIO_PROTO((FILE *, char *));
+extern void assemble_name PROTO((FILE *, char *));
#ifdef RTX_CODE
/* Assemble the integer constant X into an object of SIZE bytes.
@@ -426,3 +436,14 @@ extern int sdb_begin_function_line;
#ifdef BUFSIZ
extern FILE *asm_out_file;
#endif
+
+/* Decide whether DECL needs to be in a writable section. RELOC is the same
+ as for SELECT_SECTION. */
+
+#define DECL_READONLY_SECTION(DECL,RELOC) \
+ (TREE_READONLY (DECL) \
+ && ! TREE_THIS_VOLATILE (DECL) \
+ && DECL_INITIAL (DECL) \
+ && (DECL_INITIAL (DECL) == error_mark_node \
+ || TREE_CONSTANT (DECL_INITIAL (DECL))) \
+ && ! (RELOC && (flag_pic || DECL_ONE_ONLY (DECL))))
diff --git a/gnu/usr.bin/gcc/print-rtl.c b/gnu/usr.bin/gcc/print-rtl.c
index 20d34dbdc8e..60405bd8a81 100644
--- a/gnu/usr.bin/gcc/print-rtl.c
+++ b/gnu/usr.bin/gcc/print-rtl.c
@@ -1,5 +1,5 @@
/* Print RTL for GNU C Compiler.
- Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -47,6 +47,8 @@ char spaces[] = "
static int sawclose = 0;
+static int indent;
+
/* Names for patterns. Non-zero only when linked with insn-output.c. */
extern char **insn_name_ptr;
@@ -57,7 +59,6 @@ static void
print_rtx (in_rtx)
register rtx in_rtx;
{
- static int indent;
register int i, j;
register char *format_ptr;
register int is_insn;
@@ -108,6 +109,14 @@ print_rtx (in_rtx)
{
case 'S':
case 's':
+ if (i == 3 && GET_CODE (in_rtx) == NOTE
+ && (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_BEG
+ || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_END))
+ {
+ fprintf (outfile, " %d", NOTE_BLOCK_NUMBER (in_rtx));
+ sawclose = 1;
+ break;
+ }
if (XSTR (in_rtx, i) == 0)
fprintf (outfile, " \"\"");
else
@@ -158,13 +167,8 @@ print_rtx (in_rtx)
break;
case 'w':
- fprintf (outfile,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- " %d",
-#else
- " %ld",
-#endif
- XWINT (in_rtx, i));
+ fprintf (outfile, " ");
+ fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i));
break;
case 'i':
@@ -220,6 +224,25 @@ print_rtx (in_rtx)
sawclose = 1;
}
+/* Print an rtx on the current line of FILE. Initially indent IND
+ characters. */
+
+void
+print_inline_rtx (outf, x, ind)
+ FILE *outf;
+ rtx x;
+{
+ int oldsaw = sawclose;
+ int oldindent = indent;
+
+ sawclose = 0;
+ indent = ind;
+ outfile = outf;
+ print_rtx (x);
+ sawclose = oldsaw;
+ indent = oldindent;
+}
+
/* Call this function from the debugger to see what X looks like. */
void
@@ -271,7 +294,7 @@ debug_rtx_list (x, n)
The found insn is returned to enable further debugging analysis. */
rtx
-debug_rtx_find(x, uid)
+debug_rtx_find (x, uid)
rtx x;
int uid;
{
@@ -327,3 +350,16 @@ print_rtl (outf, rtx_first)
print_rtx (rtx_first);
}
}
+
+/* Like print_rtx, except specify a file. */
+
+void
+print_rtl_single (outf, x)
+ FILE *outf;
+ rtx x;
+{
+ outfile = outf;
+ sawclose = 0;
+ print_rtx (x);
+ putc ('\n', outf);
+}
diff --git a/gnu/usr.bin/gcc/print-tree.c b/gnu/usr.bin/gcc/print-tree.c
index 7f9dd10063c..f7468536b55 100644
--- a/gnu/usr.bin/gcc/print-tree.c
+++ b/gnu/usr.bin/gcc/print-tree.c
@@ -1,5 +1,5 @@
/* Prints out tree in human readable form - GNU C-compiler
- Copyright (C) 1990, 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1990, 91, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -109,38 +109,18 @@ print_node_brief (file, prefix, node, indent)
if (TREE_CONSTANT_OVERFLOW (node))
fprintf (file, " overflow");
+ fprintf (file, " ");
if (TREE_INT_CST_HIGH (node) == 0)
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- " %1u",
-#else
- " %1lu",
-#endif
- TREE_INT_CST_LOW (node));
+ fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED, TREE_INT_CST_LOW (node));
else if (TREE_INT_CST_HIGH (node) == -1
&& TREE_INT_CST_LOW (node) != 0)
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- " -%1u",
-#else
- " -%1lu",
-#endif
+ {
+ fprintf (file, "-");
+ fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED,
-TREE_INT_CST_LOW (node));
+ }
else
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == 64
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
- " 0x%lx%016lx",
-#else
- " 0x%x%016x",
-#endif
-#else
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
- " 0x%lx%08lx",
-#else
- " 0x%x%08x",
-#endif
-#endif
+ fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node));
}
if (TREE_CODE (node) == REAL_CST)
@@ -231,7 +211,7 @@ print_node (file, prefix, node, indent)
return;
}
- /* It is unsafe to look at any other filds of an ERROR_MARK node. */
+ /* It is unsafe to look at any other filds of an ERROR_MARK node. */
if (TREE_CODE (node) == ERROR_MARK)
{
print_node_brief (file, prefix, node, indent);
@@ -417,7 +397,6 @@ print_node (file, prefix, node, indent)
DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node));
print_node (file, "size", DECL_SIZE (node), indent + 4);
- print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4);
indent_to (file, indent + 3);
if (TREE_CODE (node) != FUNCTION_DECL)
fprintf (file, " align %d", DECL_ALIGN (node));
@@ -562,9 +541,8 @@ print_node (file, prefix, node, indent)
case '2':
case 'r':
case 's':
- switch (TREE_CODE (node))
+ if (TREE_CODE (node) == BIND_EXPR)
{
- case BIND_EXPR:
print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4);
print_node (file, "body", TREE_OPERAND (node, 1), indent + 4);
print_node (file, "block", TREE_OPERAND (node, 2), indent + 4);
@@ -591,6 +569,8 @@ print_node (file, prefix, node, indent)
break;
case RTL_EXPR:
first_rtl = 0;
+ default:
+ break;
}
for (i = 0; i < len; i++)
{
@@ -622,38 +602,19 @@ print_node (file, prefix, node, indent)
if (TREE_CONSTANT_OVERFLOW (node))
fprintf (file, " overflow");
+ fprintf (file, " ");
if (TREE_INT_CST_HIGH (node) == 0)
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- " %1u",
-#else
- " %1lu",
-#endif
+ fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED,
TREE_INT_CST_LOW (node));
else if (TREE_INT_CST_HIGH (node) == -1
&& TREE_INT_CST_LOW (node) != 0)
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
- " -%1u",
-#else
- " -%1lu",
-#endif
- -TREE_INT_CST_LOW (node));
+ {
+ fprintf (file, "-");
+ fprintf (file, HOST_WIDE_INT_PRINT_UNSIGNED,
+ -TREE_INT_CST_LOW (node));
+ }
else
- fprintf (file,
-#if HOST_BITS_PER_WIDE_INT == 64
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
- " 0x%lx%016lx",
-#else
- " 0x%x%016x",
-#endif
-#else
-#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT
- " 0x%lx%08lx",
-#else
- " 0x%x%08x",
-#endif
-#endif
+ fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
TREE_INT_CST_HIGH (node), TREE_INT_CST_LOW (node));
break;
@@ -729,6 +690,10 @@ print_node (file, prefix, node, indent)
case OP_IDENTIFIER:
print_node (file, "op1", TREE_PURPOSE (node), indent + 4);
print_node (file, "op2", TREE_VALUE (node), indent + 4);
+ break;
+
+ default:
+ break;
}
break;
diff --git a/gnu/usr.bin/gcc/protoize.c b/gnu/usr.bin/gcc/protoize.c
index 9728bf2718f..18f4ce528a1 100644
--- a/gnu/usr.bin/gcc/protoize.c
+++ b/gnu/usr.bin/gcc/protoize.c
@@ -1,5 +1,5 @@
/* Protoize program - Original version by Ron Guilmette (rfg@segfault.us.com).
- Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,7 +20,7 @@ Boston, MA 02111-1307, USA. */
/* Any reasonable C++ compiler should have all of the same features
as __STDC__ plus more, so make sure that __STDC__ is defined if
- __cplusplus is defined. */
+ __cplusplus is defined. */
#if defined(__cplusplus) && !defined(__STDC__)
#define __STDC__ 1
@@ -65,7 +65,7 @@ Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
-#ifndef _WIN32
+#if ! defined (_WIN32) || defined (__CYGWIN32__)
#if defined(POSIX) || defined(CONCURRENT)
#include <dirent.h>
#else
@@ -74,6 +74,20 @@ Boston, MA 02111-1307, USA. */
#endif
#include <setjmp.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
+
+#include "gansidecl.h"
+
/* Include getopt.h for the sake of getopt_long.
We don't need the declaration of getopt, and it could conflict
with something from a system header file, so effectively nullify that. */
@@ -87,11 +101,7 @@ extern int errno;
#ifndef HAVE_STRERROR
extern int sys_nerr;
-#if defined(bsd4_4)
-extern const char *const sys_errlist[];
-#else
extern char *sys_errlist[];
-#endif
#else
extern char *strerror();
#endif
@@ -107,7 +117,6 @@ extern char *version_string;
#define my_access(file,flag) access((char *)file, flag)
#define my_stat(file,pkt) stat((char *)file, pkt)
-#define my_execvp(prog,argv) execvp((char *)prog, (char **)argv)
#define my_link(file1, file2) link((char *)file1, (char *)file2)
#define my_unlink(file) unlink((char *)file)
#define my_open(file, mode, flag) open((char *)file, mode, flag)
@@ -115,6 +124,16 @@ extern char *version_string;
extern char *getpwd ();
+extern char *choose_temp_base PROTO ((void));
+
+extern int pexecute PROTO ((const char *, char * const *, const char *,
+ const char *, char **, char **, int));
+extern int pwait PROTO ((int, int *, int));
+/* Flag arguments to pexecute. */
+#define PEXECUTE_FIRST 1
+#define PEXECUTE_LAST 2
+#define PEXECUTE_SEARCH 4
+
/* Aliases for pointers to void.
These were made to facilitate compilation with old brain-dead DEC C
compilers which didn't properly grok `void*' types. */
@@ -166,21 +185,12 @@ typedef char * const_pointer_type;
/* Declaring stat or __flsbuf with a prototype
causes conflicts with system headers on some systems. */
-#ifndef abort
-typedef void voidfn ();
-extern VOLATILE voidfn abort;
-#endif
-#ifndef _WIN32
-extern int kill ();
-#endif
extern int creat ();
#if 0 /* These conflict with stdio.h on some systems. */
extern int fprintf (FILE *, const char *, ...);
extern int printf (const char *, ...);
extern int open (const char *, int, ...);
#endif /* 0 */
-extern void exit ();
-extern void free ();
extern int read ();
extern int write ();
extern int close ();
@@ -189,10 +199,11 @@ extern int atoi ();
extern int puts ();
extern int fputs ();
extern int fputc ();
+#if !defined(_WIN32)
extern int link ();
+#endif
extern int unlink ();
extern int access ();
-extern int execvp ();
#if 0 /* size_t from sys/types.h may fail to match GCC.
If so, we would get a warning from this. */
@@ -207,7 +218,9 @@ extern size_t strlen ()
#endif /* !defined (POSIX) */
+#ifdef NEED_DECLARATION_RINDEX
extern char *rindex ();
+#endif
/* Look for these where the `const' qualifier is intentionally cast aside. */
@@ -254,7 +267,7 @@ static char * syscalls_absolute_filename;
#endif /* !defined (UNPROTOIZE) */
-/* Type of the structure that holds information about macro unexpansions. */
+/* Type of the structure that holds information about macro unexpansions. */
struct unexpansion_struct {
const char *expanded;
@@ -295,39 +308,41 @@ static const int hash_mask = (HASH_TABLE_SIZE - 1);
#define LOCAL_INCLUDE_DIR "/usr/local/include"
#endif
-struct default_include { const char *fname; int x1, x2; } include_defaults[]
+struct default_include { const char *fname;
+ const char *component;
+ int x1, x2; } include_defaults[]
#ifdef INCLUDE_DEFAULTS
= INCLUDE_DEFAULTS;
#else
= {
/* Pick up GNU C++ specific include files. */
- { GPLUSPLUS_INCLUDE_DIR, 1, 1 },
+ { GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 },
#ifdef CROSS_COMPILE
/* This is the dir for fixincludes. Put it just before
the files that we fix. */
- { GCC_INCLUDE_DIR, 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, 0, 0, 0 },
/* This is another place that the target system's headers might be. */
- { TOOL_INCLUDE_DIR, 0, 0 },
+ { TOOL_INCLUDE_DIR, "BINUTILS", 0, 0 },
#else /* not CROSS_COMPILE */
/* This should be /use/local/include and should come before
the fixincludes-fixed header files. */
- { LOCAL_INCLUDE_DIR, 0, 1 },
+ { LOCAL_INCLUDE_DIR, 0, 0, 1 },
/* 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 },
/* 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},
+ { STANDARD_INCLUDE_DIR, 0, 0, 0},
#endif /* not CROSS_COMPILE */
- { 0, 0, 0}
+ { 0, 0, 0, 0}
};
#endif /* no INCLUDE_DEFAULTS */
@@ -501,7 +516,7 @@ static const char *indent_string = " "; /* Indentation for newly
static int local_flag = 0; /* Insert new local decls (when?). */
static int global_flag = 0; /* set by -g option */
static int cplusplus_flag = 0; /* Rename converted files to *.C. */
-static const char* nondefault_syscalls_dir = 0; /* Dir to look for
+static const char *nondefault_syscalls_dir = 0; /* Dir to look for
SYSCALLS.c.X in. */
#endif /* !defined (UNPROTOIZE) */
@@ -536,7 +551,7 @@ static const char *convert_filename;
/* Pointer to relative root string (taken from aux_info file) which indicates
where directory the user was in when he did the compilation step that
- produced the containing aux_info file. */
+ produced the containing aux_info file. */
static const char *invocation_filename;
@@ -659,7 +674,7 @@ xmalloc (byte_count)
if (rv == NULL)
{
fprintf (stderr, "\n%s: virtual memory exceeded\n", pname);
- exit (1);
+ exit (FATAL_EXIT_CODE);
return 0; /* avoid warnings */
}
else
@@ -679,7 +694,7 @@ xrealloc (old_space, byte_count)
if (rv == NULL)
{
fprintf (stderr, "\n%s: virtual memory exceeded\n", pname);
- exit (1);
+ exit (FATAL_EXIT_CODE);
return 0; /* avoid warnings */
}
else
@@ -732,7 +747,7 @@ void
fancy_abort ()
{
fprintf (stderr, "%s: internal abort\n", pname);
- exit (1);
+ exit (FATAL_EXIT_CODE);
}
/* Make a duplicate of the first N bytes of a given string in a newly
@@ -867,10 +882,10 @@ usage ()
fprintf (stderr, "%s: usage '%s [ -VqfnkN ] [ -i <istring> ] [ filename ... ]'\n",
pname, pname);
#else /* !defined (UNPROTOIZE) */
- fprintf (stderr, "%s: usage '%s [ -VqfnkNlgC ] [ -B <diname> ] [ filename ... ]'\n",
+ fprintf (stderr, "%s: usage '%s [ -VqfnkNlgC ] [ -B <dirname> ] [ filename ... ]'\n",
pname, pname);
#endif /* !defined (UNPROTOIZE) */
- exit (1);
+ exit (FATAL_EXIT_CODE);
}
/* Return true if the given filename (assumed to be an absolute filename)
@@ -1023,14 +1038,14 @@ needs_to_be_converted (file_p)
#ifndef UNPROTOIZE
- /* ... and if we a protoizing and this function is in old style ... */
+ /* ... and if we a protoizing and this function is in old style ... */
!ddp->prototyped
- /* ... and if this a definition or is a decl with an associated def ... */
+ /* ... and if this a definition or is a decl with an associated def ... */
&& (ddp->is_func_def || (!ddp->is_func_def && ddp->definition))
#else /* defined (UNPROTOIZE) */
- /* ... and if we are unprotoizing and this function is in new style ... */
+ /* ... and if we are unprotoizing and this function is in new style ... */
ddp->prototyped
#endif /* defined (UNPROTOIZE) */
@@ -1216,7 +1231,7 @@ unexpand_if_needed (aux_info_line)
{
static char *line_buf = 0;
static int line_buf_size = 0;
- const unexpansion* unexp_p;
+ const unexpansion *unexp_p;
int got_unexpanded = 0;
const char *s;
char *copy_p = line_buf;
@@ -1357,18 +1372,18 @@ abspath (cwd, rel_filename)
while (outp >= abs_buffer && *outp != '/')
outp--;
if (outp < abs_buffer)
- {
- /* Catch cases like /.. where we try to backup to a
- point above the absolute root of the logical file
- system. */
-
- fprintf (stderr, "%s: invalid file name: %s\n",
- pname, rel_filename);
- exit (1);
- }
+ {
+ /* Catch cases like /.. where we try to backup to a
+ point above the absolute root of the logical file
+ system. */
+
+ fprintf (stderr, "%s: invalid file name: %s\n",
+ pname, rel_filename);
+ exit (FATAL_EXIT_CODE);
+ }
*++outp = '\0';
continue;
- }
+ }
}
*outp++ = *inp++;
}
@@ -1534,7 +1549,7 @@ aux_info_corrupted ()
{
fprintf (stderr, "\n%s: fatal error: aux info file corrupted at line %d\n",
pname, current_aux_info_lineno);
- exit (1);
+ exit (FATAL_EXIT_CODE);
}
/* ??? This comment is vague. Say what the condition is for. */
@@ -1690,7 +1705,7 @@ save_def_or_dec (l, is_syscalls)
/* Check that this record describes a new-style, old-style, or implicit
definition or declaration. */
- p++; /* Skip over the `:'. */
+ p++; /* Skip over the `:'. */
check_aux_info ((*p == 'N') || (*p == 'O') || (*p == 'I'));
/* Is this a new style (ANSI prototyped) definition or declaration? */
@@ -1781,8 +1796,8 @@ save_def_or_dec (l, is_syscalls)
const char *left_paren_p = find_corresponding_lparen (p);
#ifndef UNPROTOIZE
{
- f_list_chain_item *cip =
- (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
+ f_list_chain_item *cip
+ = (f_list_chain_item *) xmalloc (sizeof (f_list_chain_item));
cip->formals_list
= dupnstr (left_paren_p + 1, (size_t) (p - (left_paren_p+1)));
@@ -1860,7 +1875,7 @@ save_def_or_dec (l, is_syscalls)
def_dec_p->file->hash_entry->symbol,
def_dec_p->line,
def_dec_p->hash_entry->symbol);
- exit (1);
+ exit (FATAL_EXIT_CODE);
}
free_def_dec (def_dec_p);
return;
@@ -1896,7 +1911,7 @@ save_def_or_dec (l, is_syscalls)
check_aux_info (*++p == '(');
{
- const char *kr_names_start = ++p; /* Point just inside '('. */
+ const char *kr_names_start = ++p; /* Point just inside '('. */
while (*p++ != ')')
continue;
@@ -2085,14 +2100,14 @@ munge_compile_params (params_list)
}
/* Do a recompilation for the express purpose of generating a new aux_info
- file to go with a specific base source file. */
+ file to go with a specific base source file.
+
+ The result is a boolean indicating success. */
static int
gen_aux_info_file (base_filename)
const char *base_filename;
{
- int child_pid;
-
if (!input_file_name_index)
munge_compile_params ("");
@@ -2109,79 +2124,48 @@ gen_aux_info_file (base_filename)
fprintf (stderr, "%s: compiling `%s'\n",
pname, compile_params[input_file_name_index]);
- if (child_pid = fork ())
- {
- if (child_pid == -1)
- {
- fprintf (stderr, "%s: could not fork process: %s\n",
- pname, my_strerror(errno));
- return 0;
- }
-
-#if 0
- /* Print out the command line that the other process is now executing. */
+ {
+ char *errmsg_fmt, *errmsg_arg;
+ int wait_status, pid;
+ char *temp_base = choose_temp_base ();
- if (!quiet_flag)
- {
- const char **arg;
-
- fputs ("\t", stderr);
- for (arg = compile_params; *arg; arg++)
- {
- fputs (*arg, stderr);
- fputc (' ', stderr);
- }
- fputc ('\n', stderr);
- fflush (stderr);
- }
-#endif /* 0 */
+ pid = pexecute (compile_params[0], (char * const *) compile_params,
+ pname, temp_base, &errmsg_fmt, &errmsg_arg,
+ PEXECUTE_FIRST | PEXECUTE_LAST | PEXECUTE_SEARCH);
+ if (pid == -1)
{
- int wait_status;
+ int errno_val = errno;
+ fprintf (stderr, "%s: ", pname);
+ fprintf (stderr, errmsg_fmt, errmsg_arg);
+ fprintf (stderr, ": %s\n", my_strerror (errno_val));
+ return 0;
+ }
- if (wait (&wait_status) == -1)
- {
- fprintf (stderr, "%s: wait failed: %s\n",
- pname, my_strerror(errno));
- return 0;
- }
- if (WIFSIGNALED (wait_status))
- {
- fprintf (stderr, "%s: subprocess got fatal signal %d",
- pname, WTERMSIG (wait_status));
- return 0;
- }
- if (WIFEXITED (wait_status) && WEXITSTATUS (wait_status) != 0)
+ pid = pwait (pid, &wait_status, 0);
+ if (pid == -1)
+ {
+ fprintf (stderr, "%s: wait: %s\n", pname, my_strerror (errno));
+ return 0;
+ }
+ if (WIFSIGNALED (wait_status))
+ {
+ fprintf (stderr, "%s: subprocess got fatal signal %d\n",
+ pname, WTERMSIG (wait_status));
+ return 0;
+ }
+ if (WIFEXITED (wait_status))
+ {
+ if (WEXITSTATUS (wait_status) != 0)
{
fprintf (stderr, "%s: %s exited with status %d\n",
- pname, base_filename, WEXITSTATUS (wait_status));
+ pname, compile_params[0], WEXITSTATUS (wait_status));
return 0;
}
return 1;
}
- }
- else
- {
- if (my_execvp (compile_params[0], (char *const *) compile_params))
- {
- int e = errno, f = fileno (stderr);
- write (f, pname, strlen (pname));
- write (f, ": ", 2);
- write (f, compile_params[0], strlen (compile_params[0]));
- write (f, ": ", 2);
-#ifdef HAVE_STRERROR
- {
- char *p = strerror(e);
- write (f, p, strlen (p));
- }
-#else
- write (f, sys_errlist[e], strlen (sys_errlist[e]));
-#endif
- write (f, "\n", 1);
- _exit (1);
- }
- return 1; /* Never executed. */
- }
+ abort ();
+ }
}
/* Read in all of the information contained in a single aux_info file.
@@ -2618,7 +2602,7 @@ find_extern_def (head, user)
if (dd_p->is_func_def && !dd_p->is_static)
{
if (!extern_def_p) /* Previous definition? */
- extern_def_p = dd_p; /* Remember the first definition found. */
+ extern_def_p = dd_p; /* Remember the first definition found. */
else
{
/* Ignore definition just found if it came from SYSCALLS.c.X. */
@@ -2738,7 +2722,7 @@ find_extern_def (head, user)
/* Find the (only?) static definition for a particular function name in a
given file. Here we get the function-name and the file info indirectly
- from the def_dec_info record pointer which is passed in. */
+ from the def_dec_info record pointer which is passed in. */
static const def_dec_info *
find_static_definition (user)
@@ -3434,11 +3418,11 @@ edit_formals_lists (end_formals, f_list_count, def_dec_p)
return 0;
}
-/* Given a pointer to a byte in the clean text buffer which points to the
- beginning of a line that contains a "follower" token for a function
- definition header, do whatever is necessary to find the right closing
- paren for the rightmost formals list of the function definition header.
-*/
+/* Given a pointer to a byte in the clean text buffer which points to
+ the beginning of a line that contains a "follower" token for a
+ function definition header, do whatever is necessary to find the
+ right closing paren for the rightmost formals list of the function
+ definition header. */
static const char *
find_rightmost_formals_list (clean_text_p)
@@ -3706,7 +3690,7 @@ add_global_decls (file_p, clean_text_p)
/* Now scan forward for the first non-whitespace character. In theory,
this should be the first character of the following function definition
- header. We will put in the added declarations just prior to that. */
+ header. We will put in the added declarations just prior to that. */
scan_p++;
while (isspace (*scan_p))
@@ -4386,8 +4370,8 @@ edit_file (hp)
if (!nosave_flag)
{
- char *new_filename =
- (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
+ char *new_filename
+ = (char *) xmalloc (strlen (convert_filename) + strlen (save_suffix) + 2);
strcpy (new_filename, convert_filename);
strcat (new_filename, save_suffix);
@@ -4599,7 +4583,7 @@ main (argc, argv)
{
fprintf (stderr, "%s: cannot get working directory: %s\n",
pname, my_strerror(errno));
- exit (1);
+ exit (FATAL_EXIT_CODE);
}
/* By default, convert the files in the current directory. */
@@ -4613,7 +4597,7 @@ main (argc, argv)
#endif
longopts, &longind)) != EOF)
{
- if (c == 0) /* Long option. */
+ if (c == 0) /* Long option. */
c = longopts[longind].val;
switch (c)
{
@@ -4683,8 +4667,8 @@ main (argc, argv)
/* Now actually make a list of the base source filenames. */
- base_source_filenames =
- (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
+ base_source_filenames
+ = (const char **) xmalloc ((n_base_source_files + 1) * sizeof (char *));
n_base_source_files = 0;
for (; optind < argc; optind++)
{
@@ -4724,9 +4708,8 @@ main (argc, argv)
fprintf (stderr, "%s: %s\n", pname, version_string);
do_processing ();
}
- if (errors)
- exit (1);
- else
- exit (0);
+
+ exit (errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
+
return 1;
}
diff --git a/gnu/usr.bin/gcc/recog.c b/gnu/usr.bin/gcc/recog.c
index 745d62881d2..1af2dfcd03a 100644
--- a/gnu/usr.bin/gcc/recog.c
+++ b/gnu/usr.bin/gcc/recog.c
@@ -1,5 +1,5 @@
/* Subroutines used by or related to instruction recognition.
- Copyright (C) 1987, 88, 91, 92, 93, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 91-6, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,8 +20,8 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
-#include "rtl.h"
#include <stdio.h>
+#include "rtl.h"
#include "insn-config.h"
#include "insn-attr.h"
#include "insn-flags.h"
@@ -43,8 +43,7 @@ Boston, MA 02111-1307, USA. */
/* Import from final.c: */
extern rtx alter_subreg ();
-int strict_memory_address_p ();
-int memory_address_p ();
+static rtx *find_single_use_1 PROTO((rtx, rtx *));
/* Nonzero means allow operands to be volatile.
This should be 0 if you are generating rtl, such as if you are calling
@@ -374,15 +373,28 @@ validate_replace_rtx_1 (loc, from, to, object)
}
}
+ /* Note that if CODE's RTX_CLASS is "c" or "<" we will have already
+ done the substitution, otherwise we won't. */
+
switch (code)
{
case PLUS:
/* If we have have a PLUS whose second operand is now a CONST_INT, use
plus_constant to try to simplify it. */
if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to)
- validate_change (object, loc,
- plus_constant (XEXP (x, 0), INTVAL (XEXP (x, 1))), 1);
+ validate_change (object, loc, plus_constant (XEXP (x, 0), INTVAL (to)),
+ 1);
return;
+
+ case MINUS:
+ if (GET_CODE (to) == CONST_INT && XEXP (x, 1) == from)
+ {
+ validate_change (object, loc,
+ plus_constant (XEXP (x, 0), - INTVAL (to)),
+ 1);
+ return;
+ }
+ break;
case ZERO_EXTEND:
case SIGN_EXTEND:
@@ -492,6 +504,9 @@ validate_replace_rtx_1 (loc, from, to, object)
}
break;
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -614,6 +629,9 @@ find_single_use_1 (dest, loc)
case MEM:
case SUBREG:
return find_single_use_1 (dest, &XEXP (x, 0));
+
+ default:
+ break;
}
/* If it wasn't one of the common cases above, check each expression and
@@ -806,10 +824,18 @@ general_operand (op, mode)
register rtx y = XEXP (op, 0);
if (! volatile_ok && MEM_VOLATILE_P (op))
return 0;
+ if (GET_CODE (y) == ADDRESSOF)
+ return 1;
/* Use the mem's mode, since it will be reloaded thus. */
mode = GET_MODE (op);
GO_IF_LEGITIMATE_ADDRESS (mode, y, win);
}
+
+ /* Pretend this is an operand for now; we'll run force_operand
+ on its replacement in fixup_var_refs_1. */
+ if (code == ADDRESSOF)
+ return 1;
+
return 0;
win:
@@ -871,7 +897,9 @@ register_operand (op, mode)
&& TEST_HARD_REG_BIT (reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
REGNO (SUBREG_REG (op)))
&& (GET_MODE_SIZE (mode)
- != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
+ != GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
+ && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_INT
+ && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op))) != MODE_COMPLEX_FLOAT)
return 0;
#endif
@@ -1043,6 +1071,9 @@ memory_address_p (mode, addr)
enum machine_mode mode;
register rtx addr;
{
+ if (GET_CODE (addr) == ADDRESSOF)
+ return 1;
+
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
@@ -1650,6 +1681,11 @@ constrain_operands (insn_code_num, strict)
earlyclobber[opno] = 0;
+ /* A unary operator may be accepted by the predicate, but it
+ is irrelevant for matching constraints. */
+ if (GET_RTX_CLASS (GET_CODE (op)) == '1')
+ op = XEXP (op, 0);
+
if (GET_CODE (op) == SUBREG)
{
if (GET_CODE (SUBREG_REG (op)) == REG
@@ -1765,8 +1801,9 @@ constrain_operands (insn_code_num, strict)
break;
case 'X':
- /* This is used for a MATCH_SCRATCH in the cases when we
- don't actually need anything. So anything goes any time. */
+ /* This is used for a MATCH_SCRATCH in the cases when
+ we don't actually need anything. So anything goes
+ any time. */
win = 1;
break;
@@ -1862,7 +1899,12 @@ constrain_operands (insn_code_num, strict)
case 'V':
if (GET_CODE (op) == MEM
- && ! offsettable_memref_p (op))
+ && ((strict > 0 && ! offsettable_memref_p (op))
+ || (strict < 0
+ && !(CONSTANT_P (op) || GET_CODE (op) == MEM))
+ || (reload_in_progress
+ && !(GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER))))
win = 1;
break;
@@ -1916,11 +1958,11 @@ constrain_operands (insn_code_num, strict)
if ((GET_CODE (recog_operand[opno]) == MEM
|| op_types[opno] != OP_OUT)
&& opno != eopno
- /* Ignore things like match_operator operands. */
- && *constraints[opno] != 0
+ /* Ignore things like match_operator operands. */
+ && *insn_operand_constraint[insn_code_num][opno] != 0
&& ! (matching_operands[opno] == eopno
- && rtx_equal_p (recog_operand[opno],
- recog_operand[eopno]))
+ && operands_match_p (recog_operand[opno],
+ recog_operand[eopno]))
&& ! safe_from_earlyclobber (recog_operand[opno],
recog_operand[eopno]))
lose = 1;
@@ -1949,7 +1991,7 @@ constrain_operands (insn_code_num, strict)
}
/* Return 1 iff OPERAND (assumed to be a REG rtx)
- is a hard reg in class CLASS when its regno is offsetted by OFFSET
+ is a hard reg in class CLASS when its regno is offset by OFFSET
and changed to mode MODE.
If REG occupies multiple hard regs, all of them must be in CLASS. */
diff --git a/gnu/usr.bin/gcc/recog.h b/gnu/usr.bin/gcc/recog.h
index fc0d5ffdd0a..8918c8950b1 100644
--- a/gnu/usr.bin/gcc/recog.h
+++ b/gnu/usr.bin/gcc/recog.h
@@ -1,5 +1,5 @@
/* Declarations for interface to insn recognizer and insn-output.c.
- Copyright (C) 1987 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1996, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -18,46 +18,51 @@ 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. */
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
-/* Recognize an insn and return its insn-code,
- which is the sequence number of the DEFINE_INSN that it matches.
- If the insn does not match, return -1. */
-
-extern int recog_memoized PROTO((rtx));
-
-/* Determine whether a proposed change to an insn or MEM will make it
- invalid. Make the change if not. */
-
-extern int validate_change PROTO((rtx, rtx *, rtx, int));
-
-/* Apply a group of changes if valid. */
-
-extern int apply_change_group PROTO((void));
-
-/* Return the number of changes so far in the current group. */
-
-extern int num_validated_changes PROTO((void));
-
-/* Retract some changes. */
-
-extern void cancel_changes PROTO((int));
+#include "gansidecl.h"
+
+extern void init_recog PROTO((void));
+extern void init_recog_no_volatile PROTO((void));
+extern int recog_memoized PROTO((rtx));
+extern int check_asm_operands PROTO((rtx));
+extern int validate_change PROTO((rtx, rtx *, rtx, int));
+extern int apply_change_group PROTO((void));
+extern int num_validated_changes PROTO((void));
+extern void cancel_changes PROTO((int));
+extern int constrain_operands PROTO((int, int));
+extern int memory_address_p PROTO((enum machine_mode, rtx));
+extern int strict_memory_address_p PROTO((enum machine_mode, rtx));
+extern int validate_replace_rtx PROTO((rtx, rtx, rtx));
+extern int reg_fits_class_p PROTO((rtx, enum reg_class, int,
+ enum machine_mode));
+extern rtx *find_single_use PROTO((rtx, rtx, rtx *));
+
+extern int general_operand PROTO((rtx, enum machine_mode));
+extern int address_operand PROTO((rtx, enum machine_mode));
+extern int register_operand PROTO((rtx, enum machine_mode));
+extern int scratch_operand PROTO((rtx, enum machine_mode));
+extern int immediate_operand PROTO((rtx, enum machine_mode));
+extern int const_int_operand PROTO((rtx, enum machine_mode));
+extern int cosnt_double_operand PROTO((rtx, enum machine_mode));
+extern int nonimmediate_operand PROTO((rtx, enum machine_mode));
+extern int nonmemory_operand PROTO((rtx, enum machine_mode));
+extern int push_operand PROTO((rtx, enum machine_mode));
+extern int memory_operand PROTO((rtx, enum machine_mode));
+extern int indirect_operand PROTO((rtx, enum machine_mode));
+extern int mode_independent_operand PROTO((rtx, enum machine_mode));
+extern int comparison_operator PROTO((rtx, enum machine_mode));
+
+extern int offsettable_memref_p PROTO((rtx));
+extern int offsettable_nonstrict_memref_p PROTO((rtx));
+extern int offsettable_address_p PROTO((int, enum machine_mode, rtx));
+extern int mode_dependent_address_p PROTO((rtx));
+
+extern int recog PROTO((rtx, rtx, int *));
+extern void add_clobbers PROTO((rtx, int));
+extern void insn_extract PROTO((rtx));
/* Nonzero means volatile operands are recognized. */
-
extern int volatile_ok;
-/* Extract the operands from an insn that has been recognized. */
-
-extern void insn_extract PROTO((rtx));
-
/* The following vectors hold the results from insn_extract. */
/* Indexed by N, gives value of operand N. */
@@ -74,12 +79,6 @@ extern rtx *recog_dup_loc[];
Nth duplicate-appearance of an operand. */
extern char recog_dup_num[];
-#ifndef __STDC__
-#ifndef const
-#define const
-#endif
-#endif
-
/* Access the output function for CODE. */
#define OUT_FCN(CODE) (*insn_outfun[(int) (CODE)])
diff --git a/gnu/usr.bin/gcc/reg-stack.c b/gnu/usr.bin/gcc/reg-stack.c
index c099c61a016..aea3cdb93fd 100644
--- a/gnu/usr.bin/gcc/reg-stack.c
+++ b/gnu/usr.bin/gcc/reg-stack.c
@@ -1,5 +1,5 @@
/* Register to Stack convert for GNU compiler.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -157,14 +157,15 @@ Boston, MA 02111-1307, USA. */
*/
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "rtl.h"
#include "insn-config.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "flags.h"
+#include "insn-flags.h"
#ifdef STACK_REGS
@@ -213,7 +214,7 @@ static HARD_REG_SET *block_out_reg_set;
up by find_blocks and used there and in life_analysis. It can be used
later, but only to look up an insn that is the head or tail of some
block. life_analysis and the stack register conversion process can
- add insns within a block. */
+ add insns within a block. */
static int *block_number;
/* This is the register file for all register after conversion */
@@ -224,28 +225,52 @@ static rtx
(FP_mode_reg[(regno)-FIRST_STACK_REG][(int)(mode)])
/* Get the basic block number of an insn. See note at block_number
- definition are validity of this information. */
+ definition are validity of this information. */
#define BLOCK_NUM(INSN) \
((INSN_UID (INSN) > max_uid) \
? (abort() , -1) : block_number[INSN_UID (INSN)])
extern rtx forced_labels;
-extern rtx gen_jump ();
-extern rtx gen_movdf (), gen_movxf ();
-extern rtx find_regno_note ();
-extern rtx emit_jump_insn_before ();
-extern rtx emit_label_after ();
/* Forward declarations */
-static void find_blocks ();
-static uses_reg_or_mem ();
-static void stack_reg_life_analysis ();
-static void record_reg_life_pat ();
-static void change_stack ();
-static void convert_regs ();
-static void dump_stack_info ();
+static void mark_regs_pat PROTO((rtx, HARD_REG_SET *));
+static void straighten_stack PROTO((rtx, stack));
+static void record_label_references PROTO((rtx, rtx));
+static rtx *get_true_reg PROTO((rtx *));
+static int constrain_asm_operands PROTO((int, rtx *, char **, int *,
+ enum reg_class *));
+
+static void record_asm_reg_life PROTO((rtx,stack, rtx *, char **,
+ int, int));
+static void record_reg_life_pat PROTO((rtx, HARD_REG_SET *,
+ HARD_REG_SET *, int));
+static void get_asm_operand_length PROTO((rtx, int, int *, int *));
+static void record_reg_life PROTO((rtx, int, stack));
+static void find_blocks PROTO((rtx));
+static int uses_reg_or_mem PROTO((rtx));
+static rtx stack_result PROTO((tree));
+static void stack_reg_life_analysis PROTO((rtx, HARD_REG_SET *));
+static void replace_reg PROTO((rtx *, int));
+static void remove_regno_note PROTO((rtx, enum reg_note, int));
+static int get_hard_regnum PROTO((stack, rtx));
+static void delete_insn_for_stacker PROTO((rtx));
+static rtx emit_pop_insn PROTO((rtx, stack, rtx, rtx (*) ()));
+static void emit_swap_insn PROTO((rtx, stack, rtx));
+static void move_for_stack_reg PROTO((rtx, stack, rtx));
+static void swap_rtx_condition PROTO((rtx));
+static void compare_for_stack_reg PROTO((rtx, stack, rtx));
+static void subst_stack_regs_pat PROTO((rtx, stack, rtx));
+static void subst_asm_stack_regs PROTO((rtx, stack, rtx *, rtx **,
+ char **, int, int));
+static void subst_stack_regs PROTO((rtx, stack));
+static void change_stack PROTO((rtx, stack, stack, rtx (*) ()));
+
+static void goto_block_pat PROTO((rtx, stack, rtx));
+static void convert_regs PROTO((void));
+static void print_blocks PROTO((FILE *, rtx, rtx));
+static void dump_stack_info PROTO((FILE *));
/* Mark all registers needed for this pattern. */
@@ -396,7 +421,7 @@ reg_to_stack (first, file)
before_function_beg = 0;
/* Remember whether or not this insn mentions an FP regs.
- Check JUMP_INSNs too, in case someone creates a funny PARALLEL. */
+ Check JUMP_INSNs too, in case someone creates a funny PARALLEL. */
if (GET_RTX_CLASS (code) == 'i'
&& stack_regs_mentioned_p (PATTERN (insn)))
@@ -408,7 +433,7 @@ reg_to_stack (first, file)
if (before_function_beg && code == INSN
&& GET_CODE (PATTERN (insn)) == USE)
- record_reg_life_pat (PATTERN (insn), (HARD_REG_SET*) 0,
+ record_reg_life_pat (PATTERN (insn), (HARD_REG_SET *) 0,
&stackentry, 1);
}
else
@@ -428,13 +453,13 @@ reg_to_stack (first, file)
if (! stack_reg_seen)
return;
- /* If there are stack registers, there must be at least one block. */
+ /* If there are stack registers, there must be at least one block. */
if (! blocks)
abort ();
/* Allocate some tables that last till end of compiling this function
- and some needed only in find_blocks and life_analysis. */
+ and some needed only in find_blocks and life_analysis. */
block_begin = (rtx *) alloca (blocks * sizeof (rtx));
block_end = (rtx *) alloca (blocks * sizeof (rtx));
@@ -452,7 +477,7 @@ reg_to_stack (first, file)
/* Dump the life analysis debug information before jump
optimization, as that will destroy the LABEL_REFS we keep the
- information in. */
+ information in. */
if (file)
dump_stack_info (file);
@@ -465,7 +490,7 @@ reg_to_stack (first, file)
/* Check PAT, which is in INSN, for LABEL_REFs. Add INSN to the
label's chain of references, and note which insn contains each
- reference. */
+ reference. */
static void
record_label_references (insn, pat)
@@ -483,7 +508,12 @@ record_label_references (insn, pat)
if (GET_CODE (label) != CODE_LABEL)
abort ();
- /* Don't make a duplicate in the code_label's chain. */
+ /* If this is an undefined label, LABEL_REFS (label) contains
+ garbage. */
+ if (INSN_UID (label) == 0)
+ return;
+
+ /* Don't make a duplicate in the code_label's chain. */
for (ref = LABEL_REFS (label);
ref && ref != label;
@@ -514,7 +544,7 @@ record_label_references (insn, pat)
/* Return a pointer to the REG expression within PAT. If PAT is not a
REG, possible enclosed by a conversion rtx, return the inner part of
- PAT that stopped the search. */
+ PAT that stopped the search. */
static rtx *
get_true_reg (pat)
@@ -525,7 +555,7 @@ get_true_reg (pat)
{
case SUBREG:
/* eliminate FP subregister accesses in favour of the
- actual FP register in use. */
+ actual FP register in use. */
{
rtx subreg;
if (FP_REG_P (subreg = SUBREG_REG (*pat)))
@@ -558,7 +588,7 @@ get_true_reg (pat)
OPERAND_CLASS is set to `class' as required by the constraints, not to
the subclass. If an alternative allows more than one class,
OPERAND_CLASS is set to the smallest class that is a union of the
- allowed classes. */
+ allowed classes. */
static int
constrain_asm_operands (n_operands, operands, operand_constraints,
@@ -631,11 +661,11 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
case '!':
case '*':
case '%':
- /* Ignore these. */
+ /* Ignore these. */
break;
case '#':
- /* Ignore rest of this alternative. */
+ /* Ignore rest of this alternative. */
while (*p && *p != ',') p++;
break;
@@ -649,7 +679,7 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
This kind of constraint is used for instructions such
as add when they take only two operands.
- Note that the lower-numbered operand is passed first. */
+ Note that the lower-numbered operand is passed first. */
if (operands_match_p (operands[c - '0'],
operands[this_operand]))
@@ -661,7 +691,7 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
case 'p':
/* p is used for address_operands. Since this is an asm,
- just to make sure that the operand is valid for Pmode. */
+ just to make sure that the operand is valid for Pmode. */
if (strict_memory_address_p (Pmode, op))
win = 1;
@@ -694,7 +724,7 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
case 'X':
/* This is used for a MATCH_SCRATCH in the cases when we
- don't actually need anything. So anything goes any time. */
+ don't actually need anything. So anything goes any time. */
win = 1;
break;
@@ -818,7 +848,7 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
}
/* For operands constrained to match another operand, copy the other
- operand's class to this operand's class. */
+ operand's class to this operand's class. */
for (j = 0; j < n_operands; j++)
if (operand_matches[j] >= 0)
operand_class[j] = operand_class[operand_matches[j]];
@@ -834,7 +864,7 @@ constrain_asm_operands (n_operands, operands, operand_constraints,
There are many rules that an asm statement for stack-like regs must
follow. Those rules are explained at the top of this file: the rule
- numbers below refer to that explanation. */
+ numbers below refer to that explanation. */
static void
record_asm_reg_life (insn, regstack, operands, constraints,
@@ -869,7 +899,7 @@ record_asm_reg_life (insn, regstack, operands, constraints,
if (i < 0)
malformed_asm = 1;
- /* Strip SUBREGs here to make the following code simpler. */
+ /* Strip SUBREGs here to make the following code simpler. */
for (i = 0; i < n_operands; i++)
if (GET_CODE (operands[i]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[i])) == REG)
@@ -905,7 +935,7 @@ record_asm_reg_life (insn, regstack, operands, constraints,
operand constraints must select a class with a single reg.
Also enforce rule #5: Output operands must start at the top of
- the reg-stack: output operands may not "skip" a reg. */
+ the reg-stack: output operands may not "skip" a reg. */
bzero ((char *) reg_used_as_output, sizeof (reg_used_as_output));
for (i = 0; i < n_outputs; i++)
@@ -938,14 +968,14 @@ record_asm_reg_life (insn, regstack, operands, constraints,
/* Enforce rule #2: All implicitly popped input regs must be closer
to the top of the reg-stack than any input that is not implicitly
- popped. */
+ popped. */
bzero ((char *) implicitly_dies, sizeof (implicitly_dies));
for (i = first_input; i < first_input + n_inputs; i++)
if (STACK_REG_P (operands[i]))
{
/* An input reg is implicitly popped if it is tied to an
- output, or if there is a CLOBBER for it. */
+ output, or if there is a CLOBBER for it. */
int j;
for (j = 0; j < n_clobbers; j++)
@@ -977,7 +1007,7 @@ record_asm_reg_life (insn, regstack, operands, constraints,
output constraints must use the "&" earlyclobber.
??? Detect this more deterministically by having constraint_asm_operands
- record any earlyclobber. */
+ record any earlyclobber. */
for (i = first_input; i < first_input + n_inputs; i++)
if (operand_matches[i] == -1)
@@ -1050,7 +1080,7 @@ record_asm_reg_life (insn, regstack, operands, constraints,
a SET_DEST in DEST, and other registers in SRC.
This function does not know about SET_DESTs that are both input and
- output (such as ZERO_EXTRACT) - this cannot happen on a 387. */
+ output (such as ZERO_EXTRACT) - this cannot happen on a 387. */
static void
record_reg_life_pat (pat, src, dest, douse)
@@ -1062,7 +1092,7 @@ record_reg_life_pat (pat, src, dest, douse)
register int i;
if (STACK_REG_P (pat)
- || GET_CODE (pat) == SUBREG && STACK_REG_P (SUBREG_REG (pat)))
+ || (GET_CODE (pat) == SUBREG && STACK_REG_P (SUBREG_REG (pat))))
{
if (src)
mark_regs_pat (pat, src);
@@ -1080,7 +1110,7 @@ record_reg_life_pat (pat, src, dest, douse)
return;
}
- /* We don't need to consider either of these cases. */
+ /* We don't need to consider either of these cases. */
if (GET_CODE (pat) == USE && !douse || GET_CODE (pat) == CLOBBER)
return;
@@ -1102,7 +1132,7 @@ record_reg_life_pat (pat, src, dest, douse)
/* Calculate the number of inputs and outputs in BODY, an
asm_operands. N_OPERANDS is the total number of operands, and
N_INPUTS and N_OUTPUTS are pointers to ints into which the results are
- placed. */
+ placed. */
static void
get_asm_operand_lengths (body, n_operands, n_inputs, n_outputs)
@@ -1139,7 +1169,7 @@ get_asm_operand_lengths (body, n_operands, n_inputs, n_outputs)
register. The block_end[] data is kept accurate.
Existing death and unset notes for stack registers are deleted
- before processing the insn. */
+ before processing the insn. */
static void
record_reg_life (insn, block, regstack)
@@ -1165,13 +1195,13 @@ record_reg_life (insn, block, regstack)
else
note_link = &XEXP (note, 1);
- /* Process all patterns in the insn. */
+ /* Process all patterns in the insn. */
n_operands = asm_noperands (PATTERN (insn));
if (n_operands >= 0)
{
/* This insn is an `asm' with operands. Decode the operands,
- decide how many are inputs, and record the life information. */
+ decide how many are inputs, and record the life information. */
rtx operands[MAX_RECOG_OPERANDS];
rtx body = PATTERN (insn);
@@ -1220,7 +1250,7 @@ record_reg_life (insn, block, regstack)
/* There might be a reg that is live after a function call.
Initialize it to zero so that the program does not crash. See
- comment towards the end of stack_reg_life_analysis(). */
+ comment towards the end of stack_reg_life_analysis(). */
for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
if (! TEST_HARD_REG_BIT (dest, reg)
@@ -1231,7 +1261,7 @@ record_reg_life (insn, block, regstack)
/* The insn will use virtual register numbers, and so
convert_regs is expected to process these. But BLOCK_NUM
cannot be used on these insns, because they do not appear in
- block_number[]. */
+ block_number[]. */
pat = gen_rtx (SET, VOIDmode, FP_MODE_REG (reg, DFmode),
CONST0_RTX (DFmode));
@@ -1241,7 +1271,7 @@ record_reg_life (insn, block, regstack)
CLEAR_HARD_REG_BIT (regstack->reg_set, reg);
/* If the CALL_INSN was the end of a block, move the
- block_end to point to the new insn. */
+ block_end to point to the new insn. */
if (block_end[block] == insn)
block_end[block] = init;
@@ -1257,7 +1287,7 @@ record_reg_life (insn, block, regstack)
}
/* Find all basic blocks of the function, which starts with FIRST.
- For each JUMP_INSN, build the chain of LABEL_REFS on each CODE_LABEL. */
+ For each JUMP_INSN, build the chain of LABEL_REFS on each CODE_LABEL. */
static void
find_blocks (first)
@@ -1270,7 +1300,7 @@ find_blocks (first)
rtx label_value_list = 0;
/* Record where all the blocks start and end.
- Record which basic blocks control can drop in to. */
+ Record which basic blocks control can drop in to. */
block = -1;
for (insn = first; insn; insn = NEXT_INSN (insn))
@@ -1322,33 +1352,9 @@ find_blocks (first)
if (GET_CODE (insn) == JUMP_INSN)
{
rtx pat = PATTERN (insn);
- int computed_jump = 0;
rtx x;
- if (GET_CODE (pat) == PARALLEL)
- {
- int len = XVECLEN (pat, 0);
- int has_use_labelref = 0;
- int i;
-
- for (i = len - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (pat, 0, i)) == USE
- && GET_CODE (XEXP (XVECEXP (pat, 0, i), 0)) == LABEL_REF)
- has_use_labelref = 1;
-
- if (! has_use_labelref)
- for (i = len - 1; i >= 0; i--)
- if (GET_CODE (XVECEXP (pat, 0, i)) == SET
- && SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
- && uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
- computed_jump = 1;
- }
- else if (GET_CODE (pat) == SET
- && SET_DEST (pat) == pc_rtx
- && uses_reg_or_mem (SET_SRC (pat)))
- computed_jump = 1;
-
- if (computed_jump)
+ if (computed_jump_p (insn))
{
for (x = label_value_list; x; x = XEXP (x, 1))
record_label_references (insn,
@@ -1450,7 +1456,7 @@ stack_result (decl)
If there are registers that are live at the start of the function,
insns are emitted to initialize these registers. Something similar is
- done after CALL_INSNs in record_reg_life. */
+ done after CALL_INSNs in record_reg_life. */
static void
stack_reg_life_analysis (first, stackentry)
@@ -1465,7 +1471,7 @@ stack_reg_life_analysis (first, stackentry)
if (retvalue = stack_result (current_function_decl))
{
- /* Find all RETURN insns and mark them. */
+ /* Find all RETURN insns and mark them. */
for (block = blocks - 1; --block >= 0;)
if (GET_CODE (block_end[block]) == JUMP_INSN
@@ -1473,7 +1479,7 @@ stack_reg_life_analysis (first, stackentry)
mark_regs_pat (retvalue, block_out_reg_set+block);
/* Mark off the end of last block if we "fall off" the end of the
- function into the epilogue. */
+ function into the epilogue. */
if (GET_CODE (block_end[blocks-1]) != JUMP_INSN
|| GET_CODE (PATTERN (block_end[blocks-1])) == RETURN)
@@ -1500,7 +1506,7 @@ stack_reg_life_analysis (first, stackentry)
/* If the insn is a CALL_INSN, we need to ensure that
everything dies. But otherwise don't process unless there
- are some stack regs present. */
+ are some stack regs present. */
if (GET_MODE (insn) == QImode || GET_CODE (insn) == CALL_INSN)
record_reg_life (insn, block, &regstack);
@@ -1508,13 +1514,13 @@ stack_reg_life_analysis (first, stackentry)
} while (insn != block_begin[block]);
/* Set the state at the start of the block. Mark that no
- register mapping information known yet. */
+ register mapping information known yet. */
COPY_HARD_REG_SET (block_stack_in[block].reg_set, regstack.reg_set);
block_stack_in[block].top = -2;
/* If there is a label, propagate our register life to all jumps
- to this label. */
+ to this label. */
if (GET_CODE (insn) == CODE_LABEL)
{
@@ -1535,7 +1541,7 @@ stack_reg_life_analysis (first, stackentry)
processed. If there are registers that were not known
to be live then, but are live now, we must back up
and restart life analysis from that point with the new
- life information. */
+ life information. */
GO_IF_HARD_REG_SUBSET (block_stack_in[block].reg_set,
block_out_reg_set[jump_block],
@@ -1565,7 +1571,7 @@ stack_reg_life_analysis (first, stackentry)
/* If any reg is live at the start of the first block of a
function, then we must guarantee that the reg holds some value by
generating our own "load" of that register. Otherwise a 387 would
- fault trying to access an empty register. */
+ fault trying to access an empty register. */
/* Load zero into each live register. The fact that a register
appears live at the function start necessarily implies an error
@@ -1576,7 +1582,7 @@ stack_reg_life_analysis (first, stackentry)
Note that we are inserting virtual register references here:
these insns must be processed by convert_regs later. Also, these
- insns will not be in block_number, so BLOCK_NUM() will fail for them. */
+ insns will not be in block_number, so BLOCK_NUM() will fail for them. */
for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; reg--)
if (TEST_HARD_REG_BIT (block_stack_in[0].reg_set, reg)
@@ -1599,7 +1605,7 @@ stack_reg_life_analysis (first, stackentry)
*****************************************************************************/
/* Replace REG, which is a pointer to a stack reg RTX, with an RTX for
- the desired hard REGNO. */
+ the desired hard REGNO. */
static void
replace_reg (reg, regno)
@@ -1621,7 +1627,7 @@ replace_reg (reg, regno)
}
/* Remove a note of type NOTE, which must be found, for register
- number REGNO from INSN. Remove only one such note. */
+ number REGNO from INSN. Remove only one such note. */
static void
remove_regno_note (insn, note, regno)
@@ -1647,7 +1653,7 @@ remove_regno_note (insn, note, regno)
/* Find the hard register number of virtual register REG in REGSTACK.
The hard register number is relative to the top of the stack. -1 is
- returned if the register is not found. */
+ returned if the register is not found. */
static int
get_hard_regnum (regstack, reg)
@@ -1668,7 +1674,7 @@ get_hard_regnum (regstack, reg)
/* Delete INSN from the RTL. Mark the insn, but don't remove it from
the chain of insns. Doing so could confuse block_begin and block_end
- if this were the only insn in the block. */
+ if this were the only insn in the block. */
static void
delete_insn_for_stacker (insn)
@@ -1684,7 +1690,7 @@ delete_insn_for_stacker (insn)
pop. WHEN is either emit_insn_before or emit_insn_after. A pop insn
is represented as a SET whose destination is the register to be popped
and source is the top of stack. A death note for the top of stack
- cases the movdf pattern to pop. */
+ cases the movdf pattern to pop. */
static rtx
emit_pop_insn (insn, regstack, reg, when)
@@ -1705,7 +1711,7 @@ emit_pop_insn (insn, regstack, reg, when)
FP_MODE_REG (FIRST_STACK_REG, DFmode));
pop_insn = (*when) (pop_rtx, insn);
- /* ??? This used to be VOIDmode, but that seems wrong. */
+ /* ??? This used to be VOIDmode, but that seems wrong. */
PUT_MODE (pop_insn, QImode);
REG_NOTES (pop_insn) = gen_rtx (EXPR_LIST, REG_DEAD,
@@ -1726,7 +1732,7 @@ emit_pop_insn (insn, regstack, reg, when)
the swap. A swap insn is represented as a PARALLEL of two patterns:
each pattern moves one reg to the other.
- If REG is already at the top of the stack, no insn is emitted. */
+ If REG is already at the top of the stack, no insn is emitted. */
static void
emit_swap_insn (insn, regstack, reg)
@@ -1770,7 +1776,7 @@ emit_swap_insn (insn, regstack, reg)
rtx i1dest = *get_true_reg (&SET_DEST (i1set));
/* If the previous register stack push was from the reg we are to
- swap with, omit the swap. */
+ swap with, omit the swap. */
if (GET_CODE (i1dest) == REG && REGNO (i1dest) == FIRST_STACK_REG
&& GET_CODE (i1src) == REG && REGNO (i1src) == hard_regno - 1
@@ -1796,12 +1802,12 @@ emit_swap_insn (insn, regstack, reg)
swap_rtx = gen_swapdf (FP_MODE_REG (hard_regno, DFmode),
FP_MODE_REG (FIRST_STACK_REG, DFmode));
swap_insn = emit_insn_after (swap_rtx, i1);
- /* ??? This used to be VOIDmode, but that seems wrong. */
+ /* ??? This used to be VOIDmode, but that seems wrong. */
PUT_MODE (swap_insn, QImode);
}
/* Handle a move to or from a stack register in PAT, which is in INSN.
- REGSTACK is the current stack. */
+ REGSTACK is the current stack. */
static void
move_for_stack_reg (insn, regstack, pat)
@@ -1819,14 +1825,14 @@ move_for_stack_reg (insn, regstack, pat)
if (STACK_REG_P (src) && STACK_REG_P (dest))
{
/* Write from one stack reg to another. If SRC dies here, then
- just change the register mapping and delete the insn. */
+ just change the register mapping and delete the insn. */
note = find_regno_note (insn, REG_DEAD, REGNO (src));
if (note)
{
int i;
- /* If this is a no-op move, there must not be a REG_DEAD note. */
+ /* If this is a no-op move, there must not be a REG_DEAD note. */
if (REGNO (src) == REGNO (dest))
abort ();
@@ -1834,12 +1840,12 @@ move_for_stack_reg (insn, regstack, pat)
if (regstack->reg[i] == REGNO (src))
break;
- /* The source must be live, and the dest must be dead. */
+ /* The source must be live, and the dest must be dead. */
if (i < 0 || get_hard_regnum (regstack, dest) >= FIRST_STACK_REG)
abort ();
/* It is possible that the dest is unused after this insn.
- If so, just pop the src. */
+ If so, just pop the src. */
if (find_regno_note (insn, REG_UNUSED, REGNO (dest)))
{
@@ -1859,12 +1865,12 @@ move_for_stack_reg (insn, regstack, pat)
return;
}
- /* The source reg does not die. */
+ /* The source reg does not die. */
/* If this appears to be a no-op move, delete it, or else it
will confuse the machine description output patterns. But if
it is REG_UNUSED, we must pop the reg now, as per-insn processing
- for REG_UNUSED will not work for deleted insns. */
+ for REG_UNUSED will not work for deleted insns. */
if (REGNO (src) == REGNO (dest))
{
@@ -1889,7 +1895,7 @@ move_for_stack_reg (insn, regstack, pat)
{
/* Save from a stack reg to MEM, or possibly integer reg. Since
only top of stack may be saved, emit an exchange first if
- needs be. */
+ needs be. */
emit_swap_insn (insn, regstack, src);
@@ -1900,7 +1906,7 @@ move_for_stack_reg (insn, regstack, pat)
regstack->top--;
CLEAR_HARD_REG_BIT (regstack->reg_set, REGNO (src));
}
- else if (GET_MODE (src) == XFmode && regstack->top != REG_STACK_SIZE)
+ else if (GET_MODE (src) == XFmode && regstack->top < REG_STACK_SIZE - 1)
{
/* A 387 cannot write an XFmode value to a MEM without
clobbering the source reg. The output code can handle
@@ -1943,7 +1949,7 @@ move_for_stack_reg (insn, regstack, pat)
abort ();
}
-void
+static void
swap_rtx_condition (pat)
rtx pat;
{
@@ -1977,7 +1983,7 @@ swap_rtx_condition (pat)
Also, a pop insn may need to be emitted. The 387 does have an
`fcompp' insn that can pop two regs, but it is sometimes too expensive
to do this - a `fcomp' followed by a `fstpl %st(0)' may be easier to
- set up. */
+ set up. */
static void
compare_for_stack_reg (insn, regstack, pat)
@@ -1987,12 +1993,35 @@ compare_for_stack_reg (insn, regstack, pat)
{
rtx *src1, *src2;
rtx src1_note, src2_note;
+ rtx cc0_user;
+ int have_cmove;
src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));
+ cc0_user = next_cc0_user (insn);
+
+ /* If the insn that uses cc0 is a conditional move, then the destination
+ must be the top of stack */
+ if (GET_CODE (PATTERN (cc0_user)) == SET
+ && SET_DEST (PATTERN (cc0_user)) != pc_rtx
+ && GET_CODE (SET_SRC (PATTERN (cc0_user))) == IF_THEN_ELSE)
+ {
+ rtx *dest, src_note;
+
+ dest = get_true_reg (&SET_DEST (PATTERN (cc0_user)));
+
+ have_cmove = 1;
+ if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
+ && REGNO (*dest) != regstack->reg[regstack->top])
+ {
+ emit_swap_insn (insn, regstack, *dest);
+ }
+ }
+ else
+ have_cmove = 0;
/* ??? If fxch turns out to be cheaper than fstp, give priority to
- registers that die in this insn - move those to stack top first. */
+ registers that die in this insn - move those to stack top first. */
if (! STACK_REG_P (*src1)
|| (STACK_REG_P (*src2)
&& get_hard_regnum (regstack, *src2) == FIRST_STACK_REG))
@@ -2015,7 +2044,7 @@ compare_for_stack_reg (insn, regstack, pat)
INSN_CODE (insn) = -1;
}
- /* We will fix any death note later. */
+ /* We will fix any death note later. */
src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
@@ -2024,7 +2053,8 @@ compare_for_stack_reg (insn, regstack, pat)
else
src2_note = NULL_RTX;
- emit_swap_insn (insn, regstack, *src1);
+ if (! have_cmove)
+ emit_swap_insn (insn, regstack, *src1);
replace_reg (src1, FIRST_STACK_REG);
@@ -2040,7 +2070,7 @@ compare_for_stack_reg (insn, regstack, pat)
/* If the second operand dies, handle that. But if the operands are
the same stack register, don't bother, because only one death is
- needed, and it was just handled. */
+ needed, and it was just handled. */
if (src2_note
&& ! (STACK_REG_P (*src1) && STACK_REG_P (*src2)
@@ -2049,7 +2079,7 @@ compare_for_stack_reg (insn, regstack, pat)
/* As a special case, two regs may die in this insn if src2 is
next to top of stack and the top of stack also dies. Since
we have already popped src1, "next to top of stack" is really
- at top (FIRST_STACK_REG) now. */
+ at top (FIRST_STACK_REG) now. */
if (get_hard_regnum (regstack, XEXP (src2_note, 0)) == FIRST_STACK_REG
&& src1_note)
@@ -2062,7 +2092,7 @@ compare_for_stack_reg (insn, regstack, pat)
{
/* The 386 can only represent death of the first operand in
the case handled above. In all other cases, emit a separate
- pop and remove the death note from here. */
+ pop and remove the death note from here. */
link_cc0_insns (insn);
@@ -2075,7 +2105,7 @@ compare_for_stack_reg (insn, regstack, pat)
}
/* Substitute new registers in PAT, which is part of INSN. REGSTACK
- is the current register layout. */
+ is the current register layout. */
static void
subst_stack_regs_pat (insn, regstack, pat)
@@ -2093,7 +2123,7 @@ subst_stack_regs_pat (insn, regstack, pat)
dest = get_true_reg (&SET_DEST (pat));
src = get_true_reg (&SET_SRC (pat));
- /* See if this is a `movM' pattern, and handle elsewhere if so. */
+ /* See if this is a `movM' pattern, and handle elsewhere if so. */
if (*dest != cc0_rtx
&& (STACK_REG_P (*src)
@@ -2122,13 +2152,13 @@ subst_stack_regs_pat (insn, regstack, pat)
break;
case REG:
- /* This is a `tstM2' case. */
+ /* This is a `tstM2' case. */
if (*dest != cc0_rtx)
abort ();
src1 = src;
- /* Fall through. */
+ /* Fall through. */
case FLOAT_TRUNCATE:
case SQRT:
@@ -2164,18 +2194,18 @@ subst_stack_regs_pat (insn, regstack, pat)
case DIV:
/* On i386, reversed forms of subM3 and divM3 exist for
MODE_FLOAT, so the same code that works for addM3 and mulM3
- can be used. */
+ can be used. */
case MULT:
case PLUS:
/* These insns can accept the top of stack as a destination
from a stack reg or mem, or can use the top of stack as a
source and some other stack register (possibly top of stack)
- as a destination. */
+ as a destination. */
src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));
- /* We will fix any death note later. */
+ /* We will fix any death note later. */
if (STACK_REG_P (*src1))
src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
@@ -2187,7 +2217,7 @@ subst_stack_regs_pat (insn, regstack, pat)
src2_note = NULL_RTX;
/* If either operand is not a stack register, then the dest
- must be top of stack. */
+ must be top of stack. */
if (! STACK_REG_P (*src1) || ! STACK_REG_P (*src2))
emit_swap_insn (insn, regstack, *dest);
@@ -2220,7 +2250,7 @@ subst_stack_regs_pat (insn, regstack, pat)
the destination is somewhere else - merely substitute it.
But if the reg that dies is not at top of stack, then
move the top of stack to the dead reg, as though we had
- done the insn and then a store-with-pop. */
+ done the insn and then a store-with-pop. */
if (REGNO (XEXP (src1_note, 0)) == regstack->reg[regstack->top])
{
@@ -2306,6 +2336,59 @@ subst_stack_regs_pat (insn, regstack, pat)
}
break;
+ case IF_THEN_ELSE:
+ /* This insn requires the top of stack to be the destination. */
+
+ src1 = get_true_reg (&XEXP (SET_SRC (pat), 1));
+ src2 = get_true_reg (&XEXP (SET_SRC (pat), 2));
+
+ src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+ src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+
+ {
+ rtx src_note [3];
+ int i;
+
+ src_note[0] = 0;
+ src_note[1] = src1_note;
+ src_note[2] = src2_note;
+
+ if (STACK_REG_P (*src1))
+ replace_reg (src1, get_hard_regnum (regstack, *src1));
+ if (STACK_REG_P (*src2))
+ replace_reg (src2, get_hard_regnum (regstack, *src2));
+
+ for (i = 1; i <= 2; i++)
+ if (src_note [i])
+ {
+ /* If the register that dies is not at the top of stack, then
+ move the top of stack to the dead reg */
+ if (REGNO (XEXP (src_note[i], 0))
+ != regstack->reg[regstack->top])
+ {
+ remove_regno_note (insn, REG_DEAD,
+ REGNO (XEXP (src_note [i], 0)));
+ emit_pop_insn (insn, regstack, XEXP (src_note[i], 0),
+ emit_insn_after);
+ }
+ else
+ {
+ CLEAR_HARD_REG_BIT (regstack->reg_set,
+ REGNO (XEXP (src_note[i], 0)));
+ replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG);
+ regstack->top--;
+ }
+ }
+ }
+
+ /* Make dest the top of stack. Add dest to regstack if not present. */
+ if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG)
+ regstack->reg[++regstack->top] = REGNO (*dest);
+ SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+ replace_reg (dest, FIRST_STACK_REG);
+
+ break;
+
default:
abort ();
}
@@ -2359,14 +2442,14 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
/* Find out what the constraints required. If no constraint
alternative matches, that is a compiler bug: we should have caught
such an insn during the life analysis pass (and reload should have
- caught it regardless). */
+ caught it regardless). */
i = constrain_asm_operands (n_operands, operands, constraints,
operand_matches, operand_class);
if (i < 0)
abort ();
- /* Strip SUBREGs here to make the following code simpler. */
+ /* Strip SUBREGs here to make the following code simpler. */
for (i = 0; i < n_operands; i++)
if (GET_CODE (operands[i]) == SUBREG
&& GET_CODE (SUBREG_REG (operands[i])) == REG)
@@ -2452,7 +2535,7 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
these constraints are for single register classes, and reload
guaranteed that operand[i] is already in that class, we can
just use REGNO (operands[i]) to know which actual reg this
- operand needs to be in. */
+ operand needs to be in. */
int regno = get_hard_regnum (&temp_stack, operands[i]);
@@ -2464,7 +2547,7 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
/* operands[i] is not in the right place. Find it
and swap it with whatever is already in I's place.
K is where operands[i] is now. J is where it should
- be. */
+ be. */
int j, k, temp;
k = temp_stack.top - (regno - FIRST_STACK_REG);
@@ -2483,7 +2566,7 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
change_stack (insn, regstack, &temp_stack, emit_insn_before);
/* Make the needed input register substitutions. Do death notes and
- clobbers too, because these are for inputs, not outputs. */
+ clobbers too, because these are for inputs, not outputs. */
for (i = first_input; i < first_input + n_inputs; i++)
if (STACK_REG_P (operands[i]))
@@ -2523,13 +2606,13 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
}
}
- /* Now remove from REGSTACK any inputs that the asm implicitly popped. */
+ /* Now remove from REGSTACK any inputs that the asm implicitly popped. */
for (i = first_input; i < first_input + n_inputs; i++)
if (STACK_REG_P (operands[i]))
{
/* An input reg is implicitly popped if it is tied to an
- output, or if there is a CLOBBER for it. */
+ output, or if there is a CLOBBER for it. */
int j;
for (j = 0; j < n_clobbers; j++)
@@ -2552,7 +2635,7 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
/* Now add to REGSTACK any outputs that the asm implicitly pushed.
Note that there isn't any need to substitute register numbers.
- ??? Explain why this is true. */
+ ??? Explain why this is true. */
for (i = LAST_STACK_REG; i >= FIRST_STACK_REG; i--)
{
@@ -2610,7 +2693,7 @@ subst_asm_stack_regs (insn, regstack, operands, operands_loc, constraints,
/* Substitute stack hard reg numbers for stack virtual registers in
INSN. Non-stack register numbers are not changed. REGSTACK is the
current stack content. Insns may be emitted as needed to arrange the
- stack for the 387 based on the contents of the insn. */
+ stack for the 387 based on the contents of the insn. */
static void
subst_stack_regs (insn, regstack)
@@ -2619,6 +2702,7 @@ subst_stack_regs (insn, regstack)
{
register rtx *note_link, note;
register int i;
+ rtx head, jump, pat, cipat;
int n_operands;
if (GET_CODE (insn) == CALL_INSN)
@@ -2647,7 +2731,7 @@ subst_stack_regs (insn, regstack)
Since we only record whether entire insn mentions stack regs, and
subst_stack_regs_pat only works for patterns that contain stack regs,
we must check each pattern in a parallel here. A call_value_pop could
- fail otherwise. */
+ fail otherwise. */
if (GET_MODE (insn) == QImode)
{
@@ -2656,7 +2740,7 @@ subst_stack_regs (insn, regstack)
{
/* This insn is an `asm' with operands. Decode the operands,
decide how many are inputs, and do register substitution.
- Any REG_UNUSED notes will be handled by subst_asm_stack_regs. */
+ Any REG_UNUSED notes will be handled by subst_asm_stack_regs. */
rtx operands[MAX_RECOG_OPERANDS];
rtx *operands_loc[MAX_RECOG_OPERANDS];
@@ -2685,15 +2769,48 @@ subst_stack_regs (insn, regstack)
}
/* subst_stack_regs_pat may have deleted a no-op insn. If so, any
- REG_UNUSED will already have been dealt with, so just return. */
+ REG_UNUSED will already have been dealt with, so just return. */
if (GET_CODE (insn) == NOTE)
return;
+ /* If we are reached by a computed goto which sets this same stack register,
+ then pop this stack register, but maintain regstack. */
+
+ pat = single_set (insn);
+ if (pat != 0
+ && INSN_UID (insn) <= max_uid
+ && GET_CODE (block_begin[BLOCK_NUM(insn)]) == CODE_LABEL
+ && GET_CODE (pat) == SET && STACK_REG_P (SET_DEST (pat)))
+ for (head = block_begin[BLOCK_NUM(insn)], jump = LABEL_REFS (head);
+ jump != head;
+ jump = LABEL_NEXTREF (jump))
+ {
+ cipat = single_set (CONTAINING_INSN (jump));
+ if (cipat != 0
+ && GET_CODE (cipat) == SET
+ && SET_DEST (cipat) == pc_rtx
+ && uses_reg_or_mem (SET_SRC (cipat))
+ && INSN_UID (CONTAINING_INSN (jump)) <= max_uid)
+ {
+ int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
+ if (TEST_HARD_REG_BIT (block_out_reg_set[from_block],
+ REGNO (SET_DEST (pat))))
+ {
+ struct stack_def old;
+ bcopy (regstack->reg, old.reg, sizeof (old.reg));
+ emit_pop_insn (insn, regstack, SET_DEST (pat), emit_insn_before);
+ regstack->top += 1;
+ bcopy (old.reg, regstack->reg, sizeof (old.reg));
+ SET_HARD_REG_BIT (regstack->reg_set, REGNO (SET_DEST (pat)));
+ }
+ }
+ }
+
/* If there is a REG_UNUSED note on a stack register on this insn,
the indicated reg must be popped. The REG_UNUSED note is removed,
since the form of the newly emitted pop insn references the reg,
- making it no longer `unset'. */
+ making it no longer `unset'. */
note_link = &REG_NOTES(insn);
for (note = *note_link; note; note = XEXP (note, 1))
@@ -2716,7 +2833,7 @@ subst_stack_regs (insn, regstack)
will be the same as NEW upon return.
This function will not preserve block_end[]. But that information
- is no longer needed once this has executed. */
+ is no longer needed once this has executed. */
static void
change_stack (insn, old, new, when)
@@ -2734,7 +2851,7 @@ change_stack (insn, old, new, when)
if (when == emit_insn_after)
insn = NEXT_INSN (insn);
- /* Pop any registers that are not needed in the new block. */
+ /* Pop any registers that are not needed in the new block. */
for (reg = old->top; reg >= 0; reg--)
if (! TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]))
@@ -2744,7 +2861,7 @@ change_stack (insn, old, new, when)
if (new->top == -2)
{
/* If the new block has never been processed, then it can inherit
- the old stack order. */
+ the old stack order. */
new->top = old->top;
bcopy (old->reg, new->reg, sizeof (new->reg));
@@ -2752,10 +2869,10 @@ change_stack (insn, old, new, when)
else
{
/* This block has been entered before, and we must match the
- previously selected stack order. */
+ previously selected stack order. */
/* By now, the only difference should be the order of the stack,
- not their depth or liveliness. */
+ not their depth or liveliness. */
GO_IF_HARD_REG_EQUAL (old->reg_set, new->reg_set, win);
@@ -2771,12 +2888,12 @@ change_stack (insn, old, new, when)
depth of the stack. In some cases, the reg at the top of
stack may be correct, but swapped anyway in order to fix
other regs. But since we never swap any other reg away from
- its correct slot, this algorithm will converge. */
+ its correct slot, this algorithm will converge. */
do
{
/* Swap the reg at top of stack into the position it is
- supposed to be in, until the correct top of stack appears. */
+ supposed to be in, until the correct top of stack appears. */
while (old->reg[old->top] != new->reg[new->top])
{
@@ -2793,7 +2910,7 @@ change_stack (insn, old, new, when)
/* See if any regs remain incorrect. If so, bring an
incorrect reg to the top of stack, and let the while loop
- above fix it. */
+ above fix it. */
for (reg = new->top; reg >= 0; reg--)
if (new->reg[reg] != old->reg[reg])
@@ -2804,7 +2921,7 @@ change_stack (insn, old, new, when)
}
} while (reg >= 0);
- /* At this point there must be no differences. */
+ /* At this point there must be no differences. */
for (reg = old->top; reg >= 0; reg--)
if (old->reg[reg] != new->reg[reg])
@@ -2820,7 +2937,7 @@ change_stack (insn, old, new, when)
is the order of the register stack in INSN.
Any code that is emitted here must not be later processed as part
- of any block, as it will already contain hard register numbers. */
+ of any block, as it will already contain hard register numbers. */
static void
goto_block_pat (insn, regstack, pat)
@@ -2862,7 +2979,7 @@ goto_block_pat (insn, regstack, pat)
if (GET_CODE (label) != CODE_LABEL)
abort ();
- /* First, see if in fact anything needs to be done to the stack at all. */
+ /* First, see if in fact anything needs to be done to the stack at all. */
if (INSN_UID (label) <= 0)
return;
@@ -2871,7 +2988,7 @@ goto_block_pat (insn, regstack, pat)
if (label_stack->top == -2)
{
/* If the target block hasn't had a stack order selected, then
- we need merely ensure that no pops are needed. */
+ we need merely ensure that no pops are needed. */
for (reg = regstack->top; reg >= 0; reg--)
if (! TEST_HARD_REG_BIT (label_stack->reg_set, regstack->reg[reg]))
@@ -2879,7 +2996,7 @@ goto_block_pat (insn, regstack, pat)
if (reg == -1)
{
- /* change_stack will not emit any code in this case. */
+ /* change_stack will not emit any code in this case. */
change_stack (label, regstack, label_stack, emit_insn_after);
return;
@@ -2899,7 +3016,7 @@ goto_block_pat (insn, regstack, pat)
a jump around the code we are about to emit. Emit a label for the new
code, and point the original insn at this new label. We can't use
redirect_jump here, because we're using fld[4] of the code labels as
- LABEL_REF chains, no NUSES counters. */
+ LABEL_REF chains, no NUSES counters. */
new_jump = emit_jump_insn_before (gen_jump (label), label);
record_label_references (new_jump, PATTERN (new_jump));
@@ -2912,7 +3029,7 @@ goto_block_pat (insn, regstack, pat)
LABEL_REFS (new_label) = new_label;
/* The old label_ref will no longer point to the code_label if now uses,
- so strip the label_ref from the code_label's chain of references. */
+ so strip the label_ref from the code_label's chain of references. */
for (ref = &LABEL_REFS (label); *ref != label; ref = &LABEL_NEXTREF (*ref))
if (*ref == pat)
@@ -2929,7 +3046,7 @@ goto_block_pat (insn, regstack, pat)
if (JUMP_LABEL (insn) == label)
JUMP_LABEL (insn) = new_label;
- /* Now emit the needed code. */
+ /* Now emit the needed code. */
temp_stack = *regstack;
@@ -2938,7 +3055,7 @@ goto_block_pat (insn, regstack, pat)
/* Traverse all basic blocks in a function, converting the register
references in each insn from the "flat" register file that gcc uses, to
- the stack-like registers the 387 uses. */
+ the stack-like registers the 387 uses. */
static void
convert_regs ()
@@ -2963,7 +3080,7 @@ convert_regs ()
/* Process all insns in this block. Keep track of `next' here,
so that we don't process any insns emitted while making
- substitutions in INSN. */
+ substitutions in INSN. */
next = block_begin[block];
regstack = block_stack_in[block];
@@ -2974,14 +3091,14 @@ convert_regs ()
/* Don't bother processing unless there is a stack reg
mentioned or if it's a CALL_INSN (register passing of
- floating point values). */
+ floating point values). */
if (GET_MODE (insn) == QImode || GET_CODE (insn) == CALL_INSN)
subst_stack_regs (insn, &regstack);
} while (insn != block_end[block]);
- /* Something failed if the stack life doesn't match. */
+ /* Something failed if the stack life doesn't match. */
GO_IF_HARD_REG_EQUAL (regstack.reg_set, block_out_reg_set[block], win);
@@ -2992,12 +3109,12 @@ convert_regs ()
/* Adjust the stack of this block on exit to match the stack of
the target block, or copy stack information into stack of
jump target if the target block's stack order hasn't been set
- yet. */
+ yet. */
if (GET_CODE (insn) == JUMP_INSN)
goto_block_pat (insn, &regstack, PATTERN (insn));
- /* Likewise handle the case where we fall into the next block. */
+ /* Likewise handle the case where we fall into the next block. */
if ((block < blocks - 1) && block_drops_in[block+1])
change_stack (insn, &regstack, &block_stack_in[block+1],
@@ -3006,7 +3123,7 @@ convert_regs ()
/* If the last basic block is the end of a loop, and that loop has
regs live at its start, then the last basic block will have regs live
- at its end that need to be popped before the function returns. */
+ at its end that need to be popped before the function returns. */
{
int value_reg_low, value_reg_high;
@@ -3022,8 +3139,8 @@ convert_regs ()
}
for (reg = regstack.top; reg >= 0; reg--)
- if (regstack.reg[reg] < value_reg_low ||
- regstack.reg[reg] > value_reg_high)
+ if (regstack.reg[reg] < value_reg_low
+ || regstack.reg[reg] > value_reg_high)
insn = emit_pop_insn (insn, &regstack,
FP_MODE_REG (regstack.reg[reg], DFmode),
emit_insn_after);
@@ -3032,7 +3149,7 @@ convert_regs ()
}
/* Check expression PAT, which is in INSN, for label references. if
- one is found, print the block number of destination to FILE. */
+ one is found, print the block number of destination to FILE. */
static void
print_blocks (file, insn, pat)
@@ -3071,6 +3188,7 @@ print_blocks (file, insn, pat)
/* Write information about stack registers and stack blocks into FILE.
This is part of making a debugging dump. */
+
static void
dump_stack_info (file)
FILE *file;
diff --git a/gnu/usr.bin/gcc/regclass.c b/gnu/usr.bin/gcc/regclass.c
index 9b9a4d50ec7..e307e03ff21 100644
--- a/gnu/usr.bin/gcc/regclass.c
+++ b/gnu/usr.bin/gcc/regclass.c
@@ -1,5 +1,5 @@
/* Compute register class preferences for pseudo-registers.
- Copyright (C) 1987, 88, 91, 92, 93, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */
and a function init_reg_sets to initialize the tables. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "hard-reg-set.h"
#include "flags.h"
@@ -81,6 +82,9 @@ char call_used_regs[FIRST_PSEUDO_REGISTER];
HARD_REG_SET call_used_reg_set;
+/* HARD_REG_SET of registers we want to avoid caller saving. */
+HARD_REG_SET losing_caller_save_reg_set;
+
/* Data for initializing the above. */
static char initial_call_used_regs[] = CALL_USED_REGISTERS;
@@ -160,15 +164,6 @@ char *reg_names[] = REGISTER_NAMES;
enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
-/* Indexed by n, gives number of times (REG n) is set or clobbered.
- This information remains valid for the rest of the compilation
- of the current function; it is used to control register allocation.
-
- This information applies to both hard registers and pseudo registers,
- unlike much of the information above. */
-
-short *reg_n_sets;
-
/* Maximum cost of moving from a register in one class to a register in
another class. Based on REGISTER_MOVE_COST. */
@@ -352,6 +347,9 @@ init_reg_sets ()
may_move_cost[i][j] = cost;
}
+
+ /* Do any additional initialization regsets may need */
+ INIT_ONCE_REG_SET ();
}
/* After switches have been processed, which perhaps alter
@@ -390,6 +388,8 @@ init_reg_sets_1 ()
SET_HARD_REG_BIT (call_used_reg_set, i);
if (call_fixed_regs[i])
SET_HARD_REG_BIT (call_fixed_reg_set, i);
+ if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (i)))
+ SET_HARD_REG_BIT (losing_caller_save_reg_set, i);
}
}
@@ -674,6 +674,10 @@ regclass (f, nregs)
being used in such addresses. */
if ((0
+#ifdef SECONDARY_RELOAD_CLASS
+ || (SECONDARY_RELOAD_CLASS (BASE_REG_CLASS, m, r)
+ != NO_REGS)
+#else
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
@@ -682,6 +686,7 @@ regclass (f, nregs)
|| (SECONDARY_OUTPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#endif
+#endif
)
&& ! auto_inc_dec_reg_p (r, m))
forbidden_inc_dec_class[i] = 1;
@@ -824,8 +829,8 @@ regclass (f, nregs)
basic_block_head[b] = newinsn;
}
- /* This makes one more setting of new insns's dest. */
- reg_n_sets[REGNO (recog_operand[0])]++;
+ /* This makes one more setting of new insns's dest. */
+ REG_N_SETS (REGNO (recog_operand[0]))++;
*recog_operand_loc[1] = recog_operand[0];
for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
@@ -968,7 +973,7 @@ regclass (f, nregs)
/* If we don't add any classes, nothing to try. */
if (alt == best)
- alt = (int) NO_REGS;
+ alt = NO_REGS;
/* We cast to (int) because (char) hits bugs in some compilers. */
prefclass[i] = (int) best;
@@ -1536,38 +1541,52 @@ record_address_regs (x, class, scale)
else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
record_address_regs (arg0, INDEX_REG_CLASS, scale);
- /* If this the sum of two registers where the first is known to be a
- pointer, it must be a base register with the second an index. */
+ /* If both operands are registers but one is already a hard register
+ of index or base class, give the other the class that the hard
+ register is not. */
else if (code0 == REG && code1 == REG
- && REGNO_POINTER_FLAG (REGNO (arg0)))
+ && REGNO (arg0) < FIRST_PSEUDO_REGISTER
+ && (REG_OK_FOR_BASE_P (arg0) || REG_OK_FOR_INDEX_P (arg0)))
+ record_address_regs (arg1,
+ REG_OK_FOR_BASE_P (arg0)
+ ? INDEX_REG_CLASS : BASE_REG_CLASS,
+ scale);
+ else if (code0 == REG && code1 == REG
+ && REGNO (arg1) < FIRST_PSEUDO_REGISTER
+ && (REG_OK_FOR_BASE_P (arg1) || REG_OK_FOR_INDEX_P (arg1)))
+ record_address_regs (arg0,
+ REG_OK_FOR_BASE_P (arg1)
+ ? INDEX_REG_CLASS : BASE_REG_CLASS,
+ scale);
+
+ /* If one operand is known to be a pointer, it must be the base
+ with the other operand the index. Likewise if the other operand
+ is a MULT. */
+
+ else if ((code0 == REG && REGNO_POINTER_FLAG (REGNO (arg0)))
+ || code1 == MULT)
{
record_address_regs (arg0, BASE_REG_CLASS, scale);
record_address_regs (arg1, INDEX_REG_CLASS, scale);
}
+ else if ((code1 == REG && REGNO_POINTER_FLAG (REGNO (arg1)))
+ || code0 == MULT)
+ {
+ record_address_regs (arg0, INDEX_REG_CLASS, scale);
+ record_address_regs (arg1, BASE_REG_CLASS, scale);
+ }
- /* If this is the sum of two registers and neither is known to
- be a pointer, count equal chances that each might be a base
+ /* Otherwise, count equal chances that each might be a base
or index register. This case should be rare. */
- else if (code0 == REG && code1 == REG
- && ! REGNO_POINTER_FLAG (REGNO (arg0))
- && ! REGNO_POINTER_FLAG (REGNO (arg1)))
+ else
{
record_address_regs (arg0, BASE_REG_CLASS, scale / 2);
record_address_regs (arg0, INDEX_REG_CLASS, scale / 2);
record_address_regs (arg1, BASE_REG_CLASS, scale / 2);
record_address_regs (arg1, INDEX_REG_CLASS, scale / 2);
}
-
- /* In all other cases, the first operand is an index and the
- second is the base. */
-
- else
- {
- record_address_regs (arg0, INDEX_REG_CLASS, scale);
- record_address_regs (arg1, BASE_REG_CLASS, scale);
- }
}
break;
@@ -1648,35 +1667,101 @@ auto_inc_dec_reg_p (reg, mode)
#endif /* REGISTER_CONSTRAINTS */
-/* This is the `regscan' pass of the compiler, run just before cse
- and again just before loop.
+/* Allocate enough space to hold NUM_REGS registers for the tables used for
+ reg_scan and flow_analysis that are indexed by the register number. If
+ NEW_P is non zero, initialize all of the registers, otherwise only
+ initialize the new registers allocated. The same table is kept from
+ function to function, only reallocating it when we need more room. If
+ RENUMBER_P is non zero, allocate the reg_renumber array also. */
- It finds the first and last use of each pseudo-register
- and records them in the vectors regno_first_uid, regno_last_uid
- and counts the number of sets in the vector reg_n_sets.
+void
+allocate_reg_info (num_regs, new_p, renumber_p)
+ int num_regs;
+ int new_p;
+ int renumber_p;
+{
+ static int regno_allocated = 0;
+ static int regno_max = 0;
+ static short *renumber = (short *)0;
+ int i;
+ int size_info;
+ int size_renumber;
+ int min = (new_p) ? 0 : regno_max;
- REPEAT is nonzero the second time this is called. */
+ /* If this message come up, and you want to fix it, then all of the tables
+ like reg_renumber, etc. that use short will have to be found and lengthed
+ to int or HOST_WIDE_INT. */
-/* Indexed by pseudo register number, gives uid of first insn using the reg
- (as of the time reg_scan is called). */
+ /* Free up all storage allocated */
+ if (num_regs < 0)
+ {
+ if (reg_n_info)
+ {
+ free ((char *)reg_n_info);
+ free ((char *)renumber);
+ reg_n_info = (reg_info *)0;
+ renumber = (short *)0;
+ }
+ regno_allocated = 0;
+ regno_max = 0;
+ return;
+ }
-int *regno_first_uid;
+ if (num_regs > regno_allocated)
+ {
+ regno_allocated = num_regs + (num_regs / 20); /* add some slop space */
+ size_info = regno_allocated * sizeof (reg_info);
+ size_renumber = regno_allocated * sizeof (short);
-/* Indexed by pseudo register number, gives uid of last insn using the reg
- (as of the time reg_scan is called). */
+ if (!reg_n_info)
+ {
+ reg_n_info = (reg_info *) xmalloc (size_info);
+ renumber = (short *) xmalloc (size_renumber);
+ }
+
+ else if (new_p) /* if we're zapping everything, no need to realloc */
+ {
+ free ((char *)reg_n_info);
+ free ((char *)renumber);
+ reg_n_info = (reg_info *) xmalloc (size_info);
+ renumber = (short *) xmalloc (size_renumber);
+ }
+
+ else
+ {
+ reg_n_info = (reg_info *) xrealloc ((char *)reg_n_info, size_info);
+ renumber = (short *) xrealloc ((char *)renumber, size_renumber);
+ }
+ }
-int *regno_last_uid;
+ if (min < num_regs)
+ {
+ bzero ((char *) &reg_n_info[min], (num_regs - min) * sizeof (reg_info));
+ for (i = min; i < num_regs; i++)
+ {
+ REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
+ renumber[i] = -1;
+ }
+ }
-/* Indexed by pseudo register number, gives uid of last insn using the reg
- or mentioning it in a note (as of the time reg_scan is called). */
+ if (renumber_p)
+ reg_renumber = renumber;
-int *regno_last_note_uid;
+ /* Tell the regset code about the new number of registers */
+ MAX_REGNO_REG_SET (num_regs, new_p, renumber_p);
-/* Record the number of registers we used when we allocated the above two
- tables. If we are called again with more than this, we must re-allocate
- the tables. */
+ regno_max = num_regs;
+}
-static int highest_regno_in_uid_map;
+
+/* This is the `regscan' pass of the compiler, run just before cse
+ and again just before loop.
+
+ It finds the first and last use of each pseudo-register
+ and records them in the vectors regno_first_uid, regno_last_uid
+ and counts the number of sets in the vector reg_n_sets.
+
+ REPEAT is nonzero the second time this is called. */
/* Maximum number of parallel sets and clobbers in any insn in this fn.
Always at least 3, since the combiner could put that many together
@@ -1692,26 +1777,7 @@ reg_scan (f, nregs, repeat)
{
register rtx insn;
- if (!repeat || nregs > highest_regno_in_uid_map)
- {
- /* Leave some spare space in case more regs are allocated. */
- highest_regno_in_uid_map = nregs + nregs / 20;
- regno_first_uid
- = (int *) oballoc (highest_regno_in_uid_map * sizeof (int));
- regno_last_uid
- = (int *) oballoc (highest_regno_in_uid_map * sizeof (int));
- regno_last_note_uid
- = (int *) oballoc (highest_regno_in_uid_map * sizeof (int));
- reg_n_sets
- = (short *) oballoc (highest_regno_in_uid_map * sizeof (short));
- }
-
- bzero ((char *) regno_first_uid, highest_regno_in_uid_map * sizeof (int));
- bzero ((char *) regno_last_uid, highest_regno_in_uid_map * sizeof (int));
- bzero ((char *) regno_last_note_uid,
- highest_regno_in_uid_map * sizeof (int));
- bzero ((char *) reg_n_sets, highest_regno_in_uid_map * sizeof (short));
-
+ allocate_reg_info (nregs, TRUE, FALSE);
max_parallel = 3;
for (insn = f; insn; insn = NEXT_INSN (insn))
@@ -1759,11 +1825,11 @@ reg_scan_mark_refs (x, insn, note_flag)
{
register int regno = REGNO (x);
- regno_last_note_uid[regno] = INSN_UID (insn);
+ REGNO_LAST_NOTE_UID (regno) = INSN_UID (insn);
if (!note_flag)
- regno_last_uid[regno] = INSN_UID (insn);
- if (regno_first_uid[regno] == 0)
- regno_first_uid[regno] = INSN_UID (insn);
+ REGNO_LAST_UID (regno) = INSN_UID (insn);
+ if (REGNO_FIRST_UID (regno) == 0)
+ REGNO_FIRST_UID (regno) = INSN_UID (insn);
}
break;
@@ -1788,7 +1854,7 @@ reg_scan_mark_refs (x, insn, note_flag)
;
if (GET_CODE (dest) == REG)
- reg_n_sets[REGNO (dest)]++;
+ REG_N_SETS (REGNO (dest))++;
/* If this is setting a pseudo from another pseudo or the sum of a
pseudo and a constant integer and the other pseudo is known to be
@@ -1831,7 +1897,7 @@ reg_scan_mark_refs (x, insn, note_flag)
|| GET_CODE (XEXP (note, 0)) == LABEL_REF))))
REGNO_POINTER_FLAG (REGNO (SET_DEST (x))) = 1;
- /* ... fall through ... */
+ /* ... fall through ... */
default:
{
@@ -1898,3 +1964,17 @@ reg_classes_intersect_p (c1, c2)
return 0;
}
+/* Release any memory allocated by register sets. */
+
+void
+regset_release_memory ()
+{
+ if (basic_block_live_at_start)
+ {
+ free_regset_vector (basic_block_live_at_start, n_basic_blocks);
+ basic_block_live_at_start = 0;
+ }
+
+ FREE_REG_SET (regs_live_at_setjmp);
+ bitmap_release_memory ();
+}
diff --git a/gnu/usr.bin/gcc/regs.h b/gnu/usr.bin/gcc/regs.h
index daa012e95b5..fe1dbfe6b7a 100644
--- a/gnu/usr.bin/gcc/regs.h
+++ b/gnu/usr.bin/gcc/regs.h
@@ -1,5 +1,5 @@
/* Define per-register tables for data flow info and register allocation.
- Copyright (C) 1987, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -29,6 +29,10 @@ Boston, MA 02111-1307, USA. */
#define REG_SIZE(R) \
((mode_size[(int) GET_MODE (R)] + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+#ifndef SMALL_REGISTER_CLASSES
+#define SMALL_REGISTER_CLASSES 0
+#endif
+
/* Maximum register number used in this function, plus one. */
extern int max_regno;
@@ -37,14 +41,37 @@ extern int max_regno;
extern int max_scratch;
+/* Register information indexed by register number */
+typedef struct reg_info_def {
+ /* fields set by reg_scan */
+ int first_uid; /* UID of first insn to use (REG n) */
+ int last_uid; /* UID of last insn to use (REG n) */
+ int last_note_uid; /* UID of last note to use (REG n) */
+
+ /* fields set by both reg_scan and flow_analysis */
+ int sets; /* # of times (REG n) is set */
+
+ /* fields set by flow_analysis */
+ int refs; /* # of times (REG n) is used or set */
+ int deaths; /* # of times (REG n) dies */
+ int live_length; /* # of instructions (REG n) is live */
+ int calls_crossed; /* # of calls (REG n) is live across */
+ int basic_block; /* # of basic blocks (REG n) is used in */
+ char changes_size; /* whether (SUBREG (REG n)) changes size */
+} reg_info;
+
+extern reg_info *reg_n_info;
+
/* Indexed by n, gives number of times (REG n) is used or set.
References within loops may be counted more times. */
-extern int *reg_n_refs;
+#define REG_N_REFS(N) (reg_n_info[(N)].refs)
-/* Indexed by n, gives number of times (REG n) is set. */
+/* Indexed by n, gives number of times (REG n) is set.
+ ??? both regscan and flow allocate space for this. We should settle
+ on just copy. */
-extern short *reg_n_sets;
+#define REG_N_SETS(N) (reg_n_info[(N)].sets)
/* Indexed by N, gives number of insns in which register N dies.
Note that if register N is live around loops, it can die
@@ -52,13 +79,13 @@ extern short *reg_n_sets;
So this is only a reliable indicator of how many regions of life there are
for registers that are contained in one basic block. */
-extern short *reg_n_deaths;
+#define REG_N_DEATHS(N) (reg_n_info[(N)].deaths)
/* Indexed by N; says whether a pseudo register N was ever used
within a SUBREG that changes the size of the reg. Some machines prohibit
such objects to be in certain (usually floating-point) registers. */
-extern char *reg_changes_size;
+#define REG_CHANGES_SIZE(N) (reg_n_info[(N)].changes_size)
/* Get the number of consecutive words required to hold pseudo-reg N. */
@@ -77,7 +104,7 @@ extern char *reg_changes_size;
/* Indexed by N, gives number of CALL_INSNS across which (REG n) is live. */
-extern int *reg_n_calls_crossed;
+#define REG_N_CALLS_CROSSED(N) (reg_n_info[(N)].calls_crossed)
/* Total number of instructions at which (REG n) is live.
The larger this is, the less priority (REG n) gets for
@@ -94,10 +121,14 @@ extern int *reg_n_calls_crossed;
is not required. global.c makes an allocno for this but does
not try to assign a hard register to it. */
-extern int *reg_live_length;
+#define REG_LIVE_LENGTH(N) (reg_n_info[(N)].live_length)
/* Vector of substitutions of register numbers,
- used to map pseudo regs into hardware regs. */
+ used to map pseudo regs into hardware regs.
+
+ This can't be folded into reg_n_info without changing all of the
+ machine dependent directories, since the reload functions
+ in the machine dependent files access it. */
extern short *reg_renumber;
@@ -122,7 +153,7 @@ extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
It is sometimes adjusted for subsequent changes during loop,
but not adjusted by cse even if cse invalidates it. */
-extern int *regno_first_uid;
+#define REGNO_FIRST_UID(N) (reg_n_info[(N)].first_uid)
/* Vector indexed by regno; gives uid of last insn using that reg.
This is computed by reg_scan for use by cse and loop.
@@ -130,11 +161,16 @@ extern int *regno_first_uid;
but not adjusted by cse even if cse invalidates it.
This is harmless since cse won't scan through a loop end. */
-extern int *regno_last_uid;
+#define REGNO_LAST_UID(N) (reg_n_info[(N)].last_uid)
/* Similar, but includes insns that mention the reg in their notes. */
-extern int *regno_last_note_uid;
+#define REGNO_LAST_NOTE_UID(N) (reg_n_info[(N)].last_note_uid)
+
+/* This is reset to LAST_VIRTUAL_REGISTER + 1 at the start of each function.
+ After rtl generation, it is 1 plus the largest register number used. */
+
+extern int reg_rtx_no;
/* Vector indexed by regno; contains 1 for a register is considered a pointer.
Reloading, etc. will use a pointer register rather than a non-pointer
@@ -142,6 +178,7 @@ extern int *regno_last_note_uid;
extern char *regno_pointer_flag;
#define REGNO_POINTER_FLAG(REGNO) regno_pointer_flag[REGNO]
+extern int regno_pointer_flag_length;
/* List made of EXPR_LIST rtx's which gives pairs of pseudo registers
that have to go in the same hard reg. */
@@ -165,6 +202,12 @@ extern int caller_save_needed;
#define CALLER_SAVE_PROFITABLE(REFS, CALLS) (4 * (CALLS) < (REFS))
#endif
+/* On most machines a register class is likely to be spilled if it
+ only has one register. */
+#ifndef CLASS_LIKELY_SPILLED_P
+#define CLASS_LIKELY_SPILLED_P(CLASS) (reg_class_size[(int) (CLASS)] == 1)
+#endif
+
/* Allocated in local_alloc. */
/* A list of SCRATCH rtl allocated by local-alloc. */
@@ -173,3 +216,6 @@ extern rtx *scratch_list;
extern int *scratch_block;
/* The length of the arrays pointed to by scratch_block and scratch_list. */
extern int scratch_list_length;
+
+/* Allocate reg_n_info tables */
+extern void allocate_reg_info PROTO((int, int, int));
diff --git a/gnu/usr.bin/gcc/reload.h b/gnu/usr.bin/gcc/reload.h
index d10efb5b610..2475c1f6365 100644
--- a/gnu/usr.bin/gcc/reload.h
+++ b/gnu/usr.bin/gcc/reload.h
@@ -1,5 +1,5 @@
/* Communication between reload.c and reload1.c.
- Copyright (C) 1987, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 92, 93, 94, 95, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -39,6 +39,8 @@ Boston, MA 02111-1307, USA. */
/* Maximum number of reloads we can need. */
#define MAX_RELOADS (2 * MAX_RECOG_OPERANDS * (MAX_REGS_PER_ADDRESS + 1))
+extern enum reg_class reload_address_base_reg_class;
+extern enum reg_class reload_address_index_reg_class;
extern rtx reload_in[MAX_RELOADS];
extern rtx reload_out[MAX_RELOADS];
extern rtx reload_in_reg[MAX_RELOADS];
@@ -68,7 +70,9 @@ extern rtx reload_reg_rtx[MAX_RELOADS];
something used before or after the insn
RELOAD_FOR_INPUT_ADDRESS reload for parts of the address of an object
that is an input reload
- RELOAD_FOR_OUTPUT_ADDRESS likewise, for output reload
+ RELOAD_FOR_INPADDR_ADDRESS reload needed for RELOAD_FOR_INPUT_ADDRESS
+ RELOAD_FOR_OUTPUT_ADDRESS like RELOAD_FOR INPUT_ADDRESS, for output
+ RELOAD_FOR_OUTADDR_ADDRESS reload needed for RELOAD_FOR_OUTPUT_ADDRESS
RELOAD_FOR_OPERAND_ADDRESS reload for the address of a non-reloaded
operand; these don't conflict with
any other addresses.
@@ -84,7 +88,8 @@ extern rtx reload_reg_rtx[MAX_RELOADS];
enum reload_type
{
RELOAD_FOR_INPUT, RELOAD_FOR_OUTPUT, RELOAD_FOR_INSN,
- RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_OUTPUT_ADDRESS,
+ RELOAD_FOR_INPUT_ADDRESS, RELOAD_FOR_INPADDR_ADDRESS,
+ RELOAD_FOR_OUTPUT_ADDRESS, RELOAD_FOR_OUTADDR_ADDRESS,
RELOAD_FOR_OPERAND_ADDRESS, RELOAD_FOR_OPADDR_ADDR,
RELOAD_OTHER, RELOAD_FOR_OTHER_ADDRESS
};
@@ -140,11 +145,6 @@ extern void clear_secondary_mem PROTO((void));
reload TO. */
extern void transfer_replacements PROTO((int, int));
-/* Return 1 if ADDR is a valid memory address for mode MODE,
- and check that each pseudo reg has the proper kind of
- hard reg. */
-extern int strict_memory_address_p PROTO((enum machine_mode, rtx));
-
/* Like rtx_equal_p except that it allows a REG and a SUBREG to match
if they are the same hard reg, and has special hacks for
autoincrement and autodecrement. */
@@ -207,7 +207,7 @@ extern int regno_clobbered_p PROTO((int, rtx));
extern void init_reload PROTO((void));
/* The reload pass itself. */
-extern int reload STDIO_PROTO((rtx, int, FILE *));
+extern int reload PROTO((rtx, int, FILE *));
/* Mark the slots in regs_ever_live for the hard regs
used by pseudo-reg number REGNO. */
@@ -215,7 +215,7 @@ extern void mark_home_live PROTO((int));
/* Scan X and replace any eliminable registers (such as fp) with a
replacement (such as sp), plus an offset. */
-extern rtx eliminate_regs PROTO((rtx, enum machine_mode, rtx));
+extern rtx eliminate_regs PROTO((rtx, enum machine_mode, rtx, int));
/* Emit code to perform a reload from IN (which may be a reload register) to
OUT (which may also be a reload register). IN or OUT is from operand
diff --git a/gnu/usr.bin/gcc/reload1.c b/gnu/usr.bin/gcc/reload1.c
index 33c77e4e4a8..182bb92abd5 100644
--- a/gnu/usr.bin/gcc/reload1.c
+++ b/gnu/usr.bin/gcc/reload1.c
@@ -1,5 +1,5 @@
/* Reload pseudo regs into hard regs for insns that require hard regs.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,8 +19,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "obstack.h"
#include "insn-config.h"
@@ -79,7 +79,7 @@ Boston, MA 02111-1307, USA. */
#endif
/* During reload_as_needed, element N contains a REG rtx for the hard reg
- into which reg N has been reloaded (perhaps for a previous insn). */
+ into which reg N has been reloaded (perhaps for a previous insn). */
static rtx *reg_last_reload_reg;
/* Elt N nonzero if reg_last_reload_reg[N] has been set in this insn
@@ -159,7 +159,7 @@ HARD_REG_SET forbidden_regs;
/* This reg set indicates registers that are not good for spill registers.
They will not be used to complete groups of spill registers. This includes
all fixed registers, registers that may be eliminated, and, if
- SMALL_REGISTER_CLASSES is not defined, registers explicitly used in the rtl.
+ SMALL_REGISTER_CLASSES is zero, registers explicitly used in the rtl.
(spill_reg_order prevents these registers from being used to start a
group.) */
@@ -170,6 +170,13 @@ static HARD_REG_SET bad_spill_regs;
elements that are actually valid; new ones are added at the end. */
static short spill_regs[FIRST_PSEUDO_REGISTER];
+/* This reg set indicates those registers that have been used a spill
+ registers. This information is used in reorg.c, to help figure out
+ what registers are live at any point. It is assumed that all spill_regs
+ are dead at every CODE_LABEL. */
+
+HARD_REG_SET used_spill_regs;
+
/* Index of last register assigned as a spill register. We allocate in
a round-robin fashion. */
@@ -246,6 +253,18 @@ int reload_first_uid;
int caller_save_needed;
+/* The register class to use for a base register when reloading an
+ address. This is normally BASE_REG_CLASS, but it may be different
+ when using SMALL_REGISTER_CLASSES and passing parameters in
+ registers. */
+enum reg_class reload_address_base_reg_class;
+
+/* The register class to use for an index register when reloading an
+ address. This is normally INDEX_REG_CLASS, but it may be different
+ when using SMALL_REGISTER_CLASSES and passing parameters in
+ registers. */
+enum reg_class reload_address_index_reg_class;
+
/* Set to 1 while reload_as_needed is operating.
Required by some machines to handle any generated moves differently. */
@@ -270,6 +289,9 @@ char *reload_firstobj;
/* List of labels that must never be deleted. */
extern rtx forced_labels;
+
+/* Allocation number table from global register allocation. */
+extern int *reg_allocno;
/* This structure is used to record information about register eliminations.
Each array entry describes one possible way of eliminating a register
@@ -278,22 +300,22 @@ extern rtx forced_labels;
static struct elim_table
{
- int from; /* Register number to be eliminated. */
- int to; /* Register number used as replacement. */
- int initial_offset; /* Initial difference between values. */
- int can_eliminate; /* Non-zero if this elimination can be done. */
+ int from; /* Register number to be eliminated. */
+ int to; /* Register number used as replacement. */
+ int initial_offset; /* Initial difference between values. */
+ int can_eliminate; /* Non-zero if this elimination can be done. */
int can_eliminate_previous; /* Value of CAN_ELIMINATE in previous scan over
- insns made by reload. */
- int offset; /* Current offset between the two regs. */
- int max_offset; /* Maximum offset between the two regs. */
- int previous_offset; /* Offset at end of previous insn. */
- int ref_outside_mem; /* "to" has been referenced outside a MEM. */
+ insns made by reload. */
+ int offset; /* Current offset between the two regs. */
+ int max_offset; /* Maximum offset between the two regs. */
+ int previous_offset; /* Offset at end of previous insn. */
+ int ref_outside_mem; /* "to" has been referenced outside a MEM. */
rtx from_rtx; /* REG rtx for the register to be eliminated.
We cannot simply compare the number since
we might then spuriously replace a hard
register corresponding to a pseudo
- assigned to the reg to be eliminated. */
- rtx to_rtx; /* REG rtx for the replacement. */
+ assigned to the reg to be eliminated. */
+ rtx to_rtx; /* REG rtx for the replacement. */
} reg_eliminate[] =
/* If a set of eliminable registers was specified, define the table from it.
@@ -349,13 +371,12 @@ static int eliminate_regs_in_insn PROTO((rtx, int));
static void mark_not_eliminable PROTO((rtx, rtx));
static int spill_hard_reg PROTO((int, int, FILE *, int));
static void scan_paradoxical_subregs PROTO((rtx));
-static int hard_reg_use_compare PROTO((struct hard_reg_n_uses *,
- struct hard_reg_n_uses *));
-static void order_regs_for_reload PROTO((void));
-static int compare_spill_regs PROTO((short *, short *));
+static int hard_reg_use_compare PROTO((const GENERIC_PTR, const GENERIC_PTR));
+static void order_regs_for_reload PROTO((int));
+static int compare_spill_regs PROTO((const GENERIC_PTR, const GENERIC_PTR));
static void reload_as_needed PROTO((rtx, int));
static void forget_old_reloads_1 PROTO((rtx, rtx));
-static int reload_reg_class_lower PROTO((short *, short *));
+static int reload_reg_class_lower PROTO((const GENERIC_PTR, const GENERIC_PTR));
static void mark_reload_reg_in_use PROTO((int, int, enum reload_type,
enum machine_mode));
static void clear_reload_reg_in_use PROTO((int, int, enum reload_type,
@@ -372,6 +393,18 @@ static void delete_output_reload PROTO((rtx, int, rtx));
static void inc_for_reload PROTO((rtx, rtx, int));
static int constraint_accepts_reg_p PROTO((char *, rtx));
static int count_occurrences PROTO((rtx, rtx));
+static void reload_cse_invalidate_regno PROTO((int, enum machine_mode, int));
+static int reload_cse_mem_conflict_p PROTO((rtx, rtx));
+static void reload_cse_invalidate_mem PROTO((rtx));
+static void reload_cse_invalidate_rtx PROTO((rtx, rtx));
+static int reload_cse_regno_equal_p PROTO((int, rtx, enum machine_mode));
+static int reload_cse_noop_set_p PROTO((rtx, rtx));
+static int reload_cse_simplify_set PROTO((rtx, rtx));
+static int reload_cse_simplify_operands PROTO((rtx));
+static void reload_cse_check_clobber PROTO((rtx, rtx));
+static void reload_cse_record_set PROTO((rtx, rtx));
+static void reload_cse_delete_death_notes PROTO((rtx));
+static void reload_cse_no_longer_dead PROTO((int, enum machine_mode));
/* Initialize the reload pass once per compilation. */
@@ -419,9 +452,67 @@ init_reload ()
}
}
- /* Initialize obstack for our rtl allocation. */
+ /* Initialize obstack for our rtl allocation. */
gcc_obstack_init (&reload_obstack);
reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+
+ /* Decide which register class should be used when reloading
+ addresses. If we are using SMALL_REGISTER_CLASSES, and any
+ parameters are passed in registers, then we do not want to use
+ those registers when reloading an address. Otherwise, if a
+ function argument needs a reload, we may wind up clobbering
+ another argument to the function which was already computed. If
+ we find a subset class which simply avoids those registers, we
+ use it instead. ??? It would be better to only use the
+ restricted class when we actually are loading function arguments,
+ but that is hard to determine. */
+ reload_address_base_reg_class = BASE_REG_CLASS;
+ reload_address_index_reg_class = INDEX_REG_CLASS;
+ if (SMALL_REGISTER_CLASSES)
+ {
+ int regno;
+ HARD_REG_SET base, index;
+ enum reg_class *p;
+
+ COPY_HARD_REG_SET (base, reg_class_contents[BASE_REG_CLASS]);
+ COPY_HARD_REG_SET (index, reg_class_contents[INDEX_REG_CLASS]);
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ {
+ if (FUNCTION_ARG_REGNO_P (regno))
+ {
+ CLEAR_HARD_REG_BIT (base, regno);
+ CLEAR_HARD_REG_BIT (index, regno);
+ }
+ }
+
+ GO_IF_HARD_REG_EQUAL (base, reg_class_contents[BASE_REG_CLASS],
+ baseok);
+ for (p = reg_class_subclasses[BASE_REG_CLASS];
+ *p != LIM_REG_CLASSES;
+ p++)
+ {
+ GO_IF_HARD_REG_EQUAL (base, reg_class_contents[*p], usebase);
+ continue;
+ usebase:
+ reload_address_base_reg_class = *p;
+ break;
+ }
+ baseok:;
+
+ GO_IF_HARD_REG_EQUAL (index, reg_class_contents[INDEX_REG_CLASS],
+ indexok);
+ for (p = reg_class_subclasses[INDEX_REG_CLASS];
+ *p != LIM_REG_CLASSES;
+ p++)
+ {
+ GO_IF_HARD_REG_EQUAL (index, reg_class_contents[*p], useindex);
+ continue;
+ useindex:
+ reload_address_index_reg_class = *p;
+ break;
+ }
+ indexok:;
+ }
}
/* Main entry point for the reload pass.
@@ -453,6 +544,11 @@ reload (first, global, dumpfile)
register rtx insn;
register struct elim_table *ep;
+ /* The two pointers used to track the true location of the memory used
+ for label offsets. */
+ char *real_known_ptr = NULL_PTR;
+ int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
+
int something_changed;
int something_needs_reloads;
int something_needs_elimination;
@@ -497,10 +593,18 @@ reload (first, global, dumpfile)
as homes for pseudo registers.
This is done here rather than (eg) in global_alloc
because this point is reached even if not optimizing. */
-
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
mark_home_live (i);
+ /* A function that receives a nonlocal goto must save all call-saved
+ registers. */
+ if (current_function_has_nonlocal_label)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (! call_used_regs[i] && ! fixed_regs[i])
+ regs_ever_live[i] = 1;
+ }
+
for (i = 0; i < scratch_list_length; i++)
if (scratch_list[i])
mark_scratch_live (scratch_list[i]);
@@ -534,19 +638,26 @@ reload (first, global, dumpfile)
cannot_omit_stores = (char *) alloca (max_regno);
bzero (cannot_omit_stores, max_regno);
-#ifdef SMALL_REGISTER_CLASSES
- CLEAR_HARD_REG_SET (forbidden_regs);
-#endif
+ if (SMALL_REGISTER_CLASSES)
+ CLEAR_HARD_REG_SET (forbidden_regs);
/* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
Also find all paradoxical subregs and find largest such for each pseudo.
On machines with small register classes, record hard registers that
- are used for user variables. These can never be used for spills. */
+ are used for user variables. These can never be used for spills.
+ Also look for a "constant" NOTE_INSN_SETJMP. This means that all
+ caller-saved registers must be marked live. */
for (insn = first; insn; insn = NEXT_INSN (insn))
{
rtx set = single_set (insn);
+ if (GET_CODE (insn) == NOTE && CONST_CALL_P (insn)
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (! call_used_regs[i])
+ regs_ever_live[i] = 1;
+
if (set != 0 && GET_CODE (SET_DEST (set)) == REG)
{
rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
@@ -562,7 +673,14 @@ reload (first, global, dumpfile)
if (i > LAST_VIRTUAL_REGISTER)
{
if (GET_CODE (x) == MEM)
- reg_equiv_memory_loc[i] = x;
+ {
+ /* If the operand is a PLUS, the MEM may be shared,
+ so make sure we have an unshared copy here. */
+ if (GET_CODE (XEXP (x, 0)) == PLUS)
+ x = copy_rtx (x);
+
+ reg_equiv_memory_loc[i] = x;
+ }
else if (CONSTANT_P (x))
{
if (LEGITIMATE_CONSTANT_P (x))
@@ -642,13 +760,17 @@ reload (first, global, dumpfile)
num_labels = max_label_num () - get_first_label_num ();
/* Allocate the tables used to store offset information at labels. */
- offsets_known_at = (char *) alloca (num_labels);
- offsets_at
+ /* We used to use alloca here, but the size of what it would try to
+ allocate would occasionally cause it to exceed the stack limit and
+ cause a core dump. */
+ real_known_ptr = xmalloc (num_labels);
+ real_at_ptr
= (int (*)[NUM_ELIMINABLE_REGS])
- alloca (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
+ xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
- offsets_known_at -= get_first_label_num ();
- offsets_at -= get_first_label_num ();
+ offsets_known_at = real_known_ptr - get_first_label_num ();
+ offsets_at
+ = (int (*)[NUM_ELIMINABLE_REGS]) (real_at_ptr - get_first_label_num ());
/* Alter each pseudo-reg rtx to contain its hard reg number.
Assign stack slots to the pseudos that lack hard regs or equivalents.
@@ -657,11 +779,6 @@ reload (first, global, dumpfile)
for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
alter_reg (i, -1);
- /* Round size of stack frame to BIGGEST_ALIGNMENT. This must be done here
- because the stack size may be a part of the offset computation for
- register elimination. */
- assign_stack_local (BLKmode, 0, 0);
-
/* If we have some registers we think can be eliminated, scan all insns to
see if there is an insn that sets one of these registers to something
other than itself plus a constant. If so, the register cannot be
@@ -681,17 +798,21 @@ reload (first, global, dumpfile)
in that case some pseudos might be in the wrong kind of hard reg. */
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
- if (reg_renumber[i] == -1 && reg_n_refs[i] != 0)
+ if (reg_renumber[i] == -1 && REG_N_REFS (i) != 0)
break;
if (i == max_regno && num_eliminable == 0 && ! caller_save_needed)
- return;
+ {
+ free (real_known_ptr);
+ free (real_at_ptr);
+ return;
+ }
#endif
/* Compute the order of preference for hard registers to spill.
Store them by decreasing preference in potential_reload_regs. */
- order_regs_for_reload ();
+ order_regs_for_reload (global);
/* So far, no hard regs have been spilled. */
n_spills = 0;
@@ -705,9 +826,8 @@ reload (first, global, dumpfile)
rtl as a spill register. But on some, we have to. Those will have
taken care to keep the life of hard regs as short as possible. */
-#ifndef SMALL_REGISTER_CLASSES
- COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);
-#endif
+ if (! SMALL_REGISTER_CLASSES)
+ COPY_HARD_REG_SET (forbidden_regs, bad_spill_regs);
/* Spill any hard regs that we know we can't eliminate. */
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
@@ -770,7 +890,7 @@ reload (first, global, dumpfile)
rtx max_groups_insn[N_REG_CLASSES];
rtx max_nongroups_insn[N_REG_CLASSES];
rtx x;
- int starting_frame_size = get_frame_size ();
+ HOST_WIDE_INT starting_frame_size;
int previous_frame_pointer_needed = frame_pointer_needed;
static char *reg_class_names[] = REG_CLASS_NAMES;
@@ -792,6 +912,14 @@ reload (first, global, dumpfile)
changes from 0 to 1 in this pass. */
new_basic_block_needs = 0;
+ /* Round size of stack frame to BIGGEST_ALIGNMENT. This must be done
+ here because the stack size may be a part of the offset computation
+ for register elimination, and there might have been new stack slots
+ created in the last iteration of this loop. */
+ assign_stack_local (BLKmode, 0, 0);
+
+ starting_frame_size = get_frame_size ();
+
/* Reset all offsets on eliminable registers to their initial values. */
#ifdef ELIMINABLE_REGS
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
@@ -852,7 +980,7 @@ reload (first, global, dumpfile)
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i])
{
- rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX);
+ rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX, 0);
if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]),
XEXP (x, 0)))
@@ -959,17 +1087,18 @@ reload (first, global, dumpfile)
struct needs op_addr;
struct needs op_addr_reload;
struct needs in_addr[MAX_RECOG_OPERANDS];
+ struct needs in_addr_addr[MAX_RECOG_OPERANDS];
struct needs out_addr[MAX_RECOG_OPERANDS];
+ struct needs out_addr_addr[MAX_RECOG_OPERANDS];
} insn_needs;
/* If needed, eliminate any eliminable registers. */
if (num_eliminable)
did_elimination = eliminate_regs_in_insn (insn, 0);
-#ifdef SMALL_REGISTER_CLASSES
/* Set avoid_return_reg if this is an insn
that might use the value of a function call. */
- if (GET_CODE (insn) == CALL_INSN)
+ if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
{
if (GET_CODE (PATTERN (insn)) == SET)
after_call = SET_DEST (PATTERN (insn));
@@ -979,7 +1108,7 @@ reload (first, global, dumpfile)
else
after_call = 0;
}
- else if (after_call != 0
+ else if (SMALL_REGISTER_CLASSES && after_call != 0
&& !(GET_CODE (PATTERN (insn)) == SET
&& SET_DEST (PATTERN (insn)) == stack_pointer_rtx))
{
@@ -987,7 +1116,6 @@ reload (first, global, dumpfile)
avoid_return_reg = after_call;
after_call = 0;
}
-#endif /* SMALL_REGISTER_CLASSES */
/* Analyze the instruction. */
find_reloads (insn, 0, spill_indirect_levels, global,
@@ -1066,7 +1194,6 @@ reload (first, global, dumpfile)
new_basic_block_needs = 1;
}
-
mode = reload_inmode[i];
if (GET_MODE_SIZE (reload_outmode[i]) > GET_MODE_SIZE (mode))
mode = reload_outmode[i];
@@ -1118,9 +1245,15 @@ reload (first, global, dumpfile)
case RELOAD_FOR_INPUT_ADDRESS:
this_needs = &insn_needs.in_addr[reload_opnum[i]];
break;
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ this_needs = &insn_needs.in_addr_addr[reload_opnum[i]];
+ break;
case RELOAD_FOR_OUTPUT_ADDRESS:
this_needs = &insn_needs.out_addr[reload_opnum[i]];
break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ this_needs = &insn_needs.out_addr_addr[reload_opnum[i]];
+ break;
case RELOAD_FOR_OPERAND_ADDRESS:
this_needs = &insn_needs.op_addr;
break;
@@ -1193,16 +1326,21 @@ reload (first, global, dumpfile)
k < reload_n_operands; k++)
{
in_max
- = MAX (in_max, insn_needs.in_addr[k].regs[j][i]);
+ = MAX (in_max,
+ (insn_needs.in_addr[k].regs[j][i]
+ + insn_needs.in_addr_addr[k].regs[j][i]));
out_max
= MAX (out_max, insn_needs.out_addr[k].regs[j][i]);
+ out_max
+ = MAX (out_max,
+ insn_needs.out_addr_addr[k].regs[j][i]);
}
/* RELOAD_FOR_INSN reloads conflict with inputs, outputs,
and operand addresses but not things used to reload
them. Similarly, RELOAD_FOR_OPERAND_ADDRESS reloads
don't conflict with things needed to reload inputs or
- outputs. */
+ outputs. */
in_max = MAX (MAX (insn_needs.op_addr.regs[j][i],
insn_needs.op_addr_reload.regs[j][i]),
@@ -1229,8 +1367,12 @@ reload (first, global, dumpfile)
j < reload_n_operands; j++)
{
in_max = MAX (in_max, insn_needs.in_addr[j].groups[i]);
+ in_max = MAX (in_max,
+ insn_needs.in_addr_addr[j].groups[i]);
out_max
= MAX (out_max, insn_needs.out_addr[j].groups[i]);
+ out_max
+ = MAX (out_max, insn_needs.out_addr_addr[j].groups[i]);
}
in_max = MAX (MAX (insn_needs.op_addr.groups[i],
@@ -1318,7 +1460,6 @@ reload (first, global, dumpfile)
}
}
-#ifdef SMALL_REGISTER_CLASSES
/* If this insn stores the value of a function call,
and that value is in a register that has been spilled,
and if the insn needs a reload in a class
@@ -1327,7 +1468,7 @@ reload (first, global, dumpfile)
This makes sure we have a register available that does
not overlap the return value. */
- if (avoid_return_reg)
+ if (SMALL_REGISTER_CLASSES && avoid_return_reg)
{
int regno = REGNO (avoid_return_reg);
int nregs
@@ -1360,7 +1501,7 @@ reload (first, global, dumpfile)
}
/* Now count extra regs if there might be a conflict with
- the return value register. */
+ the return value register. */
for (r = regno; r < regno + nregs; r++)
if (spill_reg_order[r] >= 0)
@@ -1387,7 +1528,6 @@ reload (first, global, dumpfile)
}
}
}
-#endif /* SMALL_REGISTER_CLASSES */
/* For each class, collect maximum need of any insn. */
@@ -1442,19 +1582,26 @@ reload (first, global, dumpfile)
/* If we have caller-saves, set up the save areas and see if caller-save
will need a spill register. */
- if (caller_save_needed
- && ! setup_save_areas (&something_changed)
- && caller_save_spill_class == NO_REGS)
+ if (caller_save_needed)
{
- /* The class we will need depends on whether the machine
- supports the sum of two registers for an address; see
- find_address_reloads for details. */
-
- caller_save_spill_class
- = double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS;
- caller_save_group_size
- = CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
- something_changed = 1;
+ /* Set the offsets for setup_save_areas. */
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
+ ep++)
+ ep->previous_offset = ep->max_offset;
+
+ if ( ! setup_save_areas (&something_changed)
+ && caller_save_spill_class == NO_REGS)
+ {
+ /* The class we will need depends on whether the machine
+ supports the sum of two registers for an address; see
+ find_address_reloads for details. */
+
+ caller_save_spill_class
+ = double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS;
+ caller_save_group_size
+ = CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
+ something_changed = 1;
+ }
}
/* See if anything that happened changes which eliminations are valid.
@@ -1676,9 +1823,8 @@ reload (first, global, dumpfile)
}
}
/* We can't complete a group, so start one. */
-#ifdef SMALL_REGISTER_CLASSES
/* Look for a pair neither of which is explicitly used. */
- if (i == FIRST_PSEUDO_REGISTER)
+ if (SMALL_REGISTER_CLASSES && i == FIRST_PSEUDO_REGISTER)
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
int k;
@@ -1701,7 +1847,6 @@ reload (first, global, dumpfile)
&& ! regs_explicitly_used[j + 1])
break;
}
-#endif
/* Now try any group at all
whose registers are not in bad_spill_regs. */
if (i == FIRST_PSEUDO_REGISTER)
@@ -1808,10 +1953,6 @@ reload (first, global, dumpfile)
while (max_needs[class] > 0 || max_nongroups[class] > 0)
{
-#ifdef SMALL_REGISTER_CLASSES
- /* This should be right for all machines, but only the 386
- is known to need it, so this conditional plays safe.
- ??? For 2.5, try making this unconditional. */
/* If we spilled enough regs, but they weren't counted
against the non-group need, see if we can count them now.
If so, we can avoid some actual spilling. */
@@ -1835,7 +1976,6 @@ reload (first, global, dumpfile)
}
if (max_needs[class] <= 0 && max_nongroups[class] <= 0)
break;
-#endif
/* Consider the potential reload regs that aren't
yet in use as reload regs, in order of preference.
@@ -1945,9 +2085,8 @@ reload (first, global, dumpfile)
if (! frame_pointer_needed)
for (i = 0; i < n_basic_blocks; i++)
- basic_block_live_at_start[i][HARD_FRAME_POINTER_REGNUM / REGSET_ELT_BITS]
- &= ~ ((REGSET_ELT_TYPE) 1 << (HARD_FRAME_POINTER_REGNUM
- % REGSET_ELT_BITS));
+ CLEAR_REGNO_REG_SET (basic_block_live_at_start[i],
+ HARD_FRAME_POINTER_REGNUM);
/* Come here (with failure set nonzero) if we can't get enough spill regs
and we decide not to abort about it. */
@@ -2012,10 +2151,29 @@ reload (first, global, dumpfile)
}
#endif
+ /* If we are doing stack checking, give a warning if this function's
+ frame size is larger than we expect. */
+ if (flag_stack_check && ! STACK_CHECK_BUILTIN)
+ {
+ HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (regs_ever_live[i] && ! fixed_regs[i] && call_used_regs[i])
+ size += UNITS_PER_WORD;
+
+ if (size > STACK_CHECK_MAX_FRAME_SIZE)
+ warning ("frame size too large for reliable stack checking");
+ }
+
/* Indicate that we no longer have known memory locations or constants. */
reg_equiv_constant = 0;
reg_equiv_memory_loc = 0;
+ if (real_known_ptr)
+ free (real_known_ptr);
+ if (real_at_ptr)
+ free (real_at_ptr);
+
if (scratch_list)
free (scratch_list);
scratch_list = 0;
@@ -2023,6 +2181,10 @@ reload (first, global, dumpfile)
free (scratch_block);
scratch_block = 0;
+ CLEAR_HARD_REG_SET (used_spill_regs);
+ for (i = 0; i < n_spills; i++)
+ SET_HARD_REG_BIT (used_spill_regs, spill_regs[i]);
+
return failure;
}
@@ -2329,7 +2491,7 @@ alter_reg (i, from_reg)
allocate a stack slot for it. */
if (reg_renumber[i] < 0
- && reg_n_refs[i] > 0
+ && REG_N_REFS (i) > 0
&& reg_equiv_constant[i] == 0
&& reg_equiv_memory_loc[i] == 0)
{
@@ -2349,7 +2511,8 @@ alter_reg (i, from_reg)
if (from_reg == -1)
{
/* No known place to spill from => no slot to reuse. */
- x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size, -1);
+ x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size,
+ inherent_size == total_size ? 0 : -1);
if (BYTES_BIG_ENDIAN)
/* Cancel the big-endian correction done in assign_stack_local.
Get the address of the beginning of the slot.
@@ -2381,7 +2544,8 @@ alter_reg (i, from_reg)
total_size = spill_stack_slot_width[from_reg];
}
/* Make a slot with that size. */
- x = assign_stack_local (mode, total_size, -1);
+ x = assign_stack_local (mode, total_size,
+ inherent_size == total_size ? 0 : -1);
stack_slot = x;
if (BYTES_BIG_ENDIAN)
{
@@ -2478,7 +2642,7 @@ set_label_offsets (x, insn, initial_p)
x = XEXP (x, 0);
- /* ... fall through ... */
+ /* ... fall through ... */
case CODE_LABEL:
/* If we know nothing about this label, set the desired offsets. Note
@@ -2533,7 +2697,7 @@ set_label_offsets (x, insn, initial_p)
case JUMP_INSN:
set_label_offsets (PATTERN (insn), insn, initial_p);
- /* ... fall through ... */
+ /* ... fall through ... */
case INSN:
case CALL_INSN:
@@ -2594,6 +2758,9 @@ set_label_offsets (x, insn, initial_p)
else if (GET_CODE (tem) != PC && GET_CODE (tem) != RETURN)
break;
return;
+
+ default:
+ break;
}
/* If we reach here, all eliminations must be at their initial
@@ -2601,6 +2768,10 @@ set_label_offsets (x, insn, initial_p)
for (p = reg_eliminate; p < &reg_eliminate[NUM_ELIMINABLE_REGS]; p++)
if (p->offset != p->initial_offset)
p->can_eliminate = 0;
+ break;
+
+ default:
+ break;
}
}
@@ -2638,10 +2809,11 @@ static struct rtvec_def *old_asm_operands_vec, *new_asm_operands_vec;
the proper thing. */
rtx
-eliminate_regs (x, mem_mode, insn)
+eliminate_regs (x, mem_mode, insn, storing)
rtx x;
enum machine_mode mem_mode;
rtx insn;
+ int storing;
{
enum rtx_code code = GET_CODE (x);
struct elim_table *ep;
@@ -2666,6 +2838,15 @@ eliminate_regs (x, mem_mode, insn)
case RETURN:
return x;
+ case ADDRESSOF:
+ /* This is only for the benefit of the debugging backends, which call
+ eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are
+ removed after CSE. */
+ new = eliminate_regs (XEXP (x, 0), 0, insn, 0);
+ if (GET_CODE (new) == MEM)
+ return XEXP (new, 0);
+ return x;
+
case REG:
regno = REGNO (x);
@@ -2698,7 +2879,7 @@ eliminate_regs (x, mem_mode, insn)
reference to the pseudo. Ensure we make a copy of the
address in case it is shared. */
new = eliminate_regs (reg_equiv_memory_loc[regno],
- mem_mode, insn);
+ mem_mode, insn, 0);
if (new != reg_equiv_memory_loc[regno])
{
cannot_omit_stores[regno] = 1;
@@ -2760,8 +2941,8 @@ eliminate_regs (x, mem_mode, insn)
reload. This is the desired action. */
{
- rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn);
- rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn);
+ rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
+ rtx new1 = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0);
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
{
@@ -2818,7 +2999,7 @@ eliminate_regs (x, mem_mode, insn)
ep->previous_offset * INTVAL (XEXP (x, 1)));
}
- /* ... fall through ... */
+ /* ... fall through ... */
case CALL:
case COMPARE:
@@ -2832,9 +3013,9 @@ eliminate_regs (x, mem_mode, insn)
case GE: case GT: case GEU: case GTU:
case LE: case LT: case LEU: case LTU:
{
- rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ rtx new0 = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
rtx new1
- = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn) : 0;
+ = XEXP (x, 1) ? eliminate_regs (XEXP (x, 1), mem_mode, insn, 0) : 0;
if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
return gen_rtx (code, GET_MODE (x), new0, new1);
@@ -2845,12 +3026,12 @@ eliminate_regs (x, mem_mode, insn)
/* If we have something in XEXP (x, 0), the usual case, eliminate it. */
if (XEXP (x, 0))
{
- new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
if (new != XEXP (x, 0))
x = gen_rtx (EXPR_LIST, REG_NOTE_KIND (x), new, XEXP (x, 1));
}
- /* ... fall through ... */
+ /* ... fall through ... */
case INSN_LIST:
/* Now do eliminations in the rest of the chain. If this was
@@ -2858,7 +3039,7 @@ eliminate_regs (x, mem_mode, insn)
strictly needed, but it simplifies the code. */
if (XEXP (x, 1))
{
- new = eliminate_regs (XEXP (x, 1), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 1), mem_mode, insn, 0);
if (new != XEXP (x, 1))
return gen_rtx (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new);
}
@@ -2885,7 +3066,6 @@ eliminate_regs (x, mem_mode, insn)
}
/* Fall through to generic unary operation case. */
- case USE:
case STRICT_LOW_PART:
case NEG: case NOT:
case SIGN_EXTEND: case ZERO_EXTEND:
@@ -2895,7 +3075,7 @@ eliminate_regs (x, mem_mode, insn)
case ABS:
case SQRT:
case FFS:
- new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
if (new != XEXP (x, 0))
return gen_rtx (code, GET_MODE (x), new);
return x;
@@ -2914,7 +3094,7 @@ eliminate_regs (x, mem_mode, insn)
&& reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
{
new = eliminate_regs (reg_equiv_memory_loc[REGNO (SUBREG_REG (x))],
- mem_mode, insn);
+ mem_mode, insn, 0);
/* If we didn't change anything, we must retain the pseudo. */
if (new == reg_equiv_memory_loc[REGNO (SUBREG_REG (x))])
@@ -2934,27 +3114,37 @@ eliminate_regs (x, mem_mode, insn)
}
}
else
- new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
+ new = eliminate_regs (SUBREG_REG (x), mem_mode, insn, 0);
if (new != XEXP (x, 0))
{
- if (GET_CODE (new) == MEM
- && (GET_MODE_SIZE (GET_MODE (x))
- <= GET_MODE_SIZE (GET_MODE (new)))
+ int x_size = GET_MODE_SIZE (GET_MODE (x));
+ int new_size = GET_MODE_SIZE (GET_MODE (new));
+
+ /* When asked to spill a partial word subreg, we need to go
+ ahead and spill the whole thing against the possibility
+ that we reload the whole reg and find garbage at the top. */
+ if (storing
+ && GET_CODE (new) == MEM
+ && x_size < new_size
+ && ((x_size + UNITS_PER_WORD-1) / UNITS_PER_WORD
+ == (new_size + UNITS_PER_WORD-1) / UNITS_PER_WORD))
+ return new;
+ else if (GET_CODE (new) == MEM
+ && x_size <= new_size
#ifdef LOAD_EXTEND_OP
- /* On these machines we will be reloading what is
- inside the SUBREG if it originally was a pseudo and
- the inner and outer modes are both a word or
- smaller. So leave the SUBREG then. */
- && ! (GET_CODE (SUBREG_REG (x)) == REG
- && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
- && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (new)))
- && INTEGRAL_MODE_P (GET_MODE (new))
- && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
+ /* On these machines we will be reloading what is
+ inside the SUBREG if it originally was a pseudo and
+ the inner and outer modes are both a word or
+ smaller. So leave the SUBREG then. */
+ && ! (GET_CODE (SUBREG_REG (x)) == REG
+ && x_size <= UNITS_PER_WORD
+ && new_size <= UNITS_PER_WORD
+ && x_size > new_size
+ && INTEGRAL_MODE_P (GET_MODE (new))
+ && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
#endif
- )
+ )
{
int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
enum machine_mode mode = GET_MODE (x);
@@ -2974,6 +3164,19 @@ eliminate_regs (x, mem_mode, insn)
return x;
+ case USE:
+ /* If using a register that is the source of an eliminate we still
+ think can be performed, note it cannot be performed since we don't
+ know how this register is used. */
+ for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (ep->from_rtx == XEXP (x, 0))
+ ep->can_eliminate = 0;
+
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
+ if (new != XEXP (x, 0))
+ return gen_rtx (code, GET_MODE (x), new);
+ return x;
+
case CLOBBER:
/* If clobbering a register that is the replacement register for an
elimination we still think can be performed, note that it cannot
@@ -2982,7 +3185,7 @@ eliminate_regs (x, mem_mode, insn)
if (ep->to_rtx == XEXP (x, 0))
ep->can_eliminate = 0;
- new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, 0), mem_mode, insn, 0);
if (new != XEXP (x, 0))
return gen_rtx (code, GET_MODE (x), new);
return x;
@@ -3000,7 +3203,7 @@ eliminate_regs (x, mem_mode, insn)
temp_vec = (rtx *) alloca (XVECLEN (x, 3) * sizeof (rtx));
for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
temp_vec[i] = eliminate_regs (ASM_OPERANDS_INPUT (x, i),
- mem_mode, insn);
+ mem_mode, insn, 0);
for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
if (temp_vec[i] != ASM_OPERANDS_INPUT (x, i))
@@ -3071,8 +3274,8 @@ eliminate_regs (x, mem_mode, insn)
/* Now avoid the loop below in this common case. */
{
- rtx new0 = eliminate_regs (SET_DEST (x), 0, insn);
- rtx new1 = eliminate_regs (SET_SRC (x), 0, insn);
+ rtx new0 = eliminate_regs (SET_DEST (x), 0, insn, 1);
+ rtx new1 = eliminate_regs (SET_SRC (x), 0, insn, 0);
/* If SET_DEST changed from a REG to a MEM and INSN is an insn,
write a CLOBBER insn. */
@@ -3088,10 +3291,16 @@ eliminate_regs (x, mem_mode, insn)
return x;
case MEM:
+ /* This is only for the benefit of the debugging backends, which call
+ eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are
+ removed after CSE. */
+ if (GET_CODE (XEXP (x, 0)) == ADDRESSOF)
+ return eliminate_regs (XEXP (XEXP (x, 0), 0), 0, insn, 0);
+
/* Our only special processing is to pass the mode of the MEM to our
recursive call and copy the flags. While we are here, handle this
case more efficiently. */
- new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn);
+ new = eliminate_regs (XEXP (x, 0), GET_MODE (x), insn, 0);
if (new != XEXP (x, 0))
{
new = gen_rtx (MEM, GET_MODE (x), new);
@@ -3102,6 +3311,9 @@ eliminate_regs (x, mem_mode, insn)
}
else
return x;
+
+ default:
+ break;
}
/* Process each of our operands recursively. If any have changed, make a
@@ -3111,7 +3323,7 @@ eliminate_regs (x, mem_mode, insn)
{
if (*fmt == 'e')
{
- new = eliminate_regs (XEXP (x, i), mem_mode, insn);
+ new = eliminate_regs (XEXP (x, i), mem_mode, insn, 0);
if (new != XEXP (x, i) && ! copied)
{
rtx new_x = rtx_alloc (code);
@@ -3128,11 +3340,11 @@ eliminate_regs (x, mem_mode, insn)
int copied_vec = 0;
for (j = 0; j < XVECLEN (x, i); j++)
{
- new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn);
+ new = eliminate_regs (XVECEXP (x, i, j), mem_mode, insn, 0);
if (new != XVECEXP (x, i, j) && ! copied_vec)
{
- rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
- &XVECEXP (x, i, 0));
+ rtvec new_v = gen_rtvec_vv (XVECLEN (x, i),
+ XVEC (x, i)->elem);
if (! copied)
{
rtx new_x = rtx_alloc (code);
@@ -3199,12 +3411,29 @@ eliminate_regs_in_insn (insn, replace)
{
rtx src = SET_SRC (old_set);
int offset, ok = 0;
+ rtx prev_insn, prev_set;
if (src == ep->to_rtx)
offset = 0, ok = 1;
else if (GET_CODE (src) == PLUS
&& GET_CODE (XEXP (src, 0)) == CONST_INT)
offset = INTVAL (XEXP (src, 0)), ok = 1;
+ else if ((prev_insn = prev_nonnote_insn (insn)) != 0
+ && (prev_set = single_set (prev_insn)) != 0
+ && rtx_equal_p (SET_DEST (prev_set), src))
+ {
+ src = SET_SRC (prev_set);
+ if (src == ep->to_rtx)
+ offset = 0, ok = 1;
+ else if (GET_CODE (src) == PLUS
+ && GET_CODE (XEXP (src, 0)) == CONST_INT
+ && XEXP (src, 1) == ep->to_rtx)
+ offset = INTVAL (XEXP (src, 0)), ok = 1;
+ else if (GET_CODE (src) == PLUS
+ && GET_CODE (XEXP (src, 1)) == CONST_INT
+ && XEXP (src, 0) == ep->to_rtx)
+ offset = INTVAL (XEXP (src, 1)), ok = 1;
+ }
if (ok)
{
@@ -3287,15 +3516,15 @@ eliminate_regs_in_insn (insn, replace)
If we are replacing a body that was a (set X (plus Y Z)), try to
re-recognize the insn. We do this in case we had a simple addition
but now can do this as a load-address. This saves an insn in this
- common case. */
+ common case. */
- new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX);
+ new_body = eliminate_regs (old_body, 0, replace ? insn : NULL_RTX, 0);
if (new_body != old_body)
{
/* If we aren't replacing things permanently and we changed something,
make another copy to ensure that all the RTL is new. Otherwise
things can go wrong if find_reload swaps commutative operands
- and one is inside RTL that has been copied while the other is not. */
+ and one is inside RTL that has been copied while the other is not. */
/* Don't copy an asm_operands because (1) there's no need and (2)
copy_rtx can't do it properly when there are multiple outputs. */
@@ -3378,7 +3607,7 @@ eliminate_regs_in_insn (insn, replace)
of spill registers to be needed in the final reload pass than in
the pre-passes. */
if (val && REG_NOTES (insn) != 0)
- REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn));
+ REG_NOTES (insn) = eliminate_regs (REG_NOTES (insn), 0, REG_NOTES (insn), 0);
if (! replace)
pop_obstacks ();
@@ -3475,14 +3704,14 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
if (! cant_eliminate
&& basic_block_needs[0]
- && reg_basic_block[i] >= 0
- && basic_block_needs[(int) class][reg_basic_block[i]] == 0)
+ && REG_BASIC_BLOCK (i) >= 0
+ && basic_block_needs[(int) class][REG_BASIC_BLOCK (i)] == 0)
{
enum reg_class *p;
for (p = reg_class_superclasses[(int) class];
*p != LIM_REG_CLASSES; p++)
- if (basic_block_needs[(int) *p][reg_basic_block[i]] > 0)
+ if (basic_block_needs[(int) *p][REG_BASIC_BLOCK (i)] > 0)
break;
if (*p == LIM_REG_CLASSES)
@@ -3494,7 +3723,7 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
/* We will need to scan everything again. */
something_changed = 1;
if (global)
- retry_global_alloc (i, forbidden_regs);
+ retry_global_alloc (i, forbidden_regs);
alter_reg (i, regno);
if (dumpfile)
@@ -3548,10 +3777,9 @@ scan_paradoxical_subregs (x)
switch (code)
{
case REG:
-#ifdef SMALL_REGISTER_CLASSES
- if (REGNO (x) < FIRST_PSEUDO_REGISTER && REG_USERVAR_P (x))
+ if (SMALL_REGISTER_CLASSES && REGNO (x) < FIRST_PSEUDO_REGISTER
+ && REG_USERVAR_P (x))
SET_HARD_REG_BIT (forbidden_regs, REGNO (x));
-#endif
return;
case CONST_INT:
@@ -3571,6 +3799,9 @@ scan_paradoxical_subregs (x)
reg_max_ref_width[REGNO (SUBREG_REG (x))]
= GET_MODE_SIZE (GET_MODE (x));
return;
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -3588,9 +3819,12 @@ scan_paradoxical_subregs (x)
}
static int
-hard_reg_use_compare (p1, p2)
- struct hard_reg_n_uses *p1, *p2;
+hard_reg_use_compare (p1p, p2p)
+ const GENERIC_PTR p1p;
+ const GENERIC_PTR p2p;
{
+ struct hard_reg_n_uses *p1 = (struct hard_reg_n_uses *)p1p,
+ *p2 = (struct hard_reg_n_uses *)p2p;
int tem = p1->uses - p2->uses;
if (tem != 0) return tem;
/* If regs are equally good, sort by regno,
@@ -3603,7 +3837,8 @@ hard_reg_use_compare (p1, p2)
Store them in order of decreasing preference in potential_reload_regs. */
static void
-order_regs_for_reload ()
+order_regs_for_reload (global)
+ int global;
{
register int i;
register int o = 0;
@@ -3632,9 +3867,17 @@ order_regs_for_reload ()
{
int lim = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
while (regno < lim)
- hard_reg_n_uses[regno++].uses += reg_n_refs[i];
+ {
+ /* If allocated by local-alloc, show more uses since
+ we're not going to be able to reallocate it, but
+ we might if allocated by global alloc. */
+ if (global && reg_allocno[i] < 0)
+ hard_reg_n_uses[regno].uses += (REG_N_REFS (i) + 1) / 2;
+
+ hard_reg_n_uses[regno++].uses += REG_N_REFS (i);
+ }
}
- large += reg_n_refs[i];
+ large += REG_N_REFS (i);
}
/* Now fixed registers (which cannot safely be used for reloading)
@@ -3651,14 +3894,13 @@ order_regs_for_reload ()
else if (regs_explicitly_used[i])
{
hard_reg_n_uses[i].uses += large + 1;
-#ifndef SMALL_REGISTER_CLASSES
- /* ??? We are doing this here because of the potential that
- bad code may be generated if a register explicitly used in
- an insn was used as a spill register for that insn. But
- not using these are spill registers may lose on some machine.
- We'll have to see how this works out. */
- SET_HARD_REG_BIT (bad_spill_regs, i);
-#endif
+ if (! SMALL_REGISTER_CLASSES)
+ /* ??? We are doing this here because of the potential
+ that bad code may be generated if a register explicitly
+ used in an insn was used as a spill register for that
+ insn. But not using these are spill registers may lose
+ on some machine. We'll have to see how this works out. */
+ SET_HARD_REG_BIT (bad_spill_regs, i);
}
}
hard_reg_n_uses[HARD_FRAME_POINTER_REGNUM].uses += 2 * large + 2;
@@ -3714,10 +3956,12 @@ order_regs_for_reload ()
/* Used in reload_as_needed to sort the spilled regs. */
static int
-compare_spill_regs (r1, r2)
- short *r1, *r2;
+compare_spill_regs (r1p, r2p)
+ const GENERIC_PTR r1p;
+ const GENERIC_PTR r2p;
{
- return *r1 - *r2;
+ short r1 = *(short *)r1p, r2 = *(short *)r2p;
+ return r1 - r2;
}
/* Reload pseudo-registers into hard regs around each insn as needed.
@@ -3807,10 +4051,9 @@ reload_as_needed (first, live_known)
rtx avoid_return_reg = 0;
rtx oldpat = PATTERN (insn);
-#ifdef SMALL_REGISTER_CLASSES
/* Set avoid_return_reg if this is an insn
that might use the value of a function call. */
- if (GET_CODE (insn) == CALL_INSN)
+ if (SMALL_REGISTER_CLASSES && GET_CODE (insn) == CALL_INSN)
{
if (GET_CODE (PATTERN (insn)) == SET)
after_call = SET_DEST (PATTERN (insn));
@@ -3820,7 +4063,7 @@ reload_as_needed (first, live_known)
else
after_call = 0;
}
- else if (after_call != 0
+ else if (SMALL_REGISTER_CLASSES && after_call != 0
&& !(GET_CODE (PATTERN (insn)) == SET
&& SET_DEST (PATTERN (insn)) == stack_pointer_rtx))
{
@@ -3828,7 +4071,6 @@ reload_as_needed (first, live_known)
avoid_return_reg = after_call;
after_call = 0;
}
-#endif /* SMALL_REGISTER_CLASSES */
/* If this is a USE and CLOBBER of a MEM, ensure that any
references to eliminable registers have been removed. */
@@ -3838,7 +4080,8 @@ reload_as_needed (first, live_known)
&& GET_CODE (XEXP (PATTERN (insn), 0)) == MEM)
XEXP (XEXP (PATTERN (insn), 0), 0)
= eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0),
- GET_MODE (XEXP (PATTERN (insn), 0)), NULL_RTX);
+ GET_MODE (XEXP (PATTERN (insn), 0)),
+ NULL_RTX, 0);
/* If we need to do register elimination processing, do so.
This might delete the insn, in which case we are done. */
@@ -3894,12 +4137,11 @@ reload_as_needed (first, live_known)
Record the choices of reload reg in reload_reg_rtx. */
choose_reload_regs (insn, avoid_return_reg);
-#ifdef SMALL_REGISTER_CLASSES
/* Merge any reloads that we didn't combine for fear of
increasing the number of spill registers needed but now
discover can be safely merged. */
- merge_assigned_reloads (insn);
-#endif
+ if (SMALL_REGISTER_CLASSES)
+ merge_assigned_reloads (insn);
/* Generate the insns to reload operands into or out of
their reload regs. */
@@ -4070,10 +4312,11 @@ static int reload_nregs[MAX_RELOADS];
should be handled first. *P1 and *P2 are the reload numbers. */
static int
-reload_reg_class_lower (p1, p2)
- short *p1, *p2;
+reload_reg_class_lower (r1p, r2p)
+ const GENERIC_PTR r1p;
+ const GENERIC_PTR r2p;
{
- register int r1 = *p1, r2 = *p2;
+ register int r1 = *(short *)r1p, r2 = *(short *)r2p;
register int t;
/* Consider required reloads before optional ones. */
@@ -4109,8 +4352,12 @@ reload_reg_class_lower (p1, p2)
static HARD_REG_SET reload_reg_used;
/* If reg is in use for a RELOAD_FOR_INPUT_ADDRESS reload for operand I. */
static HARD_REG_SET reload_reg_used_in_input_addr[MAX_RECOG_OPERANDS];
+/* If reg is in use for a RELOAD_FOR_INPADDR_ADDRESS reload for operand I. */
+static HARD_REG_SET reload_reg_used_in_inpaddr_addr[MAX_RECOG_OPERANDS];
/* If reg is in use for a RELOAD_FOR_OUTPUT_ADDRESS reload for operand I. */
static HARD_REG_SET reload_reg_used_in_output_addr[MAX_RECOG_OPERANDS];
+/* If reg is in use for a RELOAD_FOR_OUTADDR_ADDRESS reload for operand I. */
+static HARD_REG_SET reload_reg_used_in_outaddr_addr[MAX_RECOG_OPERANDS];
/* If reg is in use for a RELOAD_FOR_INPUT reload for operand I. */
static HARD_REG_SET reload_reg_used_in_input[MAX_RECOG_OPERANDS];
/* If reg is in use for a RELOAD_FOR_OUTPUT reload for operand I. */
@@ -4157,10 +4404,18 @@ mark_reload_reg_in_use (regno, opnum, type, mode)
SET_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], i);
break;
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ SET_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], i);
+ break;
+
case RELOAD_FOR_OUTPUT_ADDRESS:
SET_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], i);
break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ SET_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], i);
+ break;
+
case RELOAD_FOR_OPERAND_ADDRESS:
SET_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
break;
@@ -4214,10 +4469,18 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
CLEAR_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], i);
break;
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ CLEAR_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], i);
+ break;
+
case RELOAD_FOR_OUTPUT_ADDRESS:
CLEAR_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], i);
break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ CLEAR_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], i);
+ break;
+
case RELOAD_FOR_OPERAND_ADDRESS:
CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
break;
@@ -4256,27 +4519,24 @@ reload_reg_free_p (regno, opnum, type)
{
int i;
- /* In use for a RELOAD_OTHER means it's not available for anything except
- RELOAD_FOR_OTHER_ADDRESS. Recall that RELOAD_FOR_OTHER_ADDRESS is known
- to be used only for inputs. */
-
- if (type != RELOAD_FOR_OTHER_ADDRESS
- && TEST_HARD_REG_BIT (reload_reg_used, regno))
+ /* In use for a RELOAD_OTHER means it's not available for anything. */
+ if (TEST_HARD_REG_BIT (reload_reg_used, regno))
return 0;
switch (type)
{
case RELOAD_OTHER:
- /* In use for anything except RELOAD_FOR_OTHER_ADDRESS means
- we can't use it for RELOAD_OTHER. */
- if (TEST_HARD_REG_BIT (reload_reg_used, regno)
+ /* In use for anything means we can't use it for RELOAD_OTHER. */
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno))
return 0;
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
return 0;
@@ -4298,7 +4558,8 @@ reload_reg_free_p (regno, opnum, type)
/* If it is used in a later operand's address, can't use it. */
for (i = opnum + 1; i < reload_n_operands; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
return 0;
return 1;
@@ -4306,7 +4567,21 @@ reload_reg_free_p (regno, opnum, type)
case RELOAD_FOR_INPUT_ADDRESS:
/* Can't use a register if it is used for an input address for this
operand or used as an input in an earlier one. */
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], regno))
+ return 0;
+
+ for (i = 0; i < opnum; i++)
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
+ return 0;
+
+ return 1;
+
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ /* Can't use a register if it is used for an input address
+ address for this operand or used as an input in an earlier
+ one. */
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], regno))
return 0;
for (i = 0; i < opnum; i++)
@@ -4327,6 +4602,19 @@ reload_reg_free_p (regno, opnum, type)
return 1;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ /* Can't use a register if it is used for an output address
+ address for this operand or used as an output in this or a
+ later operand. */
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
+ return 0;
+
+ for (i = opnum; i < reload_n_operands; i++)
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
+ return 0;
+
+ return 1;
+
case RELOAD_FOR_OPERAND_ADDRESS:
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
@@ -4353,7 +4641,8 @@ reload_reg_free_p (regno, opnum, type)
return 0;
for (i = 0; i <= opnum; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno))
return 0;
return 1;
@@ -4407,12 +4696,14 @@ reload_reg_free_before_p (regno, opnum, type)
the first place, since we know that it was allocated. */
case RELOAD_FOR_OUTPUT_ADDRESS:
+ case RELOAD_FOR_OUTADDR_ADDRESS:
/* Earlier reloads are for earlier outputs or their addresses,
any RELOAD_FOR_INSN reloads, any inputs or their addresses, or any
RELOAD_FOR_OTHER_ADDRESS reloads (we know it can't conflict with
RELOAD_OTHER).. */
for (i = 0; i < opnum; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
return 0;
@@ -4421,6 +4712,7 @@ reload_reg_free_before_p (regno, opnum, type)
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
return 0;
@@ -4433,16 +4725,19 @@ reload_reg_free_before_p (regno, opnum, type)
anything that can't be used for it, except that we've already
tested for RELOAD_FOR_INSN objects. */
- if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
return 0;
for (i = 0; i < opnum; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
return 0;
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno))
return 0;
@@ -4450,13 +4745,20 @@ reload_reg_free_before_p (regno, opnum, type)
return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
case RELOAD_FOR_OPERAND_ADDRESS:
+ /* Earlier reloads include RELOAD_FOR_OPADDR_ADDR reloads. */
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno))
+ return 0;
+
+ /* ... fall through ... */
+
case RELOAD_FOR_OPADDR_ADDR:
case RELOAD_FOR_INSN:
/* These can't conflict with inputs, or each other, so all we have to
test is input addresses and the addresses of OTHER items. */
for (i = 0; i < reload_n_operands; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
return 0;
return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
@@ -4467,16 +4769,19 @@ reload_reg_free_before_p (regno, opnum, type)
with), and addresses of RELOAD_OTHER objects. */
for (i = 0; i <= opnum; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
return 0;
return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
case RELOAD_FOR_INPUT_ADDRESS:
+ case RELOAD_FOR_INPADDR_ADDRESS:
/* Similarly, all we have to check is for use in earlier inputs'
addresses. */
for (i = 0; i < opnum; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
return 0;
return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
@@ -4518,8 +4823,10 @@ reload_reg_reaches_end_p (regno, opnum, type)
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
return 0;
@@ -4528,6 +4835,7 @@ reload_reg_reaches_end_p (regno, opnum, type)
&& ! TEST_HARD_REG_BIT (reload_reg_used, regno));
case RELOAD_FOR_INPUT_ADDRESS:
+ case RELOAD_FOR_INPADDR_ADDRESS:
/* Similar, except that we check only for this and subsequent inputs
and the address of only subsequent inputs and we do not need
to check for RELOAD_OTHER objects since they are known not to
@@ -4538,11 +4846,13 @@ reload_reg_reaches_end_p (regno, opnum, type)
return 0;
for (i = opnum + 1; i < reload_n_operands; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
return 0;
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
return 0;
@@ -4560,16 +4870,18 @@ reload_reg_reaches_end_p (regno, opnum, type)
for (i = opnum + 1; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
return 0;
- /* ... fall through ... */
+ /* ... fall through ... */
case RELOAD_FOR_OPERAND_ADDRESS:
/* Check outputs and their addresses. */
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
return 0;
@@ -4578,6 +4890,7 @@ reload_reg_reaches_end_p (regno, opnum, type)
case RELOAD_FOR_OPADDR_ADDR:
for (i = 0; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_output[i], regno))
return 0;
@@ -4590,14 +4903,16 @@ reload_reg_reaches_end_p (regno, opnum, type)
opnum = -1;
- /* ... fall through ... */
+ /* ... fall through ... */
case RELOAD_FOR_OUTPUT:
case RELOAD_FOR_OUTPUT_ADDRESS:
+ case RELOAD_FOR_OUTADDR_ADDRESS:
/* We already know these can't conflict with a later output. So the
only thing to check are later output addresses. */
for (i = opnum + 1; i < reload_n_operands; i++)
- if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno))
+ if (TEST_HARD_REG_BIT (reload_reg_used_in_output_addr[i], regno)
+ || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno))
return 0;
return 1;
@@ -4620,9 +4935,8 @@ reloads_conflict (r1, r2)
int r1_opnum = reload_opnum[r1];
int r2_opnum = reload_opnum[r2];
- /* RELOAD_OTHER conflicts with everything except RELOAD_FOR_OTHER_ADDRESS. */
-
- if (r2_type == RELOAD_OTHER && r1_type != RELOAD_FOR_OTHER_ADDRESS)
+ /* RELOAD_OTHER conflicts with everything. */
+ if (r2_type == RELOAD_OTHER)
return 1;
/* Otherwise, check conflicts differently for each type. */
@@ -4634,16 +4948,26 @@ reloads_conflict (r1, r2)
|| r2_type == RELOAD_FOR_OPERAND_ADDRESS
|| r2_type == RELOAD_FOR_OPADDR_ADDR
|| r2_type == RELOAD_FOR_INPUT
- || (r2_type == RELOAD_FOR_INPUT_ADDRESS && r2_opnum > r1_opnum));
+ || ((r2_type == RELOAD_FOR_INPUT_ADDRESS
+ || r2_type == RELOAD_FOR_INPADDR_ADDRESS)
+ && r2_opnum > r1_opnum));
case RELOAD_FOR_INPUT_ADDRESS:
return ((r2_type == RELOAD_FOR_INPUT_ADDRESS && r1_opnum == r2_opnum)
|| (r2_type == RELOAD_FOR_INPUT && r2_opnum < r1_opnum));
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ return ((r2_type == RELOAD_FOR_INPADDR_ADDRESS && r1_opnum == r2_opnum)
+ || (r2_type == RELOAD_FOR_INPUT && r2_opnum < r1_opnum));
+
case RELOAD_FOR_OUTPUT_ADDRESS:
return ((r2_type == RELOAD_FOR_OUTPUT_ADDRESS && r2_opnum == r1_opnum)
|| (r2_type == RELOAD_FOR_OUTPUT && r2_opnum >= r1_opnum));
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ return ((r2_type == RELOAD_FOR_OUTADDR_ADDRESS && r2_opnum == r1_opnum)
+ || (r2_type == RELOAD_FOR_OUTPUT && r2_opnum >= r1_opnum));
+
case RELOAD_FOR_OPERAND_ADDRESS:
return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_INSN
|| r2_type == RELOAD_FOR_OPERAND_ADDRESS);
@@ -4654,7 +4978,8 @@ reloads_conflict (r1, r2)
case RELOAD_FOR_OUTPUT:
return (r2_type == RELOAD_FOR_INSN || r2_type == RELOAD_FOR_OUTPUT
- || (r2_type == RELOAD_FOR_OUTPUT_ADDRESS
+ || ((r2_type == RELOAD_FOR_OUTPUT_ADDRESS
+ || r2_type == RELOAD_FOR_OUTADDR_ADDRESS)
&& r2_opnum >= r1_opnum));
case RELOAD_FOR_INSN:
@@ -4666,7 +4991,7 @@ reloads_conflict (r1, r2)
return r2_type == RELOAD_FOR_OTHER_ADDRESS;
case RELOAD_OTHER:
- return r2_type != RELOAD_FOR_OTHER_ADDRESS;
+ return 1;
default:
abort ();
@@ -4916,7 +5241,9 @@ choose_reload_regs (insn, avoid_return_reg)
int save_reload_spill_index[MAX_RELOADS];
HARD_REG_SET save_reload_reg_used;
HARD_REG_SET save_reload_reg_used_in_input_addr[MAX_RECOG_OPERANDS];
+ HARD_REG_SET save_reload_reg_used_in_inpaddr_addr[MAX_RECOG_OPERANDS];
HARD_REG_SET save_reload_reg_used_in_output_addr[MAX_RECOG_OPERANDS];
+ HARD_REG_SET save_reload_reg_used_in_outaddr_addr[MAX_RECOG_OPERANDS];
HARD_REG_SET save_reload_reg_used_in_input[MAX_RECOG_OPERANDS];
HARD_REG_SET save_reload_reg_used_in_output[MAX_RECOG_OPERANDS];
HARD_REG_SET save_reload_reg_used_in_op_addr;
@@ -4941,13 +5268,14 @@ choose_reload_regs (insn, avoid_return_reg)
CLEAR_HARD_REG_SET (reload_reg_used_in_output[i]);
CLEAR_HARD_REG_SET (reload_reg_used_in_input[i]);
CLEAR_HARD_REG_SET (reload_reg_used_in_input_addr[i]);
+ CLEAR_HARD_REG_SET (reload_reg_used_in_inpaddr_addr[i]);
CLEAR_HARD_REG_SET (reload_reg_used_in_output_addr[i]);
+ CLEAR_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i]);
}
-#ifdef SMALL_REGISTER_CLASSES
/* Don't bother with avoiding the return reg
if we have no mandatory reload that could use it. */
- if (avoid_return_reg)
+ if (SMALL_REGISTER_CLASSES && avoid_return_reg)
{
int do_avoid = 0;
int regno = REGNO (avoid_return_reg);
@@ -4967,7 +5295,6 @@ choose_reload_regs (insn, avoid_return_reg)
if (!do_avoid)
avoid_return_reg = 0;
}
-#endif /* SMALL_REGISTER_CLASSES */
#if 0 /* Not needed, now that we can always retry without inheritance. */
/* See if we have more mandatory reloads than spill regs.
@@ -4978,10 +5305,7 @@ choose_reload_regs (insn, avoid_return_reg)
unless it is equal to reload_in or reload_out, count such reloads. */
{
- int tem = 0;
-#ifdef SMALL_REGISTER_CLASSES
- int tem = (avoid_return_reg != 0);
-#endif
+ int tem = SMALL_REGISTER_CLASSES? (avoid_return_reg != 0): 0;
for (j = 0; j < n_reloads; j++)
if (! reload_optional[j]
&& (reload_in[j] != 0 || reload_out[j] != 0 || reload_secondary_p[j])
@@ -4994,10 +5318,9 @@ choose_reload_regs (insn, avoid_return_reg)
}
#endif
-#ifdef SMALL_REGISTER_CLASSES
/* Don't use the subroutine call return reg for a reload
if we are supposed to avoid it. */
- if (avoid_return_reg)
+ if (SMALL_REGISTER_CLASSES && avoid_return_reg)
{
int regno = REGNO (avoid_return_reg);
int nregs
@@ -5008,7 +5331,6 @@ choose_reload_regs (insn, avoid_return_reg)
if (spill_reg_order[r] >= 0)
SET_HARD_REG_BIT (reload_reg_used, r);
}
-#endif /* SMALL_REGISTER_CLASSES */
/* In order to be certain of getting the registers we need,
we must sort the reloads into order of increasing register class.
@@ -5079,8 +5401,12 @@ choose_reload_regs (insn, avoid_return_reg)
reload_reg_used_in_input[i]);
COPY_HARD_REG_SET (save_reload_reg_used_in_input_addr[i],
reload_reg_used_in_input_addr[i]);
+ COPY_HARD_REG_SET (save_reload_reg_used_in_inpaddr_addr[i],
+ reload_reg_used_in_inpaddr_addr[i]);
COPY_HARD_REG_SET (save_reload_reg_used_in_output_addr[i],
reload_reg_used_in_output_addr[i]);
+ COPY_HARD_REG_SET (save_reload_reg_used_in_outaddr_addr[i],
+ reload_reg_used_in_outaddr_addr[i]);
}
/* If -O, try first with inheritance, then turning it off.
@@ -5116,12 +5442,14 @@ choose_reload_regs (insn, avoid_return_reg)
register int r = reload_order[j];
/* Ignore reloads that got marked inoperative. */
- if (reload_out[r] == 0 && reload_in[r] == 0 && ! reload_secondary_p[r])
+ if (reload_out[r] == 0 && reload_in[r] == 0
+ && ! reload_secondary_p[r])
continue;
/* If find_reloads chose a to use reload_in or reload_out as a reload
- register, we don't need to chose one. Otherwise, try even if it found
- one since we might save an insn if we find the value lying around. */
+ register, we don't need to chose one. Otherwise, try even if it
+ found one since we might save an insn if we find the value lying
+ around. */
if (reload_in[r] != 0 && reload_reg_rtx[r] != 0
&& (rtx_equal_p (reload_in[r], reload_reg_rtx[r])
|| rtx_equal_p (reload_out[r], reload_reg_rtx[r])))
@@ -5153,9 +5481,9 @@ choose_reload_regs (insn, avoid_return_reg)
an object that is already in a register of the desired class.
This would avoid the need for the secondary reload register.
But this is complex because we can't easily determine what
- objects might want to be loaded via this reload. So let a register
- be allocated here. In `emit_reload_insns' we suppress one of the
- loads in the case described above. */
+ objects might want to be loaded via this reload. So let a
+ register be allocated here. In `emit_reload_insns' we suppress
+ one of the loads in the case described above. */
if (inheritance)
{
@@ -5203,7 +5531,7 @@ choose_reload_regs (insn, avoid_return_reg)
reload_when_needed[r]))
{
/* If a group is needed, verify that all the subsequent
- registers still have their values intact. */
+ registers still have their values intact. */
int nr
= HARD_REGNO_NREGS (spill_regs[i], reload_mode[r]);
int k;
@@ -5325,8 +5653,9 @@ choose_reload_regs (insn, avoid_return_reg)
break;
}
- /* JRV: If the equiv register we have found is explicitly
- clobbered in the current insn, mark but don't use, as above. */
+ /* JRV: If the equiv register we have found is
+ explicitly clobbered in the current insn, mark but
+ don't use, as above. */
if (equiv != 0 && regno_clobbered_p (regno, insn))
{
@@ -5338,20 +5667,24 @@ choose_reload_regs (insn, avoid_return_reg)
to load it, and use it as our reload reg. */
if (equiv != 0 && regno != HARD_FRAME_POINTER_REGNUM)
{
+ int nr = HARD_REGNO_NREGS (regno, reload_mode[r]);
+ int k;
reload_reg_rtx[r] = equiv;
reload_inherited[r] = 1;
- /* If it is a spill reg,
- mark the spill reg as in use for this insn. */
- i = spill_reg_order[regno];
- if (i >= 0)
+
+ /* If any of the hard registers in EQUIV are spill
+ registers, mark them as in use for this insn. */
+ for (k = 0; k < nr; k++)
{
- int nr = HARD_REGNO_NREGS (regno, reload_mode[r]);
- int k;
- mark_reload_reg_in_use (regno, reload_opnum[r],
- reload_when_needed[r],
- reload_mode[r]);
- for (k = 0; k < nr; k++)
- SET_HARD_REG_BIT (reload_reg_used_for_inherit, regno + k);
+ i = spill_reg_order[regno + k];
+ if (i >= 0)
+ {
+ mark_reload_reg_in_use (regno, reload_opnum[r],
+ reload_when_needed[r],
+ reload_mode[r]);
+ SET_HARD_REG_BIT (reload_reg_used_for_inherit,
+ regno + k);
+ }
}
}
}
@@ -5407,7 +5740,7 @@ choose_reload_regs (insn, avoid_return_reg)
continue;
/* Skip reloads that already have a register allocated or are
- optional. */
+ optional. */
if (reload_reg_rtx[r] != 0 || reload_optional[r])
continue;
@@ -5453,8 +5786,12 @@ choose_reload_regs (insn, avoid_return_reg)
save_reload_reg_used_in_output[i]);
COPY_HARD_REG_SET (reload_reg_used_in_input_addr[i],
save_reload_reg_used_in_input_addr[i]);
+ COPY_HARD_REG_SET (reload_reg_used_in_inpaddr_addr[i],
+ save_reload_reg_used_in_inpaddr_addr[i]);
COPY_HARD_REG_SET (reload_reg_used_in_output_addr[i],
save_reload_reg_used_in_output_addr[i]);
+ COPY_HARD_REG_SET (reload_reg_used_in_outaddr_addr[i],
+ save_reload_reg_used_in_outaddr_addr[i]);
}
}
@@ -5546,7 +5883,7 @@ choose_reload_regs (insn, avoid_return_reg)
}
}
-/* If SMALL_REGISTER_CLASSES are defined, we may not have merged two
+/* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
reloads of the same item for fear that we might not have enough reload
registers. However, normally they will get the same reload register
and hence actually need not be loaded twice.
@@ -5559,8 +5896,6 @@ choose_reload_regs (insn, avoid_return_reg)
This will not increase the number of spill registers needed and will
prevent redundant code. */
-#ifdef SMALL_REGISTER_CLASSES
-
static void
merge_assigned_reloads (insn)
rtx insn;
@@ -5628,12 +5963,13 @@ merge_assigned_reloads (insn)
&& reg_overlap_mentioned_for_reload_p (reload_in[j],
reload_in[i]))
reload_when_needed[j]
- = reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
- ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER;
+ = ((reload_when_needed[i] == RELOAD_FOR_INPUT_ADDRESS
+ || reload_when_needed[i] == RELOAD_FOR_INPADDR_ADDRESS)
+ ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
}
}
}
-#endif /* SMALL_RELOAD_CLASSES */
+
/* Output insns to reload values in and out of the chosen reload regs. */
@@ -5646,11 +5982,13 @@ emit_reload_insns (insn)
rtx other_input_address_reload_insns = 0;
rtx other_input_reload_insns = 0;
rtx input_address_reload_insns[MAX_RECOG_OPERANDS];
+ rtx inpaddr_address_reload_insns[MAX_RECOG_OPERANDS];
rtx output_reload_insns[MAX_RECOG_OPERANDS];
rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
+ rtx outaddr_address_reload_insns[MAX_RECOG_OPERANDS];
rtx operand_reload_insns = 0;
rtx other_operand_reload_insns = 0;
- rtx other_output_reload_insns = 0;
+ rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
rtx following_insn = NEXT_INSN (insn);
rtx before_insn = insn;
int special;
@@ -5659,7 +5997,10 @@ emit_reload_insns (insn)
for (j = 0; j < reload_n_operands; j++)
input_reload_insns[j] = input_address_reload_insns[j]
- = output_reload_insns[j] = output_address_reload_insns[j] = 0;
+ = inpaddr_address_reload_insns[j]
+ = output_reload_insns[j] = output_address_reload_insns[j]
+ = outaddr_address_reload_insns[j]
+ = other_output_reload_insns[j] = 0;
/* Now output the instructions to copy the data into and out of the
reload registers. Do these in the order that the reloads were reported,
@@ -5670,6 +6011,7 @@ emit_reload_insns (insn)
{
register rtx old;
rtx oldequiv_reg = 0;
+ rtx this_reload_insn = 0;
if (reload_spill_index[j] >= 0)
new_spill_reg_store[reload_spill_index[j]] = 0;
@@ -5852,9 +6194,15 @@ emit_reload_insns (insn)
case RELOAD_FOR_INPUT_ADDRESS:
where = &input_address_reload_insns[reload_opnum[j]];
break;
+ case RELOAD_FOR_INPADDR_ADDRESS:
+ where = &inpaddr_address_reload_insns[reload_opnum[j]];
+ break;
case RELOAD_FOR_OUTPUT_ADDRESS:
where = &output_address_reload_insns[reload_opnum[j]];
break;
+ case RELOAD_FOR_OUTADDR_ADDRESS:
+ where = &outaddr_address_reload_insns[reload_opnum[j]];
+ break;
case RELOAD_FOR_OPERAND_ADDRESS:
where = &operand_reload_insns;
break;
@@ -5923,8 +6271,8 @@ emit_reload_insns (insn)
SET_DEST (PATTERN (temp)) = reloadreg;
/* If these are the only uses of the pseudo reg,
pretend for GDB it lives in the reload reg we used. */
- if (reg_n_deaths[REGNO (old)] == 1
- && reg_n_sets[REGNO (old)] == 1)
+ if (REG_N_DEATHS (REGNO (old)) == 1
+ && REG_N_SETS (REGNO (old)) == 1)
{
reg_renumber[REGNO (old)] = REGNO (reload_reg_rtx[j]);
alter_reg (REGNO (old), -1);
@@ -6092,6 +6440,7 @@ emit_reload_insns (insn)
#endif
}
+ this_reload_insn = get_last_insn ();
/* End this sequence. */
*where = get_insns ();
end_sequence ();
@@ -6411,7 +6760,7 @@ emit_reload_insns (insn)
reloadreg, REG_NOTES (p));
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
- if (! special
+ if (! special && second_reloadreg
&& PRESERVE_DEATH_INFO_REGNO_P (REGNO (second_reloadreg)))
for (p = get_last_insn (); p; p = PREV_INSN (p))
if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
@@ -6438,9 +6787,8 @@ emit_reload_insns (insn)
if (reload_when_needed[j] == RELOAD_OTHER)
{
- if (other_output_reload_insns)
- emit_insns (other_output_reload_insns);
- other_output_reload_insns = get_insns ();
+ emit_insns (other_output_reload_insns[reload_opnum[j]]);
+ other_output_reload_insns[reload_opnum[j]] = get_insns ();
}
else
output_reload_insns[reload_opnum[j]] = get_insns ();
@@ -6455,10 +6803,11 @@ emit_reload_insns (insn)
RELOAD_FOR_OTHER_ADDRESS reloads for input addresses.
- RELOAD_OTHER reloads, output in ascending order by reload number.
+ RELOAD_OTHER reloads.
- For each operand, any RELOAD_FOR_INPUT_ADDRESS reloads followed by
- the RELOAD_FOR_INPUT reload for the operand.
+ For each operand, any RELOAD_FOR_INPADDR_ADDRESS reloads followed
+ by any RELOAD_FOR_INPUT_ADDRESS reloads followed by the
+ RELOAD_FOR_INPUT reload for the operand.
RELOAD_FOR_OPADDR_ADDRS reloads.
@@ -6466,17 +6815,18 @@ emit_reload_insns (insn)
After the insn being reloaded, we write the following:
- For each operand, any RELOAD_FOR_OUTPUT_ADDRESS reload followed by
- the RELOAD_FOR_OUTPUT reload for that operand.
-
- Any RELOAD_OTHER output reloads, output in descending order by
- reload number. */
+ For each operand, any RELOAD_FOR_OUTADDR_ADDRESS reloads followed
+ by any RELOAD_FOR_OUTPUT_ADDRESS reload followed by the
+ RELOAD_FOR_OUTPUT reload, followed by any RELOAD_OTHER output
+ reloads for the operand. The RELOAD_OTHER output reloads are
+ output in descending order by reload number. */
emit_insns_before (other_input_address_reload_insns, before_insn);
emit_insns_before (other_input_reload_insns, before_insn);
for (j = 0; j < reload_n_operands; j++)
{
+ emit_insns_before (inpaddr_address_reload_insns[j], before_insn);
emit_insns_before (input_address_reload_insns[j], before_insn);
emit_insns_before (input_reload_insns[j], before_insn);
}
@@ -6486,12 +6836,12 @@ emit_reload_insns (insn)
for (j = 0; j < reload_n_operands; j++)
{
+ emit_insns_before (outaddr_address_reload_insns[j], following_insn);
emit_insns_before (output_address_reload_insns[j], following_insn);
emit_insns_before (output_reload_insns[j], following_insn);
+ emit_insns_before (other_output_reload_insns[j], following_insn);
}
- emit_insns_before (other_output_reload_insns, following_insn);
-
/* Move death notes from INSN
to output-operand-address and output reload insns. */
#ifdef PRESERVE_DEATH_INFO_REGNO_P
@@ -6550,107 +6900,139 @@ emit_reload_insns (insn)
/* I is nonneg if this reload used one of the spill regs.
If reload_reg_rtx[r] is 0, this is an optional reload
- that we opted to ignore.
-
- Also ignore reloads that don't reach the end of the insn,
- since we will eventually see the one that does. */
+ that we opted to ignore. */
- if (i >= 0 && reload_reg_rtx[r] != 0
- && reload_reg_reaches_end_p (spill_regs[i], reload_opnum[r],
- reload_when_needed[r]))
+ if (i >= 0 && reload_reg_rtx[r] != 0)
{
- /* First, clear out memory of what used to be in this spill reg.
- If consecutive registers are used, clear them all. */
int nr
= HARD_REGNO_NREGS (spill_regs[i], GET_MODE (reload_reg_rtx[r]));
int k;
+ int part_reaches_end = 0;
+ int all_reaches_end = 1;
+ /* For a multi register reload, we need to check if all or part
+ of the value lives to the end. */
for (k = 0; k < nr; k++)
{
- reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]] = -1;
- reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = 0;
+ if (reload_reg_reaches_end_p (spill_regs[i] + k, reload_opnum[r],
+ reload_when_needed[r]))
+ part_reaches_end = 1;
+ else
+ all_reaches_end = 0;
}
- /* Maybe the spill reg contains a copy of reload_out. */
- if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
+ /* Ignore reloads that don't reach the end of the insn in
+ entirety. */
+ if (all_reaches_end)
{
- register int nregno = REGNO (reload_out[r]);
- int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
- : HARD_REGNO_NREGS (nregno,
- GET_MODE (reload_reg_rtx[r])));
-
- spill_reg_store[i] = new_spill_reg_store[i];
- reg_last_reload_reg[nregno] = reload_reg_rtx[r];
-
- /* If NREGNO is a hard register, it may occupy more than
- one register. If it does, say what is in the
- rest of the registers assuming that both registers
- agree on how many words the object takes. If not,
- invalidate the subsequent registers. */
+ /* First, clear out memory of what used to be in this spill reg.
+ If consecutive registers are used, clear them all. */
- if (nregno < FIRST_PSEUDO_REGISTER)
- for (k = 1; k < nnr; k++)
- reg_last_reload_reg[nregno + k]
- = (nr == nnr ? gen_rtx (REG,
- reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
- REGNO (reload_reg_rtx[r]) + k)
- : 0);
-
- /* Now do the inverse operation. */
for (k = 0; k < nr; k++)
{
- reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
- = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr ? nregno
- : nregno + k);
- reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = insn;
+ reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]] = -1;
+ reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = 0;
}
- }
- /* Maybe the spill reg contains a copy of reload_in. Only do
- something if there will not be an output reload for
- the register being reloaded. */
- else if (reload_out[r] == 0
- && reload_in[r] != 0
- && ((GET_CODE (reload_in[r]) == REG
- && ! reg_has_output_reload[REGNO (reload_in[r])]
- || (GET_CODE (reload_in_reg[r]) == REG
- && ! reg_has_output_reload[REGNO (reload_in_reg[r])]))))
- {
- register int nregno;
- int nnr;
-
- if (GET_CODE (reload_in[r]) == REG)
- nregno = REGNO (reload_in[r]);
- else
- nregno = REGNO (reload_in_reg[r]);
-
- nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
- : HARD_REGNO_NREGS (nregno,
- GET_MODE (reload_reg_rtx[r])));
+ /* Maybe the spill reg contains a copy of reload_out. */
+ if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
+ {
+ register int nregno = REGNO (reload_out[r]);
+ int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
+ : HARD_REGNO_NREGS (nregno,
+ GET_MODE (reload_reg_rtx[r])));
+
+ spill_reg_store[i] = new_spill_reg_store[i];
+ reg_last_reload_reg[nregno] = reload_reg_rtx[r];
+
+ /* If NREGNO is a hard register, it may occupy more than
+ one register. If it does, say what is in the
+ rest of the registers assuming that both registers
+ agree on how many words the object takes. If not,
+ invalidate the subsequent registers. */
+
+ if (nregno < FIRST_PSEUDO_REGISTER)
+ for (k = 1; k < nnr; k++)
+ reg_last_reload_reg[nregno + k]
+ = (nr == nnr
+ ? gen_rtx (REG,
+ reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
+ REGNO (reload_reg_rtx[r]) + k)
+ : 0);
+
+ /* Now do the inverse operation. */
+ for (k = 0; k < nr; k++)
+ {
+ reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
+ = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr
+ ? nregno
+ : nregno + k);
+ reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = insn;
+ }
+ }
- reg_last_reload_reg[nregno] = reload_reg_rtx[r];
+ /* Maybe the spill reg contains a copy of reload_in. Only do
+ something if there will not be an output reload for
+ the register being reloaded. */
+ else if (reload_out[r] == 0
+ && reload_in[r] != 0
+ && ((GET_CODE (reload_in[r]) == REG
+ && ! reg_has_output_reload[REGNO (reload_in[r])])
+ || (GET_CODE (reload_in_reg[r]) == REG
+ && ! reg_has_output_reload[REGNO (reload_in_reg[r])])))
+ {
+ register int nregno;
+ int nnr;
- if (nregno < FIRST_PSEUDO_REGISTER)
- for (k = 1; k < nnr; k++)
- reg_last_reload_reg[nregno + k]
- = (nr == nnr ? gen_rtx (REG,
- reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
- REGNO (reload_reg_rtx[r]) + k)
- : 0);
+ if (GET_CODE (reload_in[r]) == REG)
+ nregno = REGNO (reload_in[r]);
+ else
+ nregno = REGNO (reload_in_reg[r]);
- /* Unless we inherited this reload, show we haven't
- recently done a store. */
- if (! reload_inherited[r])
- spill_reg_store[i] = 0;
+ nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
+ : HARD_REGNO_NREGS (nregno,
+ GET_MODE (reload_reg_rtx[r])));
+
+ reg_last_reload_reg[nregno] = reload_reg_rtx[r];
+
+ if (nregno < FIRST_PSEUDO_REGISTER)
+ for (k = 1; k < nnr; k++)
+ reg_last_reload_reg[nregno + k]
+ = (nr == nnr
+ ? gen_rtx (REG,
+ reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
+ REGNO (reload_reg_rtx[r]) + k)
+ : 0);
+
+ /* Unless we inherited this reload, show we haven't
+ recently done a store. */
+ if (! reload_inherited[r])
+ spill_reg_store[i] = 0;
+
+ for (k = 0; k < nr; k++)
+ {
+ reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
+ = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr
+ ? nregno
+ : nregno + k);
+ reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]]
+ = insn;
+ }
+ }
+ }
+ /* However, if part of the reload reaches the end, then we must
+ invalidate the old info for the part that survives to the end. */
+ else if (part_reaches_end)
+ {
for (k = 0; k < nr; k++)
- {
- reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
- = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr ? nregno
- : nregno + k);
- reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]]
- = insn;
- }
+ if (reload_reg_reaches_end_p (spill_regs[i] + k,
+ reload_opnum[r],
+ reload_when_needed[r]))
+ {
+ reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]] = -1;
+ reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = 0;
+ }
}
}
@@ -6735,8 +7117,10 @@ gen_reload (out, in, opnum, type)
if (GET_CODE (in) == PLUS
&& (GET_CODE (XEXP (in, 0)) == REG
+ || GET_CODE (XEXP (in, 0)) == SUBREG
|| GET_CODE (XEXP (in, 0)) == MEM)
&& (GET_CODE (XEXP (in, 1)) == REG
+ || GET_CODE (XEXP (in, 1)) == SUBREG
|| CONSTANT_P (XEXP (in, 1))
|| GET_CODE (XEXP (in, 1)) == MEM))
{
@@ -6764,7 +7148,7 @@ gen_reload (out, in, opnum, type)
if the add instruction is two-address and the second operand
of the add is the same as the reload reg, which is frequently
the case. If the insn would be A = B + A, rearrange it so
- it will be A = A + B as constrain_operands expects. */
+ it will be A = A + B as constrain_operands expects. */
if (GET_CODE (XEXP (in, 1)) == REG
&& REGNO (out) == REGNO (XEXP (in, 1)))
@@ -6797,12 +7181,12 @@ gen_reload (out, in, opnum, type)
DEFINE_PEEPHOLE should be specified that recognizes the sequence
we emit below. */
- if (CONSTANT_P (op1) || GET_CODE (op1) == MEM
+ if (CONSTANT_P (op1) || GET_CODE (op1) == MEM || GET_CODE (op1) == SUBREG
|| (GET_CODE (op1) == REG
&& REGNO (op1) >= FIRST_PSEUDO_REGISTER))
tem = op0, op0 = op1, op1 = tem;
- emit_insn (gen_move_insn (out, op0));
+ gen_reload (out, op0, opnum, type);
/* If OP0 and OP1 are the same, we can use OUT for OP1.
This fixes a problem on the 32K where the stack pointer cannot
@@ -6814,7 +7198,7 @@ gen_reload (out, in, opnum, type)
insn = emit_insn (gen_add2_insn (out, op1));
/* If that failed, copy the address register to the reload register.
- Then add the constant to the reload register. */
+ Then add the constant to the reload register. */
code = recog_memoized (insn);
@@ -6830,7 +7214,7 @@ gen_reload (out, in, opnum, type)
delete_insns_since (last);
- emit_insn (gen_move_insn (out, op1));
+ gen_reload (out, op1, opnum, type);
emit_insn (gen_add2_insn (out, op0));
}
@@ -6851,8 +7235,8 @@ gen_reload (out, in, opnum, type)
if (GET_MODE (loc) != GET_MODE (in))
in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
- emit_insn (gen_move_insn (loc, in));
- emit_insn (gen_move_insn (out, loc));
+ gen_reload (loc, in, opnum, type);
+ gen_reload (out, loc, opnum, type);
}
#endif
@@ -6926,8 +7310,8 @@ delete_output_reload (insn, j, output_reload_insn)
/* See if the pseudo reg has been completely replaced
with reload regs. If so, delete the store insn
and forget we had a stack slot for the pseudo. */
- else if (reg_n_deaths[REGNO (reg)] == 1
- && reg_basic_block[REGNO (reg)] >= 0
+ else if (REG_N_DEATHS (REGNO (reg)) == 1
+ && REG_BASIC_BLOCK (REGNO (reg)) >= 0
&& find_regno_note (insn, REG_DEAD, REGNO (reg)))
{
rtx i2;
@@ -6961,7 +7345,13 @@ delete_output_reload (insn, j, output_reload_insn)
rtx set = single_set (i2);
if (set != 0 && SET_DEST (set) == reg)
- delete_insn (i2);
+ {
+ /* This might be a basic block head,
+ thus don't use delete_insn. */
+ PUT_CODE (i2, NOTE);
+ NOTE_SOURCE_FILE (i2) = 0;
+ NOTE_LINE_NUMBER (i2) = NOTE_INSN_DELETED;
+ }
if (GET_CODE (i2) == CODE_LABEL
|| GET_CODE (i2) == JUMP_INSN)
break;
@@ -7150,6 +7540,9 @@ count_occurrences (x, find)
if (SET_DEST (x) == find)
return count_occurrences (SET_SRC (x), find);
break;
+
+ default:
+ break;
}
format_ptr = GET_RTX_FORMAT (code);
@@ -7174,3 +7567,1060 @@ count_occurrences (x, find)
}
return count;
}
+
+/* This array holds values which are equivalent to a hard register
+ during reload_cse_regs. Each array element is an EXPR_LIST of
+ values. Each time a hard register is set, we set the corresponding
+ array element to the value. Each time a hard register is copied
+ into memory, we add the memory location to the corresponding array
+ element. We don't store values or memory addresses with side
+ effects in this array.
+
+ If the value is a CONST_INT, then the mode of the containing
+ EXPR_LIST is the mode in which that CONST_INT was referenced.
+
+ We sometimes clobber a specific entry in a list. In that case, we
+ just set XEXP (list-entry, 0) to 0. */
+
+static rtx *reg_values;
+
+/* This is a preallocated REG rtx which we use as a temporary in
+ reload_cse_invalidate_regno, so that we don't need to allocate a
+ new one each time through a loop in that function. */
+
+static rtx invalidate_regno_rtx;
+
+/* This is a set of registers for which we must remove REG_DEAD notes in
+ previous insns, because our modifications made them invalid. That can
+ happen if we introduced the register into the current insn, or we deleted
+ the current insn which used to set the register. */
+
+static HARD_REG_SET no_longer_dead_regs;
+
+/* Invalidate any entries in reg_values which depend on REGNO,
+ including those for REGNO itself. This is called if REGNO is
+ changing. If CLOBBER is true, then always forget anything we
+ currently know about REGNO. MODE is the mode of the assignment to
+ REGNO, which is used to determine how many hard registers are being
+ changed. If MODE is VOIDmode, then only REGNO is being changed;
+ this is used when invalidating call clobbered registers across a
+ call. */
+
+static void
+reload_cse_invalidate_regno (regno, mode, clobber)
+ int regno;
+ enum machine_mode mode;
+ int clobber;
+{
+ int endregno;
+ register int i;
+
+ /* Our callers don't always go through true_regnum; we may see a
+ pseudo-register here from a CLOBBER or the like. We probably
+ won't ever see a pseudo-register that has a real register number,
+ for we check anyhow for safety. */
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ regno = reg_renumber[regno];
+ if (regno < 0)
+ return;
+
+ if (mode == VOIDmode)
+ endregno = regno + 1;
+ else
+ endregno = regno + HARD_REGNO_NREGS (regno, mode);
+
+ if (clobber)
+ for (i = regno; i < endregno; i++)
+ reg_values[i] = 0;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ rtx x;
+
+ for (x = reg_values[i]; x; x = XEXP (x, 1))
+ {
+ if (XEXP (x, 0) != 0
+ && refers_to_regno_p (regno, endregno, XEXP (x, 0), NULL_PTR))
+ {
+ /* If this is the only entry on the list, clear
+ reg_values[i]. Otherwise, just clear this entry on
+ the list. */
+ if (XEXP (x, 1) == 0 && x == reg_values[i])
+ {
+ reg_values[i] = 0;
+ break;
+ }
+ XEXP (x, 0) = 0;
+ }
+ }
+ }
+
+ /* We must look at earlier registers, in case REGNO is part of a
+ multi word value but is not the first register. If an earlier
+ register has a value in a mode which overlaps REGNO, then we must
+ invalidate that earlier register. Note that we do not need to
+ check REGNO or later registers (we must not check REGNO itself,
+ because we would incorrectly conclude that there was a conflict). */
+
+ for (i = 0; i < regno; i++)
+ {
+ rtx x;
+
+ for (x = reg_values[i]; x; x = XEXP (x, 1))
+ {
+ if (XEXP (x, 0) != 0)
+ {
+ PUT_MODE (invalidate_regno_rtx, GET_MODE (x));
+ REGNO (invalidate_regno_rtx) = i;
+ if (refers_to_regno_p (regno, endregno, invalidate_regno_rtx,
+ NULL_PTR))
+ {
+ reload_cse_invalidate_regno (i, VOIDmode, 1);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/* The memory at address MEM_BASE is being changed.
+ Return whether this change will invalidate VAL. */
+
+static int
+reload_cse_mem_conflict_p (mem_base, val)
+ rtx mem_base;
+ rtx val;
+{
+ enum rtx_code code;
+ char *fmt;
+ int i;
+
+ code = GET_CODE (val);
+ switch (code)
+ {
+ /* Get rid of a few simple cases quickly. */
+ case REG:
+ case PC:
+ case CC0:
+ case SCRATCH:
+ case CONST:
+ case CONST_INT:
+ case CONST_DOUBLE:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 0;
+
+ case MEM:
+ if (GET_MODE (mem_base) == BLKmode
+ || GET_MODE (val) == BLKmode)
+ return 1;
+ if (anti_dependence (val, mem_base))
+ return 1;
+ /* The address may contain nested MEMs. */
+ break;
+
+ default:
+ break;
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ {
+ if (reload_cse_mem_conflict_p (mem_base, XEXP (val, i)))
+ return 1;
+ }
+ else if (fmt[i] == 'E')
+ {
+ int j;
+
+ for (j = 0; j < XVECLEN (val, i); j++)
+ if (reload_cse_mem_conflict_p (mem_base, XVECEXP (val, i, j)))
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* Invalidate any entries in reg_values which are changed because of a
+ store to MEM_RTX. If this is called because of a non-const call
+ instruction, MEM_RTX is (mem:BLK const0_rtx). */
+
+static void
+reload_cse_invalidate_mem (mem_rtx)
+ rtx mem_rtx;
+{
+ register int i;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ rtx x;
+
+ for (x = reg_values[i]; x; x = XEXP (x, 1))
+ {
+ if (XEXP (x, 0) != 0
+ && reload_cse_mem_conflict_p (mem_rtx, XEXP (x, 0)))
+ {
+ /* If this is the only entry on the list, clear
+ reg_values[i]. Otherwise, just clear this entry on
+ the list. */
+ if (XEXP (x, 1) == 0 && x == reg_values[i])
+ {
+ reg_values[i] = 0;
+ break;
+ }
+ XEXP (x, 0) = 0;
+ }
+ }
+ }
+}
+
+/* Invalidate DEST, which is being assigned to or clobbered. The
+ second parameter exists so that this function can be passed to
+ note_stores; it is ignored. */
+
+static void
+reload_cse_invalidate_rtx (dest, ignore)
+ rtx dest;
+ rtx ignore;
+{
+ while (GET_CODE (dest) == STRICT_LOW_PART
+ || GET_CODE (dest) == SIGN_EXTRACT
+ || GET_CODE (dest) == ZERO_EXTRACT
+ || GET_CODE (dest) == SUBREG)
+ dest = XEXP (dest, 0);
+
+ if (GET_CODE (dest) == REG)
+ reload_cse_invalidate_regno (REGNO (dest), GET_MODE (dest), 1);
+ else if (GET_CODE (dest) == MEM)
+ reload_cse_invalidate_mem (dest);
+}
+
+/* Possibly delete death notes on the insns before INSN if modifying INSN
+ extended the lifespan of the registers. */
+
+static void
+reload_cse_delete_death_notes (insn)
+ rtx insn;
+{
+ int dreg;
+
+ for (dreg = 0; dreg < FIRST_PSEUDO_REGISTER; dreg++)
+ {
+ rtx trial;
+
+ if (! TEST_HARD_REG_BIT (no_longer_dead_regs, dreg))
+ continue;
+
+ for (trial = prev_nonnote_insn (insn);
+ (trial
+ && GET_CODE (trial) != CODE_LABEL
+ && GET_CODE (trial) != BARRIER);
+ trial = prev_nonnote_insn (trial))
+ {
+ if (find_regno_note (trial, REG_DEAD, dreg))
+ {
+ remove_death (dreg, trial);
+ break;
+ }
+ }
+ }
+}
+
+/* Record that the current insn uses hard reg REGNO in mode MODE. This
+ will be used in reload_cse_delete_death_notes to delete prior REG_DEAD
+ notes for this register. */
+
+static void
+reload_cse_no_longer_dead (regno, mode)
+ int regno;
+ enum machine_mode mode;
+{
+ int nregs = HARD_REGNO_NREGS (regno, mode);
+ while (nregs-- > 0)
+ {
+ SET_HARD_REG_BIT (no_longer_dead_regs, regno);
+ regno++;
+ }
+}
+
+
+/* Do a very simple CSE pass over the hard registers.
+
+ This function detects no-op moves where we happened to assign two
+ different pseudo-registers to the same hard register, and then
+ copied one to the other. Reload will generate a useless
+ instruction copying a register to itself.
+
+ This function also detects cases where we load a value from memory
+ into two different registers, and (if memory is more expensive than
+ registers) changes it to simply copy the first register into the
+ second register.
+
+ Another optimization is performed that scans the operands of each
+ instruction to see whether the value is already available in a
+ hard register. It then replaces the operand with the hard register
+ if possible, much like an optional reload would. */
+
+void
+reload_cse_regs (first)
+ rtx first;
+{
+ char *firstobj;
+ rtx callmem;
+ register int i;
+ rtx insn;
+
+ init_alias_analysis ();
+
+ reg_values = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_values[i] = 0;
+
+ /* Create our EXPR_LIST structures on reload_obstack, so that we can
+ free them when we are done. */
+ push_obstacks (&reload_obstack, &reload_obstack);
+ firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+
+ /* We pass this to reload_cse_invalidate_mem to invalidate all of
+ memory for a non-const call instruction. */
+ callmem = gen_rtx (MEM, BLKmode, const0_rtx);
+
+ /* This is used in reload_cse_invalidate_regno to avoid consing a
+ new REG in a loop in that function. */
+ invalidate_regno_rtx = gen_rtx (REG, VOIDmode, 0);
+
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+ rtx body;
+
+ if (GET_CODE (insn) == CODE_LABEL)
+ {
+ /* Forget all the register values at a code label. We don't
+ try to do anything clever around jumps. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_values[i] = 0;
+
+ continue;
+ }
+
+#ifdef NON_SAVING_SETJMP
+ if (NON_SAVING_SETJMP && GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+ {
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_values[i] = 0;
+
+ continue;
+ }
+#endif
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ continue;
+
+ CLEAR_HARD_REG_SET (no_longer_dead_regs);
+
+ /* If this is a call instruction, forget anything stored in a
+ call clobbered register, or, if this is not a const call, in
+ memory. */
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (call_used_regs[i])
+ reload_cse_invalidate_regno (i, VOIDmode, 1);
+
+ if (! CONST_CALL_P (insn))
+ reload_cse_invalidate_mem (callmem);
+ }
+
+ body = PATTERN (insn);
+ if (GET_CODE (body) == SET)
+ {
+ int count = 0;
+ if (reload_cse_noop_set_p (body, insn))
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ reload_cse_delete_death_notes (insn);
+
+ /* We're done with this insn. */
+ continue;
+ }
+
+ /* It's not a no-op, but we can try to simplify it. */
+ CLEAR_HARD_REG_SET (no_longer_dead_regs);
+ count += reload_cse_simplify_set (body, insn);
+
+ if (count > 0 && apply_change_group ())
+ reload_cse_delete_death_notes (insn);
+ else if (reload_cse_simplify_operands (insn))
+ reload_cse_delete_death_notes (insn);
+
+ reload_cse_record_set (body, body);
+ }
+ else if (GET_CODE (body) == PARALLEL)
+ {
+ int count = 0;
+
+ /* If every action in a PARALLEL is a noop, we can delete
+ the entire PARALLEL. */
+ for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
+ if ((GET_CODE (XVECEXP (body, 0, i)) != SET
+ || ! reload_cse_noop_set_p (XVECEXP (body, 0, i), insn))
+ && GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
+ break;
+ if (i < 0)
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ reload_cse_delete_death_notes (insn);
+
+ /* We're done with this insn. */
+ continue;
+ }
+
+ /* It's not a no-op, but we can try to simplify it. */
+ CLEAR_HARD_REG_SET (no_longer_dead_regs);
+ for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
+ if (GET_CODE (XVECEXP (body, 0, i)) == SET)
+ count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
+
+ if (count > 0 && apply_change_group ())
+ reload_cse_delete_death_notes (insn);
+ else if (reload_cse_simplify_operands (insn))
+ reload_cse_delete_death_notes (insn);
+
+ /* Look through the PARALLEL and record the values being
+ set, if possible. Also handle any CLOBBERs. */
+ for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
+ {
+ rtx x = XVECEXP (body, 0, i);
+
+ if (GET_CODE (x) == SET)
+ reload_cse_record_set (x, body);
+ else
+ note_stores (x, reload_cse_invalidate_rtx);
+ }
+ }
+ else
+ note_stores (body, reload_cse_invalidate_rtx);
+
+#ifdef AUTO_INC_DEC
+ /* Clobber any registers which appear in REG_INC notes. We
+ could keep track of the changes to their values, but it is
+ unlikely to help. */
+ {
+ rtx x;
+
+ for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
+ if (REG_NOTE_KIND (x) == REG_INC)
+ reload_cse_invalidate_rtx (XEXP (x, 0), NULL_RTX);
+ }
+#endif
+
+ /* Look for any CLOBBERs in CALL_INSN_FUNCTION_USAGE, but only
+ after we have processed the insn. */
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ rtx x;
+
+ for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1))
+ if (GET_CODE (XEXP (x, 0)) == CLOBBER)
+ reload_cse_invalidate_rtx (XEXP (XEXP (x, 0), 0), NULL_RTX);
+ }
+ }
+
+ /* Free all the temporary structures we created, and go back to the
+ regular obstacks. */
+ obstack_free (&reload_obstack, firstobj);
+ pop_obstacks ();
+}
+
+/* Return whether the values known for REGNO are equal to VAL. MODE
+ is the mode of the object that VAL is being copied to; this matters
+ if VAL is a CONST_INT. */
+
+static int
+reload_cse_regno_equal_p (regno, val, mode)
+ int regno;
+ rtx val;
+ enum machine_mode mode;
+{
+ rtx x;
+
+ if (val == 0)
+ return 0;
+
+ for (x = reg_values[regno]; x; x = XEXP (x, 1))
+ if (XEXP (x, 0) != 0
+ && rtx_equal_p (XEXP (x, 0), val)
+ && (GET_CODE (val) != CONST_INT
+ || mode == GET_MODE (x)
+ || (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))
+ /* On a big endian machine if the value spans more than
+ one register then this register holds the high part of
+ it and we can't use it.
+
+ ??? We should also compare with the high part of the
+ value. */
+ && !(WORDS_BIG_ENDIAN
+ && HARD_REGNO_NREGS (regno, GET_MODE (x)) > 1)
+ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+ GET_MODE_BITSIZE (GET_MODE (x))))))
+ return 1;
+
+ return 0;
+}
+
+/* See whether a single set is a noop. SET is the set instruction we
+ are should check, and INSN is the instruction from which it came. */
+
+static int
+reload_cse_noop_set_p (set, insn)
+ rtx set;
+ rtx insn;
+{
+ rtx src, dest;
+ enum machine_mode dest_mode;
+ int dreg, sreg;
+ int ret;
+
+ src = SET_SRC (set);
+ dest = SET_DEST (set);
+ dest_mode = GET_MODE (dest);
+
+ if (side_effects_p (src))
+ return 0;
+
+ dreg = true_regnum (dest);
+ sreg = true_regnum (src);
+
+ /* Check for setting a register to itself. In this case, we don't
+ have to worry about REG_DEAD notes. */
+ if (dreg >= 0 && dreg == sreg)
+ return 1;
+
+ ret = 0;
+ if (dreg >= 0)
+ {
+ /* Check for setting a register to itself. */
+ if (dreg == sreg)
+ ret = 1;
+
+ /* Check for setting a register to a value which we already know
+ is in the register. */
+ else if (reload_cse_regno_equal_p (dreg, src, dest_mode))
+ ret = 1;
+
+ /* Check for setting a register DREG to another register SREG
+ where SREG is equal to a value which is already in DREG. */
+ else if (sreg >= 0)
+ {
+ rtx x;
+
+ for (x = reg_values[sreg]; x; x = XEXP (x, 1))
+ {
+ rtx tmp;
+
+ if (XEXP (x, 0) == 0)
+ continue;
+
+ if (dest_mode == GET_MODE (x))
+ tmp = XEXP (x, 0);
+ else if (GET_MODE_BITSIZE (dest_mode)
+ < GET_MODE_BITSIZE (GET_MODE (x)))
+ tmp = gen_lowpart_common (dest_mode, XEXP (x, 0));
+ else
+ continue;
+
+ if (tmp
+ && reload_cse_regno_equal_p (dreg, tmp, dest_mode))
+ {
+ ret = 1;
+ break;
+ }
+ }
+ }
+ }
+ else if (GET_CODE (dest) == MEM)
+ {
+ /* Check for storing a register to memory when we know that the
+ register is equivalent to the memory location. */
+ if (sreg >= 0
+ && reload_cse_regno_equal_p (sreg, dest, dest_mode)
+ && ! side_effects_p (dest))
+ ret = 1;
+ }
+
+ /* If we can delete this SET, then we need to look for an earlier
+ REG_DEAD note on DREG, and remove it if it exists. */
+ if (ret && dreg >= 0)
+ {
+ if (! find_regno_note (insn, REG_UNUSED, dreg))
+ reload_cse_no_longer_dead (dreg, dest_mode);
+ }
+
+ return ret;
+}
+
+/* Try to simplify a single SET instruction. SET is the set pattern.
+ INSN is the instruction it came from.
+ This function only handles one case: if we set a register to a value
+ which is not a register, we try to find that value in some other register
+ and change the set into a register copy. */
+
+static int
+reload_cse_simplify_set (set, insn)
+ rtx set;
+ rtx insn;
+{
+ int dreg;
+ rtx src;
+ enum machine_mode dest_mode;
+ enum reg_class dclass;
+ register int i;
+
+ dreg = true_regnum (SET_DEST (set));
+ if (dreg < 0)
+ return 0;
+
+ src = SET_SRC (set);
+ if (side_effects_p (src) || true_regnum (src) >= 0)
+ return 0;
+
+ /* If memory loads are cheaper than register copies, don't change
+ them. */
+ if (GET_CODE (src) == MEM && MEMORY_MOVE_COST (GET_MODE (src)) < 2)
+ return 0;
+
+ dest_mode = GET_MODE (SET_DEST (set));
+ dclass = REGNO_REG_CLASS (dreg);
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (i != dreg
+ && REGISTER_MOVE_COST (REGNO_REG_CLASS (i), dclass) == 2
+ && reload_cse_regno_equal_p (i, src, dest_mode))
+ {
+ int validated;
+
+ /* Pop back to the real obstacks while changing the insn. */
+ pop_obstacks ();
+
+ validated = validate_change (insn, &SET_SRC (set),
+ gen_rtx (REG, dest_mode, i), 1);
+
+ /* Go back to the obstack we are using for temporary
+ storage. */
+ push_obstacks (&reload_obstack, &reload_obstack);
+
+ if (validated && ! find_regno_note (insn, REG_UNUSED, i))
+ {
+ reload_cse_no_longer_dead (i, dest_mode);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Try to replace operands in INSN with equivalent values that are already
+ in registers. This can be viewed as optional reloading.
+
+ For each non-register operand in the insn, see if any hard regs are
+ known to be equivalent to that operand. Record the alternatives which
+ can accept these hard registers. Among all alternatives, select the
+ ones which are better or equal to the one currently matching, where
+ "better" is in terms of '?' and '!' constraints. Among the remaining
+ alternatives, select the one which replaces most operands with
+ hard registers. */
+
+static int
+reload_cse_simplify_operands (insn)
+ rtx insn;
+{
+#ifdef REGISTER_CONSTRAINTS
+ int insn_code_number, n_operands, n_alternatives;
+ int i,j;
+
+ char *constraints[MAX_RECOG_OPERANDS];
+
+ /* Vector recording how bad an alternative is. */
+ int *alternative_reject;
+ /* Vector recording how many registers can be introduced by choosing
+ this alternative. */
+ int *alternative_nregs;
+ /* Array of vectors recording, for each operand and each alternative,
+ which hard register to substitute, or -1 if the operand should be
+ left as it is. */
+ int *op_alt_regno[MAX_RECOG_OPERANDS];
+ /* Array of alternatives, sorted in order of decreasing desirability. */
+ int *alternative_order;
+
+ /* Find out some information about this insn. */
+ insn_code_number = recog_memoized (insn);
+ /* We don't modify asm instructions. */
+ if (insn_code_number < 0)
+ return 0;
+
+ n_operands = insn_n_operands[insn_code_number];
+ n_alternatives = insn_n_alternatives[insn_code_number];
+
+ if (n_alternatives == 0 || n_operands == 0)
+ return;
+ insn_extract (insn);
+
+ /* Figure out which alternative currently matches. */
+ if (! constrain_operands (insn_code_number, 1))
+ abort ();
+
+ alternative_reject = (int *) alloca (n_alternatives * sizeof (int));
+ alternative_nregs = (int *) alloca (n_alternatives * sizeof (int));
+ alternative_order = (int *) alloca (n_alternatives * sizeof (int));
+ bzero ((char *)alternative_reject, n_alternatives * sizeof (int));
+ bzero ((char *)alternative_nregs, n_alternatives * sizeof (int));
+
+ for (i = 0; i < n_operands; i++)
+ {
+ enum machine_mode mode;
+ int regno;
+ char *p;
+
+ op_alt_regno[i] = (int *) alloca (n_alternatives * sizeof (int));
+ for (j = 0; j < n_alternatives; j++)
+ op_alt_regno[i][j] = -1;
+
+ p = constraints[i] = insn_operand_constraint[insn_code_number][i];
+ mode = insn_operand_mode[insn_code_number][i];
+
+ /* Add the reject values for each alternative given by the constraints
+ for this operand. */
+ j = 0;
+ while (*p != '\0')
+ {
+ char c = *p++;
+ if (c == ',')
+ j++;
+ else if (c == '?')
+ alternative_reject[j] += 3;
+ else if (c == '!')
+ alternative_reject[j] += 300;
+ }
+
+ /* We won't change operands which are already registers. We
+ also don't want to modify output operands. */
+ regno = true_regnum (recog_operand[i]);
+ if (regno >= 0
+ || constraints[i][0] == '='
+ || constraints[i][0] == '+')
+ continue;
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ {
+ int class = (int) NO_REGS;
+
+ if (! reload_cse_regno_equal_p (regno, recog_operand[i], mode))
+ continue;
+
+ /* We found a register equal to this operand. Now look for all
+ alternatives that can accept this register and have not been
+ assigned a register they can use yet. */
+ j = 0;
+ p = constraints[i];
+ for (;;)
+ {
+ char c = *p++;
+
+ switch (c)
+ {
+ case '=': case '+': case '?':
+ case '#': case '&': case '!':
+ case '*': case '%':
+ case '0': case '1': case '2': case '3': case '4':
+ case 'm': case '<': case '>': case 'V': case 'o':
+ case 'E': case 'F': case 'G': case 'H':
+ case 's': case 'i': case 'n':
+ case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P':
+#ifdef EXTRA_CONSTRAINT
+ case 'Q': case 'R': case 'S': case 'T': case 'U':
+#endif
+ case 'p': case 'X':
+ /* These don't say anything we care about. */
+ break;
+
+ case 'g': case 'r':
+ class = reg_class_subunion[(int) class][(int) GENERAL_REGS];
+ break;
+
+ default:
+ class
+ = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER (c)];
+ break;
+
+ case ',': case '\0':
+ /* See if REGNO fits this alternative, and set it up as the
+ replacement register if we don't have one for this
+ alternative yet. */
+ if (op_alt_regno[i][j] == -1
+ && reg_fits_class_p (gen_rtx (REG, mode, regno), class,
+ 0, mode))
+ {
+ alternative_nregs[j]++;
+ op_alt_regno[i][j] = regno;
+ }
+ j++;
+ break;
+ }
+
+ if (c == '\0')
+ break;
+ }
+ }
+ }
+
+ /* Record all alternatives which are better or equal to the currently
+ matching one in the alternative_order array. */
+ for (i = j = 0; i < n_alternatives; i++)
+ if (alternative_reject[i] <= alternative_reject[which_alternative])
+ alternative_order[j++] = i;
+ n_alternatives = j;
+
+ /* Sort it. Given a small number of alternatives, a dumb algorithm
+ won't hurt too much. */
+ for (i = 0; i < n_alternatives - 1; i++)
+ {
+ int best = i;
+ int best_reject = alternative_reject[alternative_order[i]];
+ int best_nregs = alternative_nregs[alternative_order[i]];
+ int tmp;
+
+ for (j = i + 1; j < n_alternatives; j++)
+ {
+ int this_reject = alternative_reject[alternative_order[j]];
+ int this_nregs = alternative_nregs[alternative_order[j]];
+
+ if (this_reject < best_reject
+ || (this_reject == best_reject && this_nregs < best_nregs))
+ {
+ best = j;
+ best_reject = this_reject;
+ best_nregs = this_nregs;
+ }
+ }
+
+ tmp = alternative_order[best];
+ alternative_order[best] = alternative_order[i];
+ alternative_order[i] = tmp;
+ }
+
+ /* Substitute the operands as determined by op_alt_regno for the best
+ alternative. */
+ j = alternative_order[0];
+ CLEAR_HARD_REG_SET (no_longer_dead_regs);
+
+ /* Pop back to the real obstacks while changing the insn. */
+ pop_obstacks ();
+
+ for (i = 0; i < n_operands; i++)
+ {
+ enum machine_mode mode = insn_operand_mode[insn_code_number][i];
+ if (op_alt_regno[i][j] == -1)
+ continue;
+
+ reload_cse_no_longer_dead (op_alt_regno[i][j], mode);
+ validate_change (insn, recog_operand_loc[i],
+ gen_rtx (REG, mode, op_alt_regno[i][j]), 1);
+ }
+
+ for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
+ {
+ int op = recog_dup_num[i];
+ enum machine_mode mode = insn_operand_mode[insn_code_number][op];
+
+ if (op_alt_regno[op][j] == -1)
+ continue;
+
+ reload_cse_no_longer_dead (op_alt_regno[op][j], mode);
+ validate_change (insn, recog_dup_loc[i],
+ gen_rtx (REG, mode, op_alt_regno[op][j]), 1);
+ }
+
+ /* Go back to the obstack we are using for temporary
+ storage. */
+ push_obstacks (&reload_obstack, &reload_obstack);
+
+ return apply_change_group ();
+#else
+ return 0;
+#endif
+}
+
+/* These two variables are used to pass information from
+ reload_cse_record_set to reload_cse_check_clobber. */
+
+static int reload_cse_check_clobbered;
+static rtx reload_cse_check_src;
+
+/* See if DEST overlaps with RELOAD_CSE_CHECK_SRC. If it does, set
+ RELOAD_CSE_CHECK_CLOBBERED. This is called via note_stores. The
+ second argument, which is passed by note_stores, is ignored. */
+
+static void
+reload_cse_check_clobber (dest, ignore)
+ rtx dest;
+ rtx ignore;
+{
+ if (reg_overlap_mentioned_p (dest, reload_cse_check_src))
+ reload_cse_check_clobbered = 1;
+}
+
+/* Record the result of a SET instruction. SET is the set pattern.
+ BODY is the pattern of the insn that it came from. */
+
+static void
+reload_cse_record_set (set, body)
+ rtx set;
+ rtx body;
+{
+ rtx dest, src, x;
+ int dreg, sreg;
+ enum machine_mode dest_mode;
+
+ dest = SET_DEST (set);
+ src = SET_SRC (set);
+ dreg = true_regnum (dest);
+ sreg = true_regnum (src);
+ dest_mode = GET_MODE (dest);
+
+ /* Some machines don't define AUTO_INC_DEC, but they still use push
+ instructions. We need to catch that case here in order to
+ invalidate the stack pointer correctly. Note that invalidating
+ the stack pointer is different from invalidating DEST. */
+ x = dest;
+ while (GET_CODE (x) == SUBREG
+ || GET_CODE (x) == ZERO_EXTRACT
+ || GET_CODE (x) == SIGN_EXTRACT
+ || GET_CODE (x) == STRICT_LOW_PART)
+ x = XEXP (x, 0);
+ if (push_operand (x, GET_MODE (x)))
+ {
+ reload_cse_invalidate_rtx (stack_pointer_rtx, NULL_RTX);
+ reload_cse_invalidate_rtx (dest, NULL_RTX);
+ return;
+ }
+
+ /* We can only handle an assignment to a register, or a store of a
+ register to a memory location. For other cases, we just clobber
+ the destination. We also have to just clobber if there are side
+ effects in SRC or DEST. */
+ if ((dreg < 0 && GET_CODE (dest) != MEM)
+ || side_effects_p (src)
+ || side_effects_p (dest))
+ {
+ reload_cse_invalidate_rtx (dest, NULL_RTX);
+ return;
+ }
+
+#ifdef HAVE_cc0
+ /* We don't try to handle values involving CC, because it's a pain
+ to keep track of when they have to be invalidated. */
+ if (reg_mentioned_p (cc0_rtx, src)
+ || reg_mentioned_p (cc0_rtx, dest))
+ {
+ reload_cse_invalidate_rtx (dest, NULL_RTX);
+ return;
+ }
+#endif
+
+ /* If BODY is a PARALLEL, then we need to see whether the source of
+ SET is clobbered by some other instruction in the PARALLEL. */
+ if (GET_CODE (body) == PARALLEL)
+ {
+ int i;
+
+ for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
+ {
+ rtx x;
+
+ x = XVECEXP (body, 0, i);
+ if (x == set)
+ continue;
+
+ reload_cse_check_clobbered = 0;
+ reload_cse_check_src = src;
+ note_stores (x, reload_cse_check_clobber);
+ if (reload_cse_check_clobbered)
+ {
+ reload_cse_invalidate_rtx (dest, NULL_RTX);
+ return;
+ }
+ }
+ }
+
+ if (dreg >= 0)
+ {
+ int i;
+
+ /* This is an assignment to a register. Update the value we
+ have stored for the register. */
+ if (sreg >= 0)
+ {
+ rtx x;
+
+ /* This is a copy from one register to another. Any values
+ which were valid for SREG are now valid for DREG. If the
+ mode changes, we use gen_lowpart_common to extract only
+ the part of the value that is copied. */
+ reg_values[dreg] = 0;
+ for (x = reg_values[sreg]; x; x = XEXP (x, 1))
+ {
+ rtx tmp;
+
+ if (XEXP (x, 0) == 0)
+ continue;
+ if (dest_mode == GET_MODE (XEXP (x, 0)))
+ tmp = XEXP (x, 0);
+ else if (GET_MODE_BITSIZE (dest_mode)
+ > GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
+ continue;
+ else
+ tmp = gen_lowpart_common (dest_mode, XEXP (x, 0));
+ if (tmp)
+ reg_values[dreg] = gen_rtx (EXPR_LIST, dest_mode, tmp,
+ reg_values[dreg]);
+ }
+ }
+ else
+ reg_values[dreg] = gen_rtx (EXPR_LIST, dest_mode, src, NULL_RTX);
+
+ /* We've changed DREG, so invalidate any values held by other
+ registers that depend upon it. */
+ reload_cse_invalidate_regno (dreg, dest_mode, 0);
+
+ /* If this assignment changes more than one hard register,
+ forget anything we know about the others. */
+ for (i = 1; i < HARD_REGNO_NREGS (dreg, dest_mode); i++)
+ reg_values[dreg + i] = 0;
+ }
+ else if (GET_CODE (dest) == MEM)
+ {
+ /* Invalidate conflicting memory locations. */
+ reload_cse_invalidate_mem (dest);
+
+ /* If we're storing a register to memory, add DEST to the list
+ in REG_VALUES. */
+ if (sreg >= 0 && ! side_effects_p (dest))
+ reg_values[sreg] = gen_rtx (EXPR_LIST, dest_mode, dest,
+ reg_values[sreg]);
+ }
+ else
+ {
+ /* We should have bailed out earlier. */
+ abort ();
+ }
+}
diff --git a/gnu/usr.bin/gcc/reorg.c b/gnu/usr.bin/gcc/reorg.c
index edd76d5d21b..1e828325e8f 100644
--- a/gnu/usr.bin/gcc/reorg.c
+++ b/gnu/usr.bin/gcc/reorg.c
@@ -1,5 +1,5 @@
/* Perform instruction reorganizations for delay slot filling.
- Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
Hacked by Michael Tiemann (tiemann@cygnus.com).
@@ -115,8 +115,8 @@ Boston, MA 02111-1307, USA. */
The HP-PA can conditionally nullify insns, providing a similar
effect to the ARM, differing mostly in which insn is "in charge". */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "insn-config.h"
#include "conditions.h"
@@ -130,6 +130,13 @@ Boston, MA 02111-1307, USA. */
#include "obstack.h"
#include "insn-attr.h"
+/* Import list of registers used as spill regs from reload. */
+extern HARD_REG_SET used_spill_regs;
+
+/* Import highest label used in function at end of reload. */
+extern int max_label_num_after_reload;
+
+
#ifdef DELAY_SLOTS
#define obstack_chunk_alloc xmalloc
@@ -163,8 +170,8 @@ static rtx *unfilled_firstobj;
struct resources
{
char memory; /* Insn sets or needs a memory location. */
- char unch_memory; /* Insn sets of needs a "unchanging" MEM. */
- char volatil; /* Insn sets or needs a volatile memory loc. */
+ char unch_memory; /* Insn sets of needs a "unchanging" MEM. */
+ char volatil; /* Insn sets or needs a volatile memory loc. */
char cc; /* Insn sets or needs the condition codes. */
HARD_REG_SET regs; /* Which registers are set or needed. */
};
@@ -252,6 +259,7 @@ static int find_basic_block PROTO((rtx));
static void update_block PROTO((rtx, rtx));
static int reorg_redirect_jump PROTO((rtx, rtx));
static void update_reg_dead_notes PROTO((rtx, rtx));
+static void fix_reg_dead_note PROTO((rtx, rtx));
static void update_reg_unused_notes PROTO((rtx, rtx));
static void update_live_status PROTO((rtx, rtx));
static rtx next_insn_no_annul PROTO((rtx));
@@ -328,6 +336,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
case UNSPEC_VOLATILE:
case ASM_INPUT:
+ case TRAP_IF:
/* Traditional asm's are always volatile. */
res->volatil = 1;
return;
@@ -386,7 +395,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
rtx next = NEXT_INSN (x);
int i;
- /* If we are part of a delay slot sequence, point at the SEQUENCE. */
+ /* If we are part of a delay slot sequence, point at the SEQUENCE. */
if (NEXT_INSN (insn) != x)
{
next = NEXT_INSN (NEXT_INSN (insn));
@@ -445,7 +454,7 @@ mark_referenced_resources (x, res, include_delayed_effects)
}
}
- /* ... fall through to other INSN processing ... */
+ /* ... fall through to other INSN processing ... */
case INSN:
case JUMP_INSN:
@@ -804,7 +813,7 @@ find_end_label ()
end_of_function_label = gen_label_rtx ();
LABEL_NUSES (end_of_function_label) = 0;
- /* Put the label before an USE insns that may proceed the RETURN insn. */
+ /* Put the label before an USE insns that may proceed the RETURN insn. */
while (GET_CODE (temp) == USE)
temp = PREV_INSN (temp);
@@ -861,14 +870,14 @@ emit_delay_sequence (insn, list, length, avail)
register rtx li;
int had_barrier = 0;
- /* Allocate the the rtvec to hold the insns and the SEQUENCE. */
+ /* Allocate the the rtvec to hold the insns and the SEQUENCE. */
rtvec seqv = rtvec_alloc (length + 1);
rtx seq = gen_rtx (SEQUENCE, VOIDmode, seqv);
rtx seq_insn = make_insn_raw (seq);
rtx first = get_insns ();
rtx last = get_last_insn ();
- /* Make a copy of the insn having delay slots. */
+ /* Make a copy of the insn having delay slots. */
rtx delay_insn = copy_rtx (insn);
/* If INSN is followed by a BARRIER, delete the BARRIER since it will only
@@ -885,15 +894,22 @@ emit_delay_sequence (insn, list, length, avail)
NEXT_INSN (seq_insn) = NEXT_INSN (insn);
PREV_INSN (seq_insn) = PREV_INSN (insn);
+ if (insn != last)
+ PREV_INSN (NEXT_INSN (seq_insn)) = seq_insn;
+
+ if (insn != first)
+ NEXT_INSN (PREV_INSN (seq_insn)) = seq_insn;
+
+ /* Note the calls to set_new_first_and_last_insn must occur after
+ SEQ_INSN has been completely spliced into the insn stream.
+
+ Otherwise CUR_INSN_UID will get set to an incorrect value because
+ set_new_first_and_last_insn will not find SEQ_INSN in the chain. */
if (insn == last)
set_new_first_and_last_insn (first, seq_insn);
- else
- PREV_INSN (NEXT_INSN (seq_insn)) = seq_insn;
if (insn == first)
set_new_first_and_last_insn (seq_insn, last);
- else
- NEXT_INSN (PREV_INSN (seq_insn)) = seq_insn;
/* Build our SEQUENCE and rebuild the insn chain. */
XVECEXP (seq, 0, 0) = delay_insn;
@@ -1218,6 +1234,7 @@ optimize_skip (insn)
Non conditional branches return no direction information and
are predicted as very likely taken. */
+
static int
get_jump_flags (insn, label)
rtx insn, label;
@@ -1340,6 +1357,26 @@ mostly_true_jump (jump_insn, condition)
int rare_dest = rare_destination (target_label);
int rare_fallthrough = rare_destination (NEXT_INSN (jump_insn));
+ /* If branch probabilities are available, then use that number since it
+ always gives a correct answer. */
+ if (flag_branch_probabilities)
+ {
+ rtx note = find_reg_note (jump_insn, REG_BR_PROB, 0);;
+ if (note)
+ {
+ int prob = XINT (note, 0);
+
+ if (prob >= REG_BR_PROB_BASE * 9 / 10)
+ return 2;
+ else if (prob >= REG_BR_PROB_BASE / 2)
+ return 1;
+ else if (prob >= REG_BR_PROB_BASE / 10)
+ return 0;
+ else
+ return -1;
+ }
+ }
+
/* If this is a branch outside a loop, it is highly unlikely. */
if (GET_CODE (PATTERN (jump_insn)) == SET
&& GET_CODE (SET_SRC (PATTERN (jump_insn))) == IF_THEN_ELSE
@@ -1373,7 +1410,7 @@ mostly_true_jump (jump_insn, condition)
}
/* Look at the relative rarities of the fallthrough and destination. If
- they differ, we can predict the branch that way. */
+ they differ, we can predict the branch that way. */
switch (rare_fallthrough - rare_dest)
{
@@ -1960,6 +1997,11 @@ redundant_insn (insn, target, delay_list)
struct resources needed, set;
int i;
+ /* If INSN has any REG_UNUSED notes, it can't match anything since we
+ are allowed to not actually assign to such a register. */
+ if (find_reg_note (insn, REG_UNUSED, NULL_RTX) != 0)
+ return 0;
+
/* Scan backwards looking for a match. */
for (trial = PREV_INSN (target); trial; trial = PREV_INSN (trial))
{
@@ -1998,7 +2040,8 @@ redundant_insn (insn, target, delay_list)
resource requirements as we go. */
for (i = XVECLEN (pat, 0) - 1; i > 0; i--)
if (GET_CODE (XVECEXP (pat, 0, i)) == GET_CODE (insn)
- && rtx_equal_p (PATTERN (XVECEXP (pat, 0, i)), ipat))
+ && rtx_equal_p (PATTERN (XVECEXP (pat, 0, i)), ipat)
+ && ! find_reg_note (XVECEXP (pat, 0, i), REG_UNUSED, NULL_RTX))
break;
/* If found a match, exit this loop early. */
@@ -2006,7 +2049,8 @@ redundant_insn (insn, target, delay_list)
break;
}
- else if (GET_CODE (trial) == GET_CODE (insn) && rtx_equal_p (pat, ipat))
+ else if (GET_CODE (trial) == GET_CODE (insn) && rtx_equal_p (pat, ipat)
+ && ! find_reg_note (trial, REG_UNUSED, NULL_RTX))
break;
}
@@ -2304,6 +2348,38 @@ update_reg_dead_notes (insn, delayed_insn)
}
}
+/* Called when an insn redundant with start_insn is deleted. If there
+ is a REG_DEAD note for the target of start_insn between start_insn
+ and stop_insn, then the REG_DEAD note needs to be deleted since the
+ value no longer dies there.
+
+ If the REG_DEAD note isn't deleted, then mark_target_live_regs may be
+ confused into thinking the register is dead. */
+
+static void
+fix_reg_dead_note (start_insn, stop_insn)
+ rtx start_insn, stop_insn;
+{
+ rtx p, link, next;
+
+ for (p = next_nonnote_insn (start_insn); p != stop_insn;
+ p = next_nonnote_insn (p))
+ for (link = REG_NOTES (p); link; link = next)
+ {
+ next = XEXP (link, 1);
+
+ if (REG_NOTE_KIND (link) != REG_DEAD
+ || GET_CODE (XEXP (link, 0)) != REG)
+ continue;
+
+ if (reg_set_p (XEXP (link, 0), PATTERN (start_insn)))
+ {
+ remove_note (p, link);
+ return;
+ }
+ }
+}
+
/* Delete any REG_UNUSED notes that exist on INSN but not on REDUNDANT_INSN.
This handles the case of udivmodXi4 instructions which optimize their
@@ -2399,6 +2475,188 @@ next_insn_no_annul (insn)
return insn;
}
+/* A subroutine of mark_target_live_regs. Search forward from TARGET
+ looking for registers that are set before they are used. These are dead.
+ Stop after passing a few conditional jumps, and/or a small
+ number of unconditional branches. */
+
+static rtx
+find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
+ rtx target;
+ struct resources *res;
+ rtx *jump_target;
+ int jump_count;
+ struct resources set, needed;
+{
+ HARD_REG_SET scratch;
+ rtx insn, next;
+ rtx jump_insn = 0;
+ int i;
+
+ for (insn = target; insn; insn = next)
+ {
+ rtx this_jump_insn = insn;
+
+ next = NEXT_INSN (insn);
+ switch (GET_CODE (insn))
+ {
+ case CODE_LABEL:
+ /* After a label, any pending dead registers that weren't yet
+ used can be made dead. */
+ AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs);
+ AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
+ CLEAR_HARD_REG_SET (pending_dead_regs);
+
+ if (CODE_LABEL_NUMBER (insn) < max_label_num_after_reload)
+ {
+ /* All spill registers are dead at a label, so kill all of the
+ ones that aren't needed also. */
+ COPY_HARD_REG_SET (scratch, used_spill_regs);
+ AND_COMPL_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (res->regs, scratch);
+ }
+ continue;
+
+ case BARRIER:
+ case NOTE:
+ continue;
+
+ case INSN:
+ if (GET_CODE (PATTERN (insn)) == USE)
+ {
+ /* If INSN is a USE made by update_block, we care about the
+ underlying insn. Any registers set by the underlying insn
+ are live since the insn is being done somewhere else. */
+ if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
+ mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1);
+
+ /* All other USE insns are to be ignored. */
+ continue;
+ }
+ else if (GET_CODE (PATTERN (insn)) == CLOBBER)
+ continue;
+ else if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+ /* An unconditional jump can be used to fill the delay slot
+ of a call, so search for a JUMP_INSN in any position. */
+ for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+ {
+ this_jump_insn = XVECEXP (PATTERN (insn), 0, i);
+ if (GET_CODE (this_jump_insn) == JUMP_INSN)
+ break;
+ }
+ }
+ }
+
+ if (GET_CODE (this_jump_insn) == JUMP_INSN)
+ {
+ if (jump_count++ < 10)
+ {
+ if (simplejump_p (this_jump_insn)
+ || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
+ {
+ next = JUMP_LABEL (this_jump_insn);
+ if (jump_insn == 0)
+ {
+ jump_insn = insn;
+ if (jump_target)
+ *jump_target = JUMP_LABEL (this_jump_insn);
+ }
+ }
+ else if (condjump_p (this_jump_insn)
+ || condjump_in_parallel_p (this_jump_insn))
+ {
+ struct resources target_set, target_res;
+ struct resources fallthrough_res;
+
+ /* We can handle conditional branches here by following
+ both paths, and then IOR the results of the two paths
+ together, which will give us registers that are dead
+ on both paths. Since this is expensive, we give it
+ a much higher cost than unconditional branches. The
+ cost was chosen so that we will follow at most 1
+ conditional branch. */
+
+ jump_count += 4;
+ if (jump_count >= 10)
+ break;
+
+ mark_referenced_resources (insn, &needed, 1);
+
+ /* For an annulled branch, mark_set_resources ignores slots
+ filled by instructions from the target. This is correct
+ if the branch is not taken. Since we are following both
+ paths from the branch, we must also compute correct info
+ if the branch is taken. We do this by inverting all of
+ the INSN_FROM_TARGET_P bits, calling mark_set_resources,
+ and then inverting the INSN_FROM_TARGET_P bits again. */
+
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE
+ && INSN_ANNULLED_BRANCH_P (this_jump_insn))
+ {
+ for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
+ INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
+ = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
+
+ target_set = set;
+ mark_set_resources (insn, &target_set, 0, 1);
+
+ for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
+ INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
+ = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
+
+ mark_set_resources (insn, &set, 0, 1);
+ }
+ else
+ {
+ mark_set_resources (insn, &set, 0, 1);
+ target_set = set;
+ }
+
+ target_res = *res;
+ COPY_HARD_REG_SET (scratch, target_set.regs);
+ AND_COMPL_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (target_res.regs, scratch);
+
+ fallthrough_res = *res;
+ COPY_HARD_REG_SET (scratch, set.regs);
+ AND_COMPL_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (fallthrough_res.regs, scratch);
+
+ find_dead_or_set_registers (JUMP_LABEL (this_jump_insn),
+ &target_res, 0, jump_count,
+ target_set, needed);
+ find_dead_or_set_registers (next,
+ &fallthrough_res, 0, jump_count,
+ set, needed);
+ IOR_HARD_REG_SET (fallthrough_res.regs, target_res.regs);
+ AND_HARD_REG_SET (res->regs, fallthrough_res.regs);
+ break;
+ }
+ else
+ break;
+ }
+ else
+ {
+ /* Don't try this optimization if we expired our jump count
+ above, since that would mean there may be an infinite loop
+ in the function being compiled. */
+ jump_insn = 0;
+ break;
+ }
+ }
+
+ mark_referenced_resources (insn, &needed, 1);
+ mark_set_resources (insn, &set, 0, 1);
+
+ COPY_HARD_REG_SET (scratch, set.regs);
+ AND_COMPL_HARD_REG_SET (scratch, needed.regs);
+ AND_COMPL_HARD_REG_SET (res->regs, scratch);
+ }
+
+ return jump_insn;
+}
+
/* Set the resources that are live at TARGET.
If TARGET is zero, we refer to the end of the current function and can
@@ -2509,8 +2767,7 @@ mark_target_live_regs (target, res)
if (b != -1)
{
regset regs_live = basic_block_live_at_start[b];
- int offset, j;
- REGSET_ELT_TYPE bit;
+ int j;
int regno;
rtx start_insn, stop_insn;
@@ -2518,26 +2775,18 @@ mark_target_live_regs (target, res)
marked live, plus live pseudo regs that have been renumbered to
hard regs. */
-#ifdef HARD_REG_SET
- current_live_regs = *regs_live;
-#else
- COPY_HARD_REG_SET (current_live_regs, regs_live);
-#endif
+ REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
- 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 (current_live_regs, j);
- }
+ EXECUTE_IF_SET_IN_REG_SET
+ (regs_live, FIRST_PSEUDO_REGISTER, i,
+ {
+ if ((regno = reg_renumber[i]) >= 0)
+ for (j = regno;
+ j < regno + HARD_REGNO_NREGS (regno,
+ PSEUDO_REGNO_MODE (i));
+ j++)
+ SET_HARD_REG_BIT (current_live_regs, j);
+ });
/* Get starting and ending insn, handling the case where each might
be a SEQUENCE. */
@@ -2669,92 +2918,18 @@ mark_target_live_regs (target, res)
in use. This should happen only extremely rarely. */
SET_HARD_REG_SET (res->regs);
- /* Now step forward from TARGET looking for registers that are set before
- they are used. These are dead. If we pass a label, any pending dead
- registers that weren't yet used can be made dead. Stop when we pass a
- conditional JUMP_INSN; follow the first few unconditional branches. */
-
CLEAR_RESOURCE (&set);
CLEAR_RESOURCE (&needed);
- for (insn = target; insn; insn = next)
- {
- rtx this_jump_insn = insn;
-
- next = NEXT_INSN (insn);
- switch (GET_CODE (insn))
- {
- case CODE_LABEL:
- AND_COMPL_HARD_REG_SET (pending_dead_regs, needed.regs);
- AND_COMPL_HARD_REG_SET (res->regs, pending_dead_regs);
- CLEAR_HARD_REG_SET (pending_dead_regs);
- continue;
-
- case BARRIER:
- case NOTE:
- continue;
-
- case INSN:
- if (GET_CODE (PATTERN (insn)) == USE)
- {
- /* If INSN is a USE made by update_block, we care about the
- underlying insn. Any registers set by the underlying insn
- are live since the insn is being done somewhere else. */
- if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
- mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1);
-
- /* All other USE insns are to be ignored. */
- continue;
- }
- else if (GET_CODE (PATTERN (insn)) == CLOBBER)
- continue;
- else if (GET_CODE (PATTERN (insn)) == SEQUENCE)
- {
- /* An unconditional jump can be used to fill the delay slot
- of a call, so search for a JUMP_INSN in any position. */
- for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- {
- this_jump_insn = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (this_jump_insn) == JUMP_INSN)
- break;
- }
- }
- }
-
- if (GET_CODE (this_jump_insn) == JUMP_INSN)
- {
- if (jump_count++ < 10
- && (simplejump_p (this_jump_insn)
- || GET_CODE (PATTERN (this_jump_insn)) == RETURN))
- {
- next = next_active_insn (JUMP_LABEL (this_jump_insn));
- if (jump_insn == 0)
- {
- jump_insn = insn;
- jump_target = JUMP_LABEL (this_jump_insn);
- }
- }
- else
- break;
- }
-
- mark_referenced_resources (insn, &needed, 1);
- mark_set_resources (insn, &set, 0, 1);
-
- COPY_HARD_REG_SET (scratch, set.regs);
- AND_COMPL_HARD_REG_SET (scratch, needed.regs);
- AND_COMPL_HARD_REG_SET (res->regs, scratch);
- }
+ jump_insn = find_dead_or_set_registers (target, res, &jump_target, 0,
+ set, needed);
/* If we hit an unconditional branch, we have another way of finding out
what is live: we can see what is live at the branch target and include
anything used but not set before the branch. The only things that are
- live are those that are live using the above test and the test below.
-
- Don't try this if we expired our jump count above, since that would
- mean there may be an infinite loop in the function being compiled. */
+ live are those that are live using the above test and the test below. */
- if (jump_insn && jump_count < 10)
+ if (jump_insn)
{
struct resources new_resources;
rtx stop_insn = next_active_insn (jump_insn);
@@ -2804,7 +2979,7 @@ fill_simple_delay_slots (first, non_jumps_p)
register int i, j;
int num_unfilled_slots = unfilled_slots_next - unfilled_slots_base;
struct resources needed, set;
- register int slots_to_fill, slots_filled;
+ int slots_to_fill, slots_filled;
rtx delay_list;
for (i = 0; i < num_unfilled_slots; i++)
@@ -3136,6 +3311,19 @@ fill_simple_delay_slots (first, non_jumps_p)
}
}
+ /* If this is an unconditional jump, then try to get insns from the
+ target of the jump. */
+ if (GET_CODE (insn) == JUMP_INSN
+ && simplejump_p (insn)
+ && slots_filled != slots_to_fill)
+ delay_list
+ = fill_slots_from_thread (insn, const_true_rtx,
+ next_active_insn (JUMP_LABEL (insn)),
+ NULL, 1, 1,
+ own_thread_p (JUMP_LABEL (insn),
+ JUMP_LABEL (insn), 0),
+ 0, slots_to_fill, &slots_filled);
+
if (delay_list)
unfilled_slots_base[i]
= emit_delay_sequence (insn, delay_list,
@@ -3181,6 +3369,14 @@ fill_simple_delay_slots (first, non_jumps_p)
else
SET_HARD_REG_BIT (needed.regs, STACK_POINTER_REGNUM);
+#ifdef EPILOGUE_USES
+ for (i = 0; i <FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (EPILOGUE_USES (i))
+ SET_HARD_REG_BIT (needed.regs, i);
+ }
+#endif
+
for (trial = get_last_insn (); ! stop_search_p (trial, 1);
trial = PREV_INSN (trial))
{
@@ -3347,6 +3543,7 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
we did. */
if (prior_insn = redundant_insn (trial, insn, delay_list))
{
+ fix_reg_dead_note (prior_insn, insn);
if (own_thread)
{
update_block (trial, thread);
@@ -3422,6 +3619,12 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
if (own_thread)
{
update_block (trial, thread);
+ if (trial == thread)
+ {
+ thread = next_active_insn (thread);
+ if (new_thread == trial)
+ new_thread = thread;
+ }
delete_insn (trial);
}
else
@@ -3524,7 +3727,10 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
depend on the destination register. If so, try to place the opposite
arithmetic insn after the jump insn and put the arithmetic insn in the
delay slot. If we can't do this, return. */
- if (delay_list == 0 && likely && new_thread && GET_CODE (new_thread) == INSN)
+ if (delay_list == 0 && likely && new_thread
+ && GET_CODE (new_thread) == INSN
+ && GET_CODE (PATTERN (new_thread)) != ASM_INPUT
+ && asm_noperands (PATTERN (new_thread)) < 0)
{
rtx pat = PATTERN (new_thread);
rtx dest;
@@ -3570,6 +3776,12 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
if (own_thread)
{
update_block (trial, thread);
+ if (trial == thread)
+ {
+ thread = next_active_insn (thread);
+ if (new_thread == trial)
+ new_thread = thread;
+ }
delete_insn (trial);
}
else
@@ -3903,11 +4115,20 @@ relax_delay_slots (first)
if (trial && GET_CODE (PATTERN (trial)) != SEQUENCE
&& redundant_insn (trial, insn, 0))
{
- trial = next_active_insn (trial);
- if (trial == 0)
- target_label = find_end_label ();
- else
- target_label = get_label_before (trial);
+ rtx tmp;
+
+ /* Figure out where to emit the special USE insn so we don't
+ later incorrectly compute register live/death info. */
+ tmp = next_active_insn (trial);
+ if (tmp == 0)
+ tmp = find_end_label ();
+
+ /* Insert the special USE insn and update dataflow info. */
+ update_block (trial, tmp);
+
+ /* Now emit a label before the special USE insn, and
+ redirect our jump to the new label. */
+ target_label = get_label_before (PREV_INSN (tmp));
reorg_redirect_jump (delay_insn, target_label);
next = insn;
continue;
@@ -4271,13 +4492,16 @@ dbr_schedule (first, file)
else
SET_HARD_REG_BIT (end_of_function_needs.regs, STACK_POINTER_REGNUM);
- if (current_function_return_rtx != 0
- && GET_CODE (current_function_return_rtx) == REG)
+ if (current_function_return_rtx != 0)
mark_referenced_resources (current_function_return_rtx,
&end_of_function_needs, 1);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (global_regs[i])
+ if (global_regs[i]
+#ifdef EPILOGUE_USES
+ || EPILOGUE_USES (i)
+#endif
+ )
SET_HARD_REG_BIT (end_of_function_needs.regs, i);
/* The registers required to be live at the end of the function are
diff --git a/gnu/usr.bin/gcc/rtl.c b/gnu/usr.bin/gcc/rtl.c
index 3063d3e67f4..b5602437c8c 100644
--- a/gnu/usr.bin/gcc/rtl.c
+++ b/gnu/usr.bin/gcc/rtl.c
@@ -1,5 +1,5 @@
/* Allocate and read RTL for GNU C Compiler.
- Copyright (C) 1987, 1988, 1991, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -172,14 +172,20 @@ char *note_insn_name[] = { 0 , "NOTE_INSN_DELETED",
"NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
"NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
"NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
- "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG"};
+ "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
+ "NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
+ "NOTE_REPEATED_LINE_NUMBER" };
char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
"REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
"REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
"REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
- "REG_DEP_ANTI", "REG_DEP_OUTPUT" };
+ "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
+ "REG_EXEC_COUNT" };
+static void dump_and_abort PROTO((int, int, FILE *));
+static void read_name PROTO((char *, FILE *));
+
/* Allocate an rtx vector of N elements.
Store the length, and initialize all elements to zero. */
@@ -195,9 +201,10 @@ rtvec_alloc (n)
+ (( n - 1) * sizeof (rtunion)));
/* clear out the vector */
- PUT_NUM_ELEM(rt, n);
- for (i=0; i < n; i++)
- rt->elem[i].rtvec = NULL; /* @@ not portable due to rtunion */
+ PUT_NUM_ELEM (rt, n);
+
+ for (i = 0; i < n; i++)
+ rt->elem[i].rtwint = 0;
return rt;
}
@@ -278,7 +285,8 @@ copy_rtx (orig)
case PC:
case CC0:
case SCRATCH:
- /* SCRATCH must be shared because they represent distinct values. */
+ /* SCRATCH must be shared because they represent distinct values. */
+ case ADDRESSOF:
return orig;
case CONST:
@@ -294,6 +302,9 @@ copy_rtx (orig)
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. */
+
+ default:
+ break;
}
copy = rtx_alloc (code);
@@ -380,6 +391,8 @@ copy_most_rtx (orig, may_share)
case PC:
case CC0:
return orig;
+ default:
+ break;
}
copy = rtx_alloc (code);
@@ -838,14 +851,3 @@ init_rtl ()
}
}
}
-
-#ifdef memset
-gcc_memset (dest, value, len)
- char *dest;
- int value;
- int len;
-{
- while (len-- > 0)
- *dest++ = value;
-}
-#endif /* memset */
diff --git a/gnu/usr.bin/gcc/rtl.def b/gnu/usr.bin/gcc/rtl.def
index acb3a7dcae8..12c9c3b9be9 100644
--- a/gnu/usr.bin/gcc/rtl.def
+++ b/gnu/usr.bin/gcc/rtl.def
@@ -1,7 +1,7 @@
/* This file contains the definitions and documentation for the
Register Transfer Expressions (rtx's) that make up the
Register Transfer Language (rtl) used in the Back End of the GNU compiler.
- Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92, 94, 95, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -102,7 +102,7 @@ DEF_RTL_EXPR(INSN_LIST, "insn_list", "ue", 'x')
'=' to indicate the operand is only written to.
'+' to indicate the operand is both read and written to.
- Each character in the string represents an allocatable class for an operand.
+ Each character in the string represents an allocable class for an operand.
'g' indicates the operand can be any valid class.
'i' indicates the operand can be immediate (in the instruction) data.
'r' indicates the operand can be in a register.
@@ -257,7 +257,7 @@ DEF_RTL_EXPR(DEFINE_DELAY, "define_delay", "eE", 'x')
unit with no issue constraints. If only one operation can
be executed a time and the unit is busy for the entire time,
the 3rd operand should be specified as 1, the 6th operand
- sould be specified as 0, and the 7th operand should not
+ should be specified as 0, and the 7th operand should not
be specified.
If this operand is specified, it is a list of attribute
@@ -385,7 +385,7 @@ DEF_RTL_EXPR(NOTE, "note", "iuusn", 'x')
it contains helps to build the mapping function between the rtx's of
the function to be inlined and the current function being expanded. */
-DEF_RTL_EXPR(INLINE_HEADER, "inline_header", "iuuuiiiiiieeiiEe", 'x')
+DEF_RTL_EXPR(INLINE_HEADER, "inline_header", "iuuuiiiiiieeiiEeEsse", 'x')
/* ----------------------------------------------------------------------
Top level constituents of INSN, JUMP_INSN and CALL_INSN.
@@ -571,6 +571,15 @@ DEF_RTL_EXPR(SYMBOL_REF, "symbol_ref", "s", 'o')
pretend to be looking at the entire value and comparing it. */
DEF_RTL_EXPR(CC0, "cc0", "", 'o')
+/* Reference to the address of a register. Removed by purge_addressof after
+ CSE has elided as many as possible.
+ 1st operand: the register we may need the address of.
+ 2nd operand: the original pseudo regno we were generated for.
+ 3rd operand: the decl for the object in the register, for
+ put_reg_in_stack. */
+
+DEF_RTL_EXPR(ADDRESSOF, "addressof", "ei0", 'o')
+
/* =====================================================================
A QUEUED expression really points to a member of the queue of instructions
to be output later for postincrement/postdecrement.
@@ -760,6 +769,5 @@ DEF_RTL_EXPR(LO_SUM, "lo_sum", "ee", 'o')
/*
Local variables:
mode:c
-version-control: t
End:
*/
diff --git a/gnu/usr.bin/gcc/rtl.texi b/gnu/usr.bin/gcc/rtl.texi
index 1e1f5b71a4d..b815e12d365 100644
--- a/gnu/usr.bin/gcc/rtl.texi
+++ b/gnu/usr.bin/gcc/rtl.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 1989, 1992, 1994 Free Software Foundation, Inc.
+@c Copyright (C) 1988, 1989, 1992, 1994, 1997 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -1212,6 +1212,14 @@ by incrementing it, but there is no need to mention this in the RTL.
This RTX represents a reference to main memory at an address
represented by the expression @var{addr}. @var{m} specifies how large
a unit of memory is accessed.
+
+@findex addressof
+@item (addressof:@var{m} @var{reg})
+This RTX represents a request for the address of register @var{reg}. Its mode
+is always @code{Pmode}. If there are any @code{addressof}
+expressions left in the function after CSE, @var{reg} is forced into the
+stack and the @code{addressof} expression is replaced with a @code{plus}
+expression for the address of its stack slot.
@end table
@node Arithmetic, Comparisons, Regs and Memory, RTL
@@ -1584,7 +1592,8 @@ option @code{BITS_BIG_ENDIAN} says which end of the memory unit
If @var{loc} is in memory, its mode must be a single-byte integer mode.
If @var{loc} is in a register, the mode to use is specified by the
operand of the @code{insv} or @code{extv} pattern
-(@pxref{Standard Names}) and is usually a full-word integer mode.
+(@pxref{Standard Names}) and is usually a full-word integer mode,
+which is the default if none is specified.
The mode of @var{pos} is machine-specific and is also specified
in the @code{insv} or @code{extv} pattern.
@@ -2290,6 +2299,14 @@ These types of notes indicate the position of the beginning and end
of a level of scoping of variable names. They control the output
of debugging information.
+@findex NOTE_INSN_EH_REGION_BEG
+@findex NOTE_INSN_EH_REGION_END
+@item NOTE_INSN_EH_REGION_BEG
+@itemx NOTE_INSN_EH_REGION_END
+These types of notes indicate the position of the beginning and end of a
+level of scoping for exception handling. @code{NOTE_BLOCK_NUMBER}
+identifies which @code{CODE_LABEL} is associated with the given region.
+
@findex NOTE_INSN_LOOP_BEG
@findex NOTE_INSN_LOOP_END
@item NOTE_INSN_LOOP_BEG
@@ -2376,8 +2393,8 @@ nor a label may come between the related insns.
@findex REG_NOTES
@item REG_NOTES (@var{i})
A list (chain of @code{expr_list} and @code{insn_list} expressions)
-giving miscellaneous information about the insn. It is often information
-pertaining to the registers used in this insn.
+giving miscellaneous information about the insn. It is often
+information pertaining to the registers used in this insn.
@end table
The @code{LOG_LINKS} field of an insn is a chain of @code{insn_list}
@@ -2402,11 +2419,11 @@ mode @code{VOIDmode}.
The @code{REG_NOTES} field of an insn is a chain similar to the
@code{LOG_LINKS} field but it includes @code{expr_list} expressions in
-addition to @code{insn_list} expressions. There are several kinds
-of register notes, which are distinguished by the machine mode, which
-in a register note is really understood as being an @code{enum reg_note}.
+addition to @code{insn_list} expressions. There are several kinds of
+register notes, which are distinguished by the machine mode, which in a
+register note is really understood as being an @code{enum reg_note}.
The first operand @var{op} of the note is data whose meaning depends on
-the kind of note.
+the kind of note.
@findex REG_NOTE_KIND
@findex PUT_REG_NOTE_KIND
@@ -2504,6 +2521,17 @@ slot where the parameter was passed. Although in this case the register
may be set by other insns, it is still valid to replace the register
by the stack slot throughout the function.
+A @code{REG_EQUIV} note is also used on an instruction which copies a
+register parameter into a pseudo-register at entry to a function, if
+there is a stack slot where that parameter could be stored. Although
+other insns may set the pseudo-register, it is valid for the compiler to
+replace the pseudo-register by stack slot throughout the function,
+provided the compiler ensures that the stack slot is properly
+initialized by making the replacement in the initial copy instruction as
+well. This is used on machines for which the calling convention
+allocates stack space for register parameters. See
+@code{REG_PARM_STACK_SPACE} in @ref{Stack Arguments}.
+
In the case of @code{REG_EQUAL}, the register that is set by this insn
will be equal to @var{op} at run time at the end of this insn but not
necessarily elsewhere in the function. In this case, @var{op}
@@ -2604,6 +2632,25 @@ This indicates an anti dependence (a write after read dependence).
This indicates an output dependence (a write after write dependence).
@end table
+These notes describe information gathered from gcov profile data. They
+are stored in the @code{REG_NOTES} field of an insn as an
+@code{expr_list}.
+
+@table @code
+@findex REG_EXEC_COUNT
+@item REG_EXEC_COUNT
+This is used to indicate the number of times a basic block was executed
+according to the profile data. The note is attached to the first insn in
+the basic block.
+
+@findex REG_BR_PROB
+@item REG_BR_PROB
+This is used to specify the ratio of branches to non-branches of a
+branch insn according to the profile data. The value is stored as a
+value between 0 and REG_BR_PROB_BASE; larger values indicate a higher
+probability that the branch will be taken.
+@end table
+
For convenience, the machine mode in an @code{insn_list} or
@code{expr_list} is printed using these symbolic codes in debugging dumps.
diff --git a/gnu/usr.bin/gcc/rtlanal.c b/gnu/usr.bin/gcc/rtlanal.c
index 17cfd36201f..d311652d2ef 100644
--- a/gnu/usr.bin/gcc/rtlanal.c
+++ b/gnu/usr.bin/gcc/rtlanal.c
@@ -1,5 +1,5 @@
/* Analyze RTL for C-Compiler
- Copyright (C) 1987, 88, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -20,10 +20,14 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
-void note_stores ();
-int reg_set_p ();
+static int rtx_addr_can_trap_p PROTO((rtx));
+
+
+/* Forward declarations */
+static int jmp_uses_reg_or_mem PROTO((rtx));
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
@@ -105,6 +109,9 @@ rtx_varies_p (x)
/* The operand 0 of a LO_SUM is considered constant
(in fact is it related specifically to operand 1). */
return rtx_varies_p (XEXP (x, 1));
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -117,7 +124,7 @@ rtx_varies_p (x)
/* Return 0 if the use of X as an address in a MEM can cause a trap. */
-int
+static int
rtx_addr_can_trap_p (x)
register rtx x;
{
@@ -149,6 +156,9 @@ rtx_addr_can_trap_p (x)
case LO_SUM:
return rtx_addr_can_trap_p (XEXP (x, 1));
+
+ default:
+ break;
}
/* If it isn't one of the case above, it can cause a trap. */
@@ -177,8 +187,17 @@ rtx_addr_varies_p (x)
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (fmt[i] == 'e')
- if (rtx_addr_varies_p (XEXP (x, i)))
- return 1;
+ {
+ if (rtx_addr_varies_p (XEXP (x, i)))
+ return 1;
+ }
+ else if (fmt[i] == 'E')
+ {
+ int j;
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (rtx_addr_varies_p (XVECEXP (x, i, j)))
+ return 1;
+ }
return 0;
}
@@ -265,6 +284,9 @@ reg_mentioned_p (reg, in)
case CONST_DOUBLE:
/* These are kept unique for a given value. */
return 0;
+
+ default:
+ break;
}
if (GET_CODE (reg) == code && rtx_equal_p (reg, in))
@@ -355,13 +377,13 @@ reg_referenced_p (x, body)
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
&& reg_overlap_mentioned_p (x, SET_DEST (body)))
return 1;
- break;
+ return 0;
case ASM_OPERANDS:
for (i = ASM_OPERANDS_INPUT_LENGTH (body) - 1; i >= 0; i--)
if (reg_overlap_mentioned_p (x, ASM_OPERANDS_INPUT (body, i)))
return 1;
- break;
+ return 0;
case CALL:
case USE:
@@ -376,15 +398,16 @@ reg_referenced_p (x, body)
for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
if (reg_referenced_p (x, XVECEXP (body, 0, i)))
return 1;
- break;
+ return 0;
+
+ default:
+ return 0;
}
-
- return 0;
}
/* Nonzero if register REG is referenced in an insn between
FROM_INSN and TO_INSN (exclusive of those two). Sets of REG do
- not count. */
+ not count. */
int
reg_referenced_between_p (reg, from_insn, to_insn)
@@ -430,7 +453,7 @@ static int reg_set_flag;
static void
reg_set_p_1 (x, pat)
- rtx x;
+ rtx x, pat;
{
/* We don't want to return 1 if X is a MEM that contains a register
within REG_SET_REG. */
@@ -508,6 +531,9 @@ modified_between_p (x, start, end)
case REG:
return reg_set_between_p (x, start, end);
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -560,6 +586,9 @@ modified_in_p (x, insn)
case REG:
return reg_set_p (x, insn);
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -740,6 +769,9 @@ refers_to_regno_p (regno, endregno, x, loc)
return 0;
x = SET_SRC (x);
goto repeat;
+
+ default:
+ break;
}
/* X does not match, so try its subexpressions. */
@@ -915,7 +947,7 @@ reg_set_last (x, insn)
return 0;
}
-/* This is 1 until after reload pass. */
+/* This is 1 until after the rtl generation pass. */
int rtx_equal_function_value_matters;
/* Return 1 if X and Y are identical-looking rtx's.
@@ -1395,6 +1427,9 @@ volatile_insn_p (x)
case ASM_OPERANDS:
if (MEM_VOLATILE_P (x))
return 1;
+
+ default:
+ break;
}
/* Recursively scan the operands of this expression. */
@@ -1458,6 +1493,9 @@ volatile_refs_p (x)
case ASM_OPERANDS:
if (MEM_VOLATILE_P (x))
return 1;
+
+ default:
+ break;
}
/* Recursively scan the operands of this expression. */
@@ -1530,6 +1568,9 @@ side_effects_p (x)
case ASM_OPERANDS:
if (MEM_VOLATILE_P (x))
return 1;
+
+ default:
+ break;
}
/* Recursively scan the operands of this expression. */
@@ -1598,16 +1639,20 @@ may_trap_p (x)
case MOD:
case UDIV:
case UMOD:
- if (! CONSTANT_P (XEXP (x, 1)))
+ if (! CONSTANT_P (XEXP (x, 1))
+ || GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
return 1;
/* This was const0_rtx, but by not using that,
we can link this file into other programs. */
if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0)
return 1;
+ break;
+
case EXPR_LIST:
/* An EXPR_LIST is used to represent a function call. This
certainly may trap. */
return 1;
+
default:
/* Any floating arithmetic may trap. */
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
@@ -1666,6 +1711,9 @@ inequality_comparisons_p (x)
case GE:
case GEU:
return 1;
+
+ default:
+ break;
}
len = GET_RTX_LENGTH (code);
@@ -1821,6 +1869,9 @@ replace_regs (x, reg_map, nregs, replace_dest)
SET_SRC (x) = replace_regs (SET_SRC (x), reg_map, nregs, 0);
return x;
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -1838,3 +1889,94 @@ replace_regs (x, reg_map, nregs, replace_dest)
}
return x;
}
+
+/* Return 1 if X, the SRC_SRC of SET of (pc) contain a REG or MEM that is
+ not in the constant pool and not in the condition of an IF_THEN_ELSE. */
+
+static int
+jmp_uses_reg_or_mem (x)
+ rtx x;
+{
+ enum rtx_code code = GET_CODE (x);
+ int i, j;
+ char *fmt;
+
+ switch (code)
+ {
+ case CONST:
+ case LABEL_REF:
+ case PC:
+ return 0;
+
+ case REG:
+ return 1;
+
+ case MEM:
+ return ! (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0)));
+
+ case IF_THEN_ELSE:
+ return (jmp_uses_reg_or_mem (XEXP (x, 1))
+ || jmp_uses_reg_or_mem (XEXP (x, 2)));
+
+ case PLUS: case MINUS: case MULT:
+ return (jmp_uses_reg_or_mem (XEXP (x, 0))
+ || jmp_uses_reg_or_mem (XEXP (x, 1)));
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e'
+ && jmp_uses_reg_or_mem (XEXP (x, i)))
+ return 1;
+
+ if (fmt[i] == 'E')
+ for (j = 0; j < XVECLEN (x, i); j++)
+ if (jmp_uses_reg_or_mem (XVECEXP (x, i, j)))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return nonzero if INSN is an indirect jump (aka computed jump).
+
+ Tablejumps and casesi insns are not considered indirect jumps;
+ we can recognize them by a (use (lael_ref)). */
+
+int
+computed_jump_p (insn)
+ rtx insn;
+{
+ int i;
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ rtx pat = PATTERN (insn);
+ int computed_jump = 0;
+
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ int len = XVECLEN (pat, 0);
+ int has_use_labelref = 0;
+
+ for (i = len - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == USE
+ && (GET_CODE (XEXP (XVECEXP (pat, 0, i), 0))
+ == LABEL_REF))
+ has_use_labelref = 1;
+
+ if (! has_use_labelref)
+ for (i = len - 1; i >= 0; i--)
+ if (GET_CODE (XVECEXP (pat, 0, i)) == SET
+ && SET_DEST (XVECEXP (pat, 0, i)) == pc_rtx
+ && jmp_uses_reg_or_mem (SET_SRC (XVECEXP (pat, 0, i))))
+ return 1;
+ }
+ else if (GET_CODE (pat) == SET
+ && SET_DEST (pat) == pc_rtx
+ && jmp_uses_reg_or_mem (SET_SRC (pat)))
+ return 1;
+ }
+ return 0;
+}
diff --git a/gnu/usr.bin/gcc/scan-decls.c b/gnu/usr.bin/gcc/scan-decls.c
index e8309b813ec..a5fb8741fd6 100644
--- a/gnu/usr.bin/gcc/scan-decls.c
+++ b/gnu/usr.bin/gcc/scan-decls.c
@@ -1,5 +1,5 @@
/* scan-decls.c - Extracts declarations from cpp output.
- Copyright (C) 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -78,19 +78,21 @@ int
scan_decls (pfile, argc, argv)
cpp_reader *pfile;
int argc;
- char**argv;
+ char **argv;
{
int saw_extern, saw_inline;
+ int start_written;
int old_written;
/* If declarator_start is non-zero, it marks the start of the current
declarator. If it is zero, we are either still parsing the
- decl-specs, or prev_id_start marks the start of the declarator. */
+ decl-specs, or prev_id_start marks the start of the declarator. */
int declarator_start;
int prev_id_start, prev_id_end;
enum cpp_token token;
new_statement:
CPP_SET_WRITTEN (pfile, 0);
+ start_written = 0;
token = cpp_get_token (pfile);
handle_statement:
@@ -122,13 +124,10 @@ scan_decls (pfile, argc, argv)
declarator_start = 0;
for (;;)
{
- int start_written = CPP_WRITTEN (pfile);
- token = cpp_get_token (pfile);
- handle_token:
switch (token)
{
case CPP_LPAREN:
- /* Looks like this is the start of a formal parameter list. */
+ /* Looks like this is the start of a formal parameter list. */
if (prev_id_start)
{
int nesting = 1;
@@ -187,7 +186,7 @@ scan_decls (pfile, argc, argv)
pfile->token_buffer,
prev_id_start);
}
- /* ... fall through ... */
+ /* ... fall through ... */
maybe_handle_comma:
if (token != CPP_COMMA)
goto new_statement;
@@ -225,10 +224,10 @@ scan_decls (pfile, argc, argv)
}
}
else
- goto handle_token;
+ continue;
break;
}
- /* This may be the name of a variable or function. */
+ /* This may be the name of a variable or function. */
prev_id_start = start_written;
prev_id_end = CPP_WRITTEN (pfile);
break;
@@ -240,7 +239,7 @@ scan_decls (pfile, argc, argv)
goto new_statement; /* handle_statement? */
case CPP_HSPACE: case CPP_VSPACE: case CPP_COMMENT: case CPP_POP:
- /* Skip initial white space. */
+ /* Skip initial white space. */
if (start_written == 0)
CPP_SET_WRITTEN (pfile, 0);
break;
@@ -248,5 +247,8 @@ scan_decls (pfile, argc, argv)
default:
prev_id_start = 0;
}
+
+ start_written = CPP_WRITTEN (pfile);
+ token = cpp_get_token (pfile);
}
}
diff --git a/gnu/usr.bin/gcc/scan.c b/gnu/usr.bin/gcc/scan.c
index 1086c384f1a..4f575b38a9f 100644
--- a/gnu/usr.bin/gcc/scan.c
+++ b/gnu/usr.bin/gcc/scan.c
@@ -111,7 +111,7 @@ scan_string (fp, s, init)
return c;
}
-/* Skip horizontal white spaces (spaces, tabs, and C-style comments). */
+/* Skip horizontal white spaces (spaces, tabs, and C-style comments). */
int
skip_spaces (fp, c)
diff --git a/gnu/usr.bin/gcc/scan.h b/gnu/usr.bin/gcc/scan.h
index e56dd1593eb..929a1ef5fee 100644
--- a/gnu/usr.bin/gcc/scan.h
+++ b/gnu/usr.bin/gcc/scan.h
@@ -51,22 +51,22 @@ struct fn_decl
};
extern int lineno;
-extern void sstring_append _PARAMS((sstring*, sstring*));
-extern void make_sstring_space _PARAMS((sstring*, int));
-extern int skip_spaces _PARAMS((FILE*, int));
+extern void sstring_append _PARAMS((sstring *, sstring *));
+extern void make_sstring_space _PARAMS((sstring *, int));
+extern int skip_spaces _PARAMS((FILE *, int));
extern int scan_ident _PARAMS((FILE *, sstring *, int));
-extern int scan_string _PARAMS((FILE*, sstring *, int));
-extern int read_upto _PARAMS((FILE*, sstring*, int));
+extern int scan_string _PARAMS((FILE *, sstring *, int));
+extern int read_upto _PARAMS((FILE *, sstring *, int));
extern char *xmalloc _PARAMS((unsigned));
extern char *xrealloc _PARAMS((char *, unsigned));
-extern unsigned long hash _PARAMS((const char*));
+extern unsigned long hash _PARAMS((const char *));
/* get_token is a simple C lexer. */
#define IDENTIFIER_TOKEN 300
#define CHAR_TOKEN 301
#define STRING_TOKEN 302
#define INT_TOKEN 303
-extern int get_token _PARAMS ((FILE*, sstring*));
+extern int get_token _PARAMS ((FILE *, sstring *));
/* Current file and line numer, taking #-directives into account */
extern int source_lineno;
diff --git a/gnu/usr.bin/gcc/sdbout.c b/gnu/usr.bin/gcc/sdbout.c
index 8fdb72c6ae2..7fab3bec57e 100644
--- a/gnu/usr.bin/gcc/sdbout.c
+++ b/gnu/usr.bin/gcc/sdbout.c
@@ -1,5 +1,5 @@
/* Output sdb-format symbol table information from GNU compiler.
- Copyright (C) 1988, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1988, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -44,25 +44,28 @@ AT&T C compiler. From the example below I would conclude the following:
#ifdef SDB_DEBUGGING_INFO
+#include <stdio.h>
#include "tree.h"
#include "rtl.h"
-#include <stdio.h>
#include "regs.h"
+#include "defaults.h"
#include "flags.h"
#include "insn-config.h"
#include "reload.h"
-/* Mips systems use the SDB functions to dump out symbols, but
- do not supply usable syms.h include files. */
-#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__)
+/* Mips systems use the SDB functions to dump out symbols, but do not
+ supply usable syms.h include files. Which syms.h file to use is a
+ target parameter so don't use the native one if we're cross compiling. */
+
+#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__) && !defined(CROSS_COMPILE)
#include <syms.h>
/* Use T_INT if we don't have T_VOID. */
#ifndef T_VOID
#define T_VOID T_INT
#endif
-#else /* not USG, or MIPS */
+#else
#include "gsyms.h"
-#endif /* not USG, or MIPS */
+#endif
/* #include <storclass.h> used to be this instead of syms.h. */
@@ -101,12 +104,20 @@ void sdbout_init ();
void sdbout_symbol ();
void sdbout_types();
-static void sdbout_typedefs ();
-static void sdbout_syms ();
-static void sdbout_one_type ();
-static void sdbout_queue_anonymous_type ();
-static void sdbout_dequeue_anonymous_types ();
-static int plain_type_1 ();
+static char *gen_fake_label PROTO((void));
+static int plain_type PROTO((tree));
+static int template_name_p PROTO((tree));
+static void sdbout_record_type_name PROTO((tree));
+static int plain_type_1 PROTO((tree, int));
+static void sdbout_block PROTO((tree));
+static void sdbout_syms PROTO((tree));
+static void sdbout_queue_anonymous_type PROTO((tree));
+static void sdbout_dequeue_anonymous_types PROTO((void));
+static void sdbout_type PROTO((tree));
+static void sbdout_field_types PROTO((tree));
+static void sdbout_one_type PROTO((tree));
+static void sdbout_parms PROTO((tree));
+static void sdbout_reg_parms PROTO((tree));
/* Define the default sizes for various types. */
@@ -277,6 +288,38 @@ do { fprintf (asm_out_file, "\t.def\t"); \
/* Ensure we don't output a negative line number. */
#define MAKE_LINE_SAFE(line) \
if (line <= sdb_begin_function_line) line = sdb_begin_function_line + 1
+
+/* Perform linker optimization of merging header file definitions together
+ for targets with MIPS_DEBUGGING_INFO defined. This won't work without a
+ post 960826 version of GAS. Nothing breaks with earlier versions of GAS,
+ the optimization just won't be done. The native assembler already has the
+ necessary support. */
+
+#ifdef MIPS_DEBUGGING_INFO
+
+#ifndef PUT_SDB_SRC_FILE
+#define PUT_SDB_SRC_FILE(FILENAME) \
+output_file_directive (asm_out_file, (FILENAME))
+#endif
+
+/* ECOFF linkers have an optimization that does the same kind of thing as
+ N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the
+ executable. To achieve this, GCC must output a .file for each file
+ name change. */
+
+/* This is a stack of input files. */
+
+struct sdb_file
+{
+ struct sdb_file *next;
+ char *name;
+};
+
+/* This is the top of the stack. */
+
+static struct sdb_file *current_file;
+
+#endif /* MIPS_DEBUGGING_INFO */
/* Set up for SDB output at the start of compilation. */
@@ -286,6 +329,12 @@ sdbout_init (asm_file, input_file_name, syms)
char *input_file_name;
tree syms;
{
+#ifdef MIPS_DEBUGGING_INFO
+ current_file = (struct sdb_file *) xmalloc (sizeof *current_file);
+ current_file->next = NULL;
+ current_file->name = input_file_name;
+#endif
+
#ifdef RMS_QUICK_HACK_1
tree t;
for (t = syms; t; t = TREE_CHAIN (t))
@@ -293,13 +342,6 @@ sdbout_init (asm_file, input_file_name, syms)
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
sdbout_symbol (t, 0);
#endif
-
-#if 0 /* Nothing need be output for the predefined types. */
- /* Get all permanent types that have typedef names,
- and output them all, except for those already output. */
-
- sdbout_typedefs (syms);
-#endif
}
#if 0
@@ -489,10 +531,14 @@ plain_type_1 (type, level)
{
char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ if (!strcmp (name, "char"))
+ return T_CHAR;
if (!strcmp (name, "unsigned char"))
return T_UCHAR;
if (!strcmp (name, "signed char"))
return T_CHAR;
+ if (!strcmp (name, "int"))
+ return T_INT;
if (!strcmp (name, "unsigned int"))
return T_UINT;
if (!strcmp (name, "short int"))
@@ -505,12 +551,12 @@ plain_type_1 (type, level)
return T_ULONG;
}
+ if (size == INT_TYPE_SIZE)
+ return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
if (size == CHAR_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
if (size == SHORT_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT);
- if (size == INT_TYPE_SIZE)
- return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
if (size == LONG_TYPE_SIZE)
return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
if (size == LONG_LONG_TYPE_SIZE) /* better than nothing */
@@ -520,11 +566,15 @@ plain_type_1 (type, level)
case REAL_TYPE:
{
- int size = int_size_in_bytes (type) * BITS_PER_UNIT;
- if (size == FLOAT_TYPE_SIZE)
+ int precision = TYPE_PRECISION (type);
+ if (precision == FLOAT_TYPE_SIZE)
return T_FLOAT;
- if (size == DOUBLE_TYPE_SIZE)
+ if (precision == DOUBLE_TYPE_SIZE)
return T_DOUBLE;
+#ifdef EXTENDED_SDB_BASIC_TYPES
+ if (precision == LONG_DOUBLE_TYPE_SIZE)
+ return T_LNGDBL;
+#endif
return 0;
}
@@ -538,7 +588,10 @@ plain_type_1 (type, level)
if (sdb_n_dims < SDB_MAX_DIM)
sdb_dims[sdb_n_dims++]
= (TYPE_DOMAIN (type)
- ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
+ && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
+ ? (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1)
: 0);
return PUSH_DERIVED_LEVEL (DT_ARY, m);
}
@@ -564,8 +617,8 @@ plain_type_1 (type, level)
only if the .def has already been finished.
At least on 386, the Unix assembler
cannot handle forward references to tags. */
- /* But the 88100, it requires them, sigh... */
- /* And the MIPS requires unknown refs as well... */
+ /* But the 88100, it requires them, sigh... */
+ /* And the MIPS requires unknown refs as well... */
tag = KNOWN_TYPE_TAG (type);
PUT_SDB_TAG (tag);
/* These 3 lines used to follow the close brace.
@@ -691,7 +744,10 @@ sdbout_symbol (decl, local)
context = decl_function_context (decl);
if (context == current_function_decl)
return;
- if (DECL_EXTERNAL (decl))
+ /* Check DECL_INITIAL to distinguish declarations from definitions.
+ Don't output debug info here for declarations; they will have
+ a DECL_INITIAL value of 0. */
+ if (! DECL_INITIAL (decl))
return;
if (GET_CODE (DECL_RTL (decl)) != MEM
|| GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
@@ -737,7 +793,7 @@ sdbout_symbol (decl, local)
if (DECL_RTL (decl) == 0)
return;
- DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
+ DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX, 0);
#ifdef LEAF_REG_REMAP
if (leaf_function)
leaf_renumber_regs_insn (DECL_RTL (decl));
@@ -936,7 +992,7 @@ sdbout_toplevel_data (decl)
#ifdef SDB_ALLOW_FORWARD_REFERENCES
-/* Machinery to record and output anonymous types. */
+/* Machinery to record and output anonymous types. */
static tree anonymous_types;
@@ -1236,9 +1292,9 @@ sdbout_parms (parms)
/* Perform any necessary register eliminations on the parameter's rtl,
so that the debugging output will be accurate. */
- DECL_INCOMING_RTL (parms) =
- eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
- DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
+ DECL_INCOMING_RTL (parms)
+ = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX, 0);
+ DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX, 0);
if (PARM_PASSED_IN_MEMORY (parms))
{
@@ -1315,7 +1371,7 @@ sdbout_parms (parms)
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
PUT_SDB_SCL (C_REGPARM);
- PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+ PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
PUT_SDB_ENDEF;
}
else if (GET_CODE (DECL_RTL (parms)) == MEM
@@ -1338,7 +1394,7 @@ sdbout_parms (parms)
PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
XEXP (DECL_RTL (parms), 0)));
PUT_SDB_SCL (C_ARG);
- PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+ PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
PUT_SDB_ENDEF;
}
}
@@ -1376,7 +1432,7 @@ sdbout_reg_parms (parms)
PUT_SDB_DEF (name);
PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));
PUT_SDB_SCL (C_REG);
- PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
+ PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
PUT_SDB_ENDEF;
}
/* Report parms that live in memory but not where they were passed. */
@@ -1544,4 +1600,35 @@ sdbout_label (insn)
PUT_SDB_ENDEF;
}
+/* Change to reading from a new source file. */
+
+void
+sdbout_start_new_source_file (filename)
+ char *filename;
+{
+#ifdef MIPS_DEBUGGING_INFO
+ struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n);
+
+ n->next = current_file;
+ n->name = filename;
+ current_file = n;
+ PUT_SDB_SRC_FILE (filename);
+#endif
+}
+
+/* Revert to reading a previous source file. */
+
+void
+sdbout_resume_previous_source_file ()
+{
+#ifdef MIPS_DEBUGGING_INFO
+ struct sdb_file *next;
+
+ next = current_file->next;
+ free (current_file);
+ current_file = next;
+ PUT_SDB_SRC_FILE (current_file->name);
+#endif
+}
+
#endif /* SDB_DEBUGGING_INFO */
diff --git a/gnu/usr.bin/gcc/stmt.c b/gnu/usr.bin/gcc/stmt.c
index 7ce2dd9e40a..9451012d13b 100644
--- a/gnu/usr.bin/gcc/stmt.c
+++ b/gnu/usr.bin/gcc/stmt.c
@@ -1,5 +1,5 @@
/* Expands front end tree to back end RTL for GNU C-Compiler
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "tree.h"
#include "flags.h"
+#include "except.h"
#include "function.h"
#include "insn-flags.h"
#include "insn-config.h"
@@ -106,10 +107,6 @@ extern rtx cleanup_label;
extern rtx return_label;
-/* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
- So we can mark them all live at the end of the function, if nonopt. */
-extern rtx save_expr_regs;
-
/* Offset to end of allocated area of stack frame.
If stack grows down, this is the address of the last stack slot allocated.
If stack grows up, this is the address for the next slot. */
@@ -132,14 +129,10 @@ extern rtx arg_pointer_save_area;
/* Chain of all RTL_EXPRs that have insns in them. */
extern tree rtl_expr_chain;
-#if 0 /* Turned off because 0 seems to work just as well. */
-/* Cleanup lists are required for binding levels regardless of whether
- that binding level has cleanups or not. This node serves as the
- cleanup list whenever an empty list is required. */
-static tree empty_cleanup_list;
-#endif
+/* Stack allocation level in which temporaries for TARGET_EXPRs live. */
+extern int target_temp_slot_level;
-extern void (*interim_eh_hook) PROTO((tree));
+extern int temp_slot_level;
/* Functions and data structures for expanding case statements. */
@@ -147,8 +140,9 @@ extern void (*interim_eh_hook) PROTO((tree));
statements. We handle "range" labels; for a single-value label
as in C, the high and low limits are the same.
- A chain of case nodes is initially maintained via the RIGHT fields
- in the nodes. Nodes with higher case values are later in the list.
+ An AVL tree of case nodes is initially created, and later transformed
+ to a list linked via the RIGHT fields in the nodes. Nodes with
+ higher case values are later in the list.
Switch statements can be output in one of two forms. A branch table
is used if there are more than a few labels and the labels are dense
@@ -172,6 +166,7 @@ struct case_node
tree low; /* Lowest index value for this label */
tree high; /* Highest index value for this label */
tree code_label; /* Label to jump to when node matches */
+ int balance;
};
typedef struct case_node case_node;
@@ -224,7 +219,7 @@ struct nesting
and no `else' has been seen yet. */
rtx endif_label;
/* Label for the end of this alternative.
- This may be the end of the if or the next else/elseif. */
+ This may be the end of the if or the next else/elseif. */
rtx next_label;
} cond;
/* For loops. */
@@ -248,7 +243,7 @@ struct nesting
in order of entry. */
int block_start_count;
/* Nonzero => value to restore stack to on exit. Complemented by
- bc_stack_level (see below) when generating bytecodes. */
+ bc_stack_level (see below) when generating bytecodes. */
rtx stack_level;
/* The NOTE that starts this contour.
Used by expand_goto to check whether the destination
@@ -265,7 +260,7 @@ struct nesting
as they were at the locus where this block appears.
There is an element for each containing block,
ordered innermost containing block first.
- The tail of this list can be 0 (was empty_cleanup_list),
+ The tail of this list can be 0,
if all remaining elements would be empty lists.
The element's TREE_VALUE is the cleanup-list of that block,
which may be null. */
@@ -277,6 +272,28 @@ struct nesting
int function_call_count;
/* Bytecode specific: stack level to restore stack to on exit. */
int bc_stack_level;
+ /* Nonzero if this is associated with a EH region. */
+ int exception_region;
+ /* The saved target_temp_slot_level from our outer block.
+ We may reset target_temp_slot_level to be the level of
+ this block, if that is done, target_temp_slot_level
+ reverts to the saved target_temp_slot_level at the very
+ end of the block. */
+ int target_temp_slot_level;
+ /* True if we are currently emitting insns in an area of
+ output code that is controlled by a conditional
+ expression. This is used by the cleanup handling code to
+ generate conditional cleanup actions. */
+ int conditional_code;
+ /* A place to move the start of the exception region for any
+ of the conditional cleanups, must be at the end or after
+ the start of the last unconditional cleanup, and before any
+ conditional branch points. */
+ rtx last_unconditional_cleanup;
+ /* When in a conditional context, this is the specific
+ cleanup list associated with last_unconditional_cleanup,
+ where we place the conditionalized cleanups. */
+ tree *cleanup_ptr;
} block;
/* For switch (C) or case (Pascal) statements,
and also for dummies (see `expand_start_case_dummy'). */
@@ -287,12 +304,11 @@ struct nesting
rtx start;
/* For bytecodes, the case table is in-lined right in the code.
A label is needed for skipping over this block. It is only
- used when generating bytecodes. */
+ used when generating bytecodes. */
rtx skip_label;
- /* A list of case labels, kept in ascending order by value
- as the list is built.
- During expand_end_case, this list may be rearranged into a
- nearly balanced binary tree. */
+ /* A list of case labels; it is first built as an AVL tree.
+ During expand_end_case, this is converted to a list, and may be
+ rearranged into a nearly balanced binary tree. */
struct case_node *case_list;
/* Label to jump to if no case matches. */
tree default_label;
@@ -395,7 +411,7 @@ struct goto_fixup
rtx stack_level;
/* List of lists of cleanup expressions to be run by this goto.
There is one element for each block that this goto is within.
- The tail of this list can be 0 (was empty_cleanup_list),
+ The tail of this list can be 0,
if all remaining elements would be empty.
The TREE_VALUE contains the cleanup list of that block as of the
time this goto was seen.
@@ -429,6 +445,12 @@ struct label_chain
struct label_chain *next;
tree label;
};
+
+
+/* Non-zero if we are using EH to handle cleanus. */
+static int using_eh_for_cleanups_p = 0;
+
+
static void expand_goto_internal PROTO((tree, rtx, rtx));
static void bc_expand_goto_internal PROTO((enum bytecode_opcode,
struct bc_label *, tree));
@@ -466,17 +488,23 @@ static int node_has_high_bound PROTO((case_node_ptr, tree));
static int node_is_bounded PROTO((case_node_ptr, tree));
static void emit_jump_if_reachable PROTO((rtx));
static void emit_case_nodes PROTO((rtx, case_node_ptr, rtx, tree));
+static int add_case_node PROTO((tree, tree, tree, tree *));
+static struct case_node *case_tree2list PROTO((case_node *, case_node *));
extern rtx bc_allocate_local ();
extern rtx bc_allocate_variable_array ();
void
+using_eh_for_cleanups ()
+{
+ using_eh_for_cleanups_p = 1;
+}
+
+void
init_stmt ()
{
gcc_obstack_init (&stmt_obstack);
-#if 0
- empty_cleanup_list = build_tree_list (NULL_TREE, NULL_TREE);
-#endif
+ init_eh ();
}
void
@@ -499,6 +527,8 @@ init_stmt_for_function ()
/* We are not processing a ({...}) grouping. */
expr_stmts_for_value = 0;
last_expr_type = 0;
+
+ init_eh_for_function ();
}
void
@@ -519,6 +549,7 @@ save_stmt_status (p)
p->emit_filename = emit_filename;
p->emit_lineno = emit_lineno;
p->goto_fixup_chain = goto_fixup_chain;
+ save_eh_status (p);
}
void
@@ -539,6 +570,7 @@ restore_stmt_status (p)
emit_filename = p->emit_filename;
emit_lineno = p->emit_lineno;
goto_fixup_chain = p->goto_fixup_chain;
+ restore_eh_status (p);
}
/* Emit a no-op instruction. */
@@ -607,6 +639,11 @@ expand_computed_goto (exp)
#endif
emit_queue ();
+ /* Be sure the function is executable. */
+ if (flag_check_memory_usage)
+ emit_library_call (chkr_check_exec_libfunc, 1,
+ VOIDmode, 1, x, ptr_mode);
+
do_pending_stack_adjust ();
emit_indirect_jump (x);
}
@@ -774,7 +811,7 @@ expand_goto_internal (body, label, last_insn)
/* NOTICE! If a bytecode instruction other than `jump' is needed,
then the caller has to call bc_expand_goto_internal()
directly. This is rather an exceptional case, and there aren't
- that many places where this is necessary. */
+ that many places where this is necessary. */
if (output_bytecode)
{
expand_goto_internal (body, label, last_insn);
@@ -809,8 +846,9 @@ expand_goto_internal (body, label, last_insn)
if (stack_level)
{
- /* Ensure stack adjust isn't done by emit_jump, as this would clobber
- the stack pointer. This one should be deleted as dead by flow. */
+ /* Ensure stack adjust isn't done by emit_jump, as this
+ would clobber the stack pointer. This one should be
+ deleted as dead by flow. */
clear_pending_stack_adjust ();
do_pending_stack_adjust ();
emit_stack_restore (SAVE_BLOCK, stack_level, NULL_RTX);
@@ -834,7 +872,7 @@ expand_goto_internal (body, label, last_insn)
}
/* Generate a jump with OPCODE to the given bytecode LABEL which is
- found within BODY. */
+ found within BODY. */
static void
bc_expand_goto_internal (opcode, label, body)
@@ -847,7 +885,7 @@ bc_expand_goto_internal (opcode, label, body)
/* If the label is defined, adjust the stack as necessary.
If it's not defined, we have to push the reference on the
- fixup list. */
+ fixup list. */
if (label->defined)
{
@@ -875,7 +913,7 @@ bc_expand_goto_internal (opcode, label, body)
must do so after the jump, since the jump may depend on
what's on the stack. Thus, any stack-modifying conditional
jumps (these are the only ones that rely on what's on the
- stack) go into the fixup list. */
+ stack) go into the fixup list. */
if (stack_level >= 0
&& stack_depth != stack_level
@@ -1020,11 +1058,7 @@ expand_fixup (tree_label, rtl_label, last_insn)
fixup->block_start_count = block_start_count;
fixup->stack_level = 0;
fixup->cleanup_list_list
- = (((block->data.block.outer_cleanups
-#if 0
- && block->data.block.outer_cleanups != empty_cleanup_list
-#endif
- )
+ = ((block->data.block.outer_cleanups
|| block->data.block.cleanups)
? tree_cons (NULL_TREE, block->data.block.cleanups,
block->data.block.outer_cleanups)
@@ -1148,12 +1182,12 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
&& (after_label == 0
|| INSN_UID (first_insn) < INSN_UID (after_label))
&& INSN_UID (first_insn) > INSN_UID (f->before_jump)
- && ! DECL_REGISTER (f->target))
+ && ! DECL_ERROR_ISSUED (f->target))
{
error_with_decl (f->target,
"label `%s' used before containing binding contour");
/* Prevent multiple errors for one label. */
- DECL_REGISTER (f->target) = 1;
+ DECL_ERROR_ISSUED (f->target) = 1;
}
/* We will expand the cleanups into a sequence of their own and
@@ -1213,7 +1247,7 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
/* For any still-undefined labels, do the cleanups for this block now.
We must do this now since items in the cleanup list may go out
- of scope when the block ends. */
+ of scope when the block ends. */
for (prev = 0, f = goto_fixup_chain; f; prev = f, f = f->next)
if (f->before_jump != 0
&& PREV_INSN (f->target_rtl) == 0
@@ -1243,8 +1277,9 @@ fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
cleanup_insns = get_insns ();
poplevel (1, 0, 0);
end_sequence ();
- f->before_jump
- = emit_insns_after (cleanup_insns, f->before_jump);
+ if (cleanup_insns != 0)
+ f->before_jump
+ = emit_insns_after (cleanup_insns, f->before_jump);
f->cleanup_list_list = TREE_CHAIN (lists);
}
@@ -1299,8 +1334,8 @@ bc_fixup_gotos (thisblock, stack_level, cleanup_list, first_insn, dont_jump_in)
/* Emit code to restore the stack and continue */
bc_emit_bytecode_labeldef (f->label);
- /* Save stack_depth across call, since bc_adjust_stack () will alter
- the perceived stack depth via the instructions generated. */
+ /* Save stack_depth across call, since bc_adjust_stack will alter
+ the perceived stack depth via the instructions generated. */
if (f->bc_stack_level >= 0)
{
@@ -1334,6 +1369,12 @@ expand_asm (body)
return;
}
+ if (flag_check_memory_usage)
+ {
+ error ("`asm' cannot be used with `-fcheck-memory-usage'");
+ return;
+ }
+
if (TREE_CODE (body) == ADDR_EXPR)
body = TREE_OPERAND (body, 0);
@@ -1368,11 +1409,15 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
rtx body;
int ninputs = list_length (inputs);
int noutputs = list_length (outputs);
+ int ninout = 0;
int nclobbers;
tree tail;
register int i;
/* Vector of RTX's of evaluated output operands. */
rtx *output_rtx = (rtx *) alloca (noutputs * sizeof (rtx));
+ int *inout_opnum = (int *) alloca (noutputs * sizeof (int));
+ enum machine_mode *inout_mode
+ = (enum machine_mode *) alloca (noutputs * sizeof (enum machine_mode));
/* The insn we have emitted. */
rtx insn;
@@ -1382,6 +1427,12 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
return;
}
+ if (flag_check_memory_usage)
+ {
+ error ("`asm' cannot be used with `-fcheck-memory-usage'");
+ return;
+ }
+
/* Count the number of meaningful clobbered registers, ignoring what
we would ignore later. */
nclobbers = 0;
@@ -1404,6 +1455,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
tree val1;
int j;
int found_equal = 0;
+ int found_plus = 0;
int allows_reg = 0;
/* If there's an erroneous arg, emit no insn. */
@@ -1419,15 +1471,23 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
{
case '+':
- error ("output operand constraint contains `+'");
- return;
+ /* Make sure we can specify the matching operand. */
+ if (i > 9)
+ {
+ error ("output operand constraint %d contains `+'", i);
+ return;
+ }
+
+ /* Replace '+' with '='. */
+ TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] = '=';
+ found_plus = 1;
+ break;
case '=':
found_equal = 1;
break;
case '?': case '!': case '*': case '%': case '&':
- case '0': case '1': case '2': case '3': case '4':
case 'V': case 'm': case 'o': case '<': case '>':
case 'E': case 'F': case 'G': case 'H': case 'X':
case 's': case 'i': case 'n':
@@ -1438,13 +1498,18 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
#endif
break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ error ("matching constraint not valid in output operand");
+ break;
+
case 'p': case 'g': case 'r':
default:
allows_reg = 1;
break;
}
- if (! found_equal)
+ if (! found_equal && ! found_plus)
{
error ("output operand constraint lacks `='");
return;
@@ -1459,32 +1524,33 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|| (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
&& ! (GET_CODE (DECL_RTL (val)) == REG
&& GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
- || ! allows_reg)
+ || ! allows_reg
+ || found_plus)
{
if (! allows_reg)
mark_addressable (TREE_VALUE (tail));
output_rtx[i]
- = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode, 0);
+ = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode,
+ EXPAND_MEMORY_USE_WO);
if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
error ("output number %d not directly addressable", i);
}
else
{
- if (TYPE_MODE (type) == BLKmode)
- {
- output_rtx[i] = assign_stack_temp (BLKmode,
- int_size_in_bytes (type), 0);
- MEM_IN_STRUCT_P (output_rtx[i]) = AGGREGATE_TYPE_P (type);
- }
- else
- output_rtx[i] = gen_reg_rtx (TYPE_MODE (type));
-
+ output_rtx[i] = assign_temp (type, 0, 0, 0);
TREE_VALUE (tail) = make_tree (type, output_rtx[i]);
}
+
+ if (found_plus)
+ {
+ inout_mode[ninout] = TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)));
+ inout_opnum[ninout++] = i;
+ }
}
+ ninputs += ninout;
if (ninputs + noutputs > MAX_RECOG_OPERANDS)
{
error ("more than %d operands in `asm'", MAX_RECOG_OPERANDS);
@@ -1499,7 +1565,10 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
body = gen_rtx (ASM_OPERANDS, VOIDmode,
TREE_STRING_POINTER (string), "", 0, argvec, constraints,
filename, line);
- MEM_VOLATILE_P (body) = vol;
+
+ /* The only use of BODY is if no outputs are specified, so set
+ it volatile, at least for now. */
+ MEM_VOLATILE_P (body) = 1;
/* Eval the inputs and put them into ARGVEC.
Put their constraints into ASM_INPUTs and store in CONSTRAINTS. */
@@ -1543,7 +1612,23 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
#endif
break;
+ /* Whether or not a numeric constraint allows a register is
+ decided by the matching constraint, and so there is no need
+ to do anything special with them. We must handle them in
+ the default case, so that we don't unnecessarily force
+ operands to memory. */
case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]
+ >= '0' + noutputs)
+ {
+ error
+ ("matching constraint references invalid operand number");
+ return;
+ }
+
+ /* ... fall through ... */
+
case 'p': case 'g': case 'r':
default:
allows_reg = 1;
@@ -1575,10 +1660,8 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
|| GET_CODE (XVECEXP (body, 3, i)) == CONCAT))
{
tree type = TREE_TYPE (TREE_VALUE (tail));
- rtx memloc = assign_stack_temp (TYPE_MODE (type),
- int_size_in_bytes (type), 1);
+ rtx memloc = assign_temp (type, 1, 1, 1);
- MEM_IN_STRUCT_P (memloc) = AGGREGATE_TYPE_P (type);
emit_move_insn (memloc, XVECEXP (body, 3, i));
XVECEXP (body, 3, i) = memloc;
}
@@ -1592,12 +1675,25 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
/* Protect all the operands from the queue,
now that they have all been evaluated. */
- for (i = 0; i < ninputs; i++)
+ for (i = 0; i < ninputs - ninout; i++)
XVECEXP (body, 3, i) = protect_from_queue (XVECEXP (body, 3, i), 0);
for (i = 0; i < noutputs; i++)
output_rtx[i] = protect_from_queue (output_rtx[i], 1);
+ /* For in-out operands, copy output rtx to input rtx. */
+ for (i = 0; i < ninout; i++)
+ {
+ static char match[9+1][2]
+ = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
+ int j = inout_opnum[i];
+
+ XVECEXP (body, 3, ninputs - ninout + i) /* argvec */
+ = output_rtx[j];
+ XVECEXP (body, 4, ninputs - ninout + i) /* constraints */
+ = gen_rtx (ASM_INPUT, inout_mode[j], match[j]);
+ }
+
/* Now, for each output, construct an rtx
(set OUTPUT (asm_operands INSN OUTPUTNUMBER OUTPUTCONSTRAINT
ARGVEC CONSTRAINTS))
@@ -1662,7 +1758,7 @@ expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
continue;
}
- /* Ignore unknown register, error already signalled. */
+ /* Ignore unknown register, error already signaled. */
continue;
}
@@ -1843,7 +1939,7 @@ warn_if_unused_value (exp)
the user cannot control it. */
if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
return warn_if_unused_value (TREE_OPERAND (exp, 0));
- /* ... fall through ... */
+ /* ... fall through ... */
default:
/* Referencing a volatile value is a side effect, so don't warn. */
@@ -1921,7 +2017,7 @@ expand_end_stmt_expr (t)
of adding code to inhibit dropping the last expression value, it
is here recovered by undoing the `drop'. Since `drop' is
equivalent to `adjustackSI [1]', it can be undone with `adjstackSI
- [-1]'. */
+ [-1]'. */
bc_adjust_stack (-1);
@@ -2041,7 +2137,7 @@ expand_start_else ()
emit_jump (cond_stack->data.cond.endif_label);
emit_label (cond_stack->data.cond.next_label);
- cond_stack->data.cond.next_label = 0; /* No more _else or _elseif calls. */
+ cond_stack->data.cond.next_label = 0; /* No more _else or _elseif calls. */
}
/* After calling expand_start_else, turn this "else" into an "else if"
@@ -2082,7 +2178,7 @@ expand_end_cond ()
/* Generate code for the start of an if-then. COND is the expression
whose truth is to be tested; if EXITFLAG is nonzero this conditional
is to be visible to exit_something. It is assumed that the caller
- has pushed the previous context on the cond stack. */
+ has pushed the previous context on the cond stack. */
static void
bc_expand_start_cond (cond, exitflag)
@@ -2530,6 +2626,21 @@ expand_value_return (val)
if (GET_CODE (return_reg) == REG
&& REGNO (return_reg) < FIRST_PSEUDO_REGISTER)
emit_insn (gen_rtx (USE, VOIDmode, return_reg));
+ /* Handle calls that return values in multiple non-contiguous locations.
+ The Irix 6 ABI has examples of this. */
+ else if (GET_CODE (return_reg) == PARALLEL)
+ {
+ int i;
+
+ for (i = 0; i < XVECLEN (return_reg, 0); i++)
+ {
+ rtx x = XEXP (XVECEXP (return_reg, 0, i), 0);
+
+ if (GET_CODE (x) == REG
+ && REGNO (x) < FIRST_PSEUDO_REGISTER)
+ emit_insn (gen_rtx (USE, VOIDmode, x));
+ }
+ }
/* Does any pending block have cleanups? */
@@ -2606,7 +2717,7 @@ expand_return (retval)
struct nesting *block;
/* Bytecode returns are quite simple, just leave the result on the
- arithmetic stack. */
+ arithmetic stack. */
if (output_bytecode)
{
bc_expand_expr (retval);
@@ -2665,14 +2776,14 @@ expand_return (retval)
tree expr;
do_jump (TREE_OPERAND (retval_rhs, 0), label, NULL_RTX);
- expr = build (MODIFY_EXPR, TREE_TYPE (current_function_decl),
+ expr = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (current_function_decl)),
DECL_RESULT (current_function_decl),
TREE_OPERAND (retval_rhs, 1));
TREE_SIDE_EFFECTS (expr) = 1;
expand_return (expr);
emit_label (label);
- expr = build (MODIFY_EXPR, TREE_TYPE (current_function_decl),
+ expr = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (current_function_decl)),
DECL_RESULT (current_function_decl),
TREE_OPERAND (retval_rhs, 2));
TREE_SIDE_EFFECTS (expr) = 1;
@@ -2718,29 +2829,55 @@ expand_return (retval)
{
/* If this is return x == y; then generate
if (x == y) return 1; else return 0;
- if we can do it with explicit return insns and
- branches are cheap. */
+ if we can do it with explicit return insns and branches are cheap,
+ but not if we have the corresponding scc insn. */
+ int has_scc = 0;
if (retval_rhs)
switch (TREE_CODE (retval_rhs))
{
case EQ_EXPR:
+#ifdef HAVE_seq
+ has_scc = HAVE_seq;
+#endif
case NE_EXPR:
+#ifdef HAVE_sne
+ has_scc = HAVE_sne;
+#endif
case GT_EXPR:
+#ifdef HAVE_sgt
+ has_scc = HAVE_sgt;
+#endif
case GE_EXPR:
+#ifdef HAVE_sge
+ has_scc = HAVE_sge;
+#endif
case LT_EXPR:
+#ifdef HAVE_slt
+ has_scc = HAVE_slt;
+#endif
case LE_EXPR:
+#ifdef HAVE_sle
+ has_scc = HAVE_sle;
+#endif
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case TRUTH_NOT_EXPR:
case TRUTH_XOR_EXPR:
- op0 = gen_label_rtx ();
- jumpifnot (retval_rhs, op0);
- expand_value_return (const1_rtx);
- emit_label (op0);
- expand_value_return (const0_rtx);
- return;
+ if (! has_scc)
+ {
+ op0 = gen_label_rtx ();
+ jumpifnot (retval_rhs, op0);
+ expand_value_return (const1_rtx);
+ emit_label (op0);
+ expand_value_return (const0_rtx);
+ return;
+ }
+ break;
+
+ default:
+ break;
}
}
#endif /* HAVE_return */
@@ -2838,9 +2975,7 @@ expand_return (retval)
result_reg_mode = tmpmode;
result_reg = gen_reg_rtx (result_reg_mode);
- /* Now that the value is in pseudos, copy it to the result reg(s). */
emit_queue ();
- free_temp_slots ();
for (i = 0; i < n_regs; i++)
emit_move_insn (operand_subword (result_reg, i, 0, result_reg_mode),
result_pseudos[i]);
@@ -2856,10 +2991,10 @@ expand_return (retval)
&& GET_CODE (DECL_RTL (DECL_RESULT (current_function_decl))) == REG)
{
/* Calculate the return value into a pseudo reg. */
- val = expand_expr (retval_rhs, NULL_RTX, VOIDmode, 0);
+ val = gen_reg_rtx (DECL_MODE (DECL_RESULT (current_function_decl)));
+ val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
+ val = force_not_mem (val);
emit_queue ();
- /* All temporaries have now been used. */
- free_temp_slots ();
/* Return the calculated value, doing cleanups first. */
expand_value_return (val);
}
@@ -2869,7 +3004,6 @@ expand_return (retval)
calculate value into hard return reg. */
expand_expr (retval, const0_rtx, VOIDmode, 0);
emit_queue ();
- free_temp_slots ();
expand_value_return (DECL_RTL (DECL_RESULT (current_function_decl)));
}
}
@@ -2909,7 +3043,8 @@ tail_recursion_args (actuals, formals)
for (a = actuals, f = formals, i = 0; a && f; a = TREE_CHAIN (a), f = TREE_CHAIN (f), i++)
{
- if (TREE_TYPE (TREE_VALUE (a)) != TREE_TYPE (f))
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (a)))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (f)))
return 0;
if (GET_CODE (DECL_RTL (f)) != REG || DECL_MODE (f) == BLKmode)
return 0;
@@ -2975,22 +3110,13 @@ expand_start_bindings (exit_flag)
thisblock->data.block.stack_level = 0;
thisblock->data.block.cleanups = 0;
thisblock->data.block.function_call_count = 0;
-#if 0
- if (block_stack)
- {
- if (block_stack->data.block.cleanups == NULL_TREE
- && (block_stack->data.block.outer_cleanups == NULL_TREE
- || block_stack->data.block.outer_cleanups == empty_cleanup_list))
- thisblock->data.block.outer_cleanups = empty_cleanup_list;
- else
- thisblock->data.block.outer_cleanups
- = tree_cons (NULL_TREE, block_stack->data.block.cleanups,
- block_stack->data.block.outer_cleanups);
- }
- else
- thisblock->data.block.outer_cleanups = 0;
-#endif
-#if 1
+ thisblock->data.block.exception_region = 0;
+ thisblock->data.block.target_temp_slot_level = target_temp_slot_level;
+
+ thisblock->data.block.conditional_code = 0;
+ thisblock->data.block.last_unconditional_cleanup = note;
+ thisblock->data.block.cleanup_ptr = &thisblock->data.block.cleanups;
+
if (block_stack
&& !(block_stack->data.block.cleanups == NULL_TREE
&& block_stack->data.block.outer_cleanups == NULL_TREE))
@@ -2999,7 +3125,6 @@ expand_start_bindings (exit_flag)
block_stack->data.block.outer_cleanups);
else
thisblock->data.block.outer_cleanups = 0;
-#endif
thisblock->data.block.label_chain = 0;
thisblock->data.block.innermost_stack_block = stack_block_stack;
thisblock->data.block.first_insn = note;
@@ -3015,6 +3140,91 @@ expand_start_bindings (exit_flag)
}
}
+/* Specify the scope of temporaries created by TARGET_EXPRs. Similar
+ to CLEANUP_POINT_EXPR, but handles cases when a series of calls to
+ expand_expr are made. After we end the region, we know that all
+ space for all temporaries that were created by TARGET_EXPRs will be
+ destroyed and their space freed for reuse. */
+
+void
+expand_start_target_temps ()
+{
+ /* This is so that even if the result is preserved, the space
+ allocated will be freed, as we know that it is no longer in use. */
+ push_temp_slots ();
+
+ /* Start a new binding layer that will keep track of all cleanup
+ actions to be performed. */
+ expand_start_bindings (0);
+
+ target_temp_slot_level = temp_slot_level;
+}
+
+void
+expand_end_target_temps ()
+{
+ expand_end_bindings (NULL_TREE, 0, 0);
+
+ /* This is so that even if the result is preserved, the space
+ allocated will be freed, as we know that it is no longer in use. */
+ pop_temp_slots ();
+}
+
+/* Mark top block of block_stack as an implicit binding for an
+ exception region. This is used to prevent infinite recursion when
+ ending a binding with expand_end_bindings. It is only ever called
+ by expand_eh_region_start, as that it the only way to create a
+ block stack for a exception region. */
+
+void
+mark_block_as_eh_region ()
+{
+ block_stack->data.block.exception_region = 1;
+ if (block_stack->next
+ && block_stack->next->data.block.conditional_code)
+ {
+ block_stack->data.block.conditional_code
+ = block_stack->next->data.block.conditional_code;
+ block_stack->data.block.last_unconditional_cleanup
+ = block_stack->next->data.block.last_unconditional_cleanup;
+ block_stack->data.block.cleanup_ptr
+ = block_stack->next->data.block.cleanup_ptr;
+ }
+}
+
+/* True if we are currently emitting insns in an area of output code
+ that is controlled by a conditional expression. This is used by
+ the cleanup handling code to generate conditional cleanup actions. */
+
+int
+conditional_context ()
+{
+ return block_stack && block_stack->data.block.conditional_code;
+}
+
+/* Mark top block of block_stack as not for an implicit binding for an
+ exception region. This is only ever done by expand_eh_region_end
+ to let expand_end_bindings know that it is being called explicitly
+ to end the binding layer for just the binding layer associated with
+ the exception region, otherwise expand_end_bindings would try and
+ end all implicit binding layers for exceptions regions, and then
+ one normal binding layer. */
+
+void
+mark_block_as_not_eh_region ()
+{
+ block_stack->data.block.exception_region = 0;
+}
+
+/* True if the top block of block_stack was marked as for an exception
+ region by mark_block_as_eh_region. */
+
+int
+is_eh_region ()
+{
+ return block_stack && block_stack->data.block.exception_region;
+}
+
/* Given a pointer to a BLOCK node, save a pointer to the most recently
generated NOTE_INSN_BLOCK_END in the BLOCK_END_NOTE field of the given
BLOCK node. */
@@ -3042,19 +3252,39 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
int mark_ends;
int dont_jump_in;
{
- register struct nesting *thisblock = block_stack;
+ register struct nesting *thisblock;
register tree decl;
+ while (block_stack->data.block.exception_region)
+ {
+ /* Because we don't need or want a new temporary level and
+ because we didn't create one in expand_eh_region_start,
+ create a fake one now to avoid removing one in
+ expand_end_bindings. */
+ push_temp_slots ();
+
+ block_stack->data.block.exception_region = 0;
+
+ expand_end_bindings (NULL_TREE, 0, 0);
+ }
+
if (output_bytecode)
{
bc_expand_end_bindings (vars, mark_ends, dont_jump_in);
return;
}
+ /* Since expand_eh_region_start does an expand_start_bindings, we
+ have to first end all the bindings that were created by
+ expand_eh_region_start. */
+
+ thisblock = block_stack;
+
if (warn_unused)
for (decl = vars; decl; decl = TREE_CHAIN (decl))
if (! TREE_USED (decl) && TREE_CODE (decl) == VAR_DECL
- && ! DECL_IN_SYSTEM_HEADER (decl))
+ && ! DECL_IN_SYSTEM_HEADER (decl)
+ && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
warning_with_decl (decl, "unused variable `%s'");
if (thisblock->exit_label)
@@ -3159,6 +3389,11 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
}
#endif
+#ifdef HAVE_nonlocal_goto_receiver
+ if (HAVE_nonlocal_goto_receiver)
+ emit_insn (gen_nonlocal_goto_receiver ());
+#endif
+
/* The handler expects the desired label address in the static chain
register. It tests the address and does an appropriate jump
to whatever label is desired. */
@@ -3183,10 +3418,10 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
emit_label (afterward);
}
- /* Don't allow jumping into a block that has cleanups or a stack level. */
+ /* Don't allow jumping into a block that has a stack level.
+ Cleanups are allowed, though. */
if (dont_jump_in
- || thisblock->data.block.stack_level != 0
- || thisblock->data.block.cleanups != 0)
+ || thisblock->data.block.stack_level != 0)
{
struct label_chain *chain;
@@ -3197,7 +3432,7 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
DECL_TOO_LATE (chain->label) = 1;
/* If any goto without a fixup came to this label,
that must be an error, because gotos without fixups
- come from outside all saved stack-levels and all cleanups. */
+ come from outside all saved stack-levels. */
if (TREE_ADDRESSABLE (chain->label))
error_with_decl (chain->label,
"label `%s' used before containing binding contour");
@@ -3271,6 +3506,9 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
use_variable (rtl);
}
+ /* Restore the temporary level of TARGET_EXPRs. */
+ target_temp_slot_level = thisblock->data.block.target_temp_slot_level;
+
/* Restore block_stack level for containing block. */
stack_block_stack = thisblock->data.block.innermost_stack_block;
@@ -3368,29 +3606,20 @@ expand_decl (decl)
enum machine_mode reg_mode
= promote_mode (type, DECL_MODE (decl), &unsignedp, 0);
- if (TREE_CODE (type) == COMPLEX_TYPE)
- {
- rtx realpart, imagpart;
- enum machine_mode partmode = TYPE_MODE (TREE_TYPE (type));
-
- /* For a complex type variable, make a CONCAT of two pseudos
- so that the real and imaginary parts
- can be allocated separately. */
- realpart = gen_reg_rtx (partmode);
- REG_USERVAR_P (realpart) = 1;
- imagpart = gen_reg_rtx (partmode);
- REG_USERVAR_P (imagpart) = 1;
- DECL_RTL (decl) = gen_rtx (CONCAT, reg_mode, realpart, imagpart);
- }
- else
- {
- DECL_RTL (decl) = gen_reg_rtx (reg_mode);
- if (TREE_CODE (type) == POINTER_TYPE)
- mark_reg_pointer (DECL_RTL (decl));
- REG_USERVAR_P (DECL_RTL (decl)) = 1;
- }
+ DECL_RTL (decl) = gen_reg_rtx (reg_mode);
+ mark_user_reg (DECL_RTL (decl));
+
+ if (TREE_CODE (type) == POINTER_TYPE)
+ mark_reg_pointer (DECL_RTL (decl),
+ (TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl)))
+ / BITS_PER_UNIT));
}
- else if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
+
+ else if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST
+ && ! (flag_stack_check && ! STACK_CHECK_BUILTIN
+ && (TREE_INT_CST_HIGH (DECL_SIZE (decl)) != 0
+ || (TREE_INT_CST_LOW (DECL_SIZE (decl))
+ > STACK_CHECK_MAX_VAR_SIZE * BITS_PER_UNIT))))
{
/* Variable of fixed size that goes on the stack. */
rtx oldaddr = 0;
@@ -3461,9 +3690,12 @@ expand_decl (decl)
NULL_RTX, VOIDmode, 0);
free_temp_slots ();
- /* Allocate space on the stack for the variable. */
+ /* Allocate space on the stack for the variable. Note that
+ DECL_ALIGN says how the variable is to be aligned and we
+ cannot use it to conclude anything about the alignment of
+ the size. */
address = allocate_dynamic_stack_space (size, NULL_RTX,
- DECL_ALIGN (decl));
+ TYPE_ALIGN (TREE_TYPE (decl)));
/* Reference the variable indirect through that rtx. */
DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl), address);
@@ -3533,7 +3765,7 @@ bc_expand_decl (decl, cleanup)
else if (DECL_SIZE (decl) == 0)
/* Variable with incomplete type. The stack offset herein will be
- fixed later in expand_decl_init (). */
+ fixed later in expand_decl_init. */
DECL_RTL (decl) = bc_gen_rtx ((char *) 0, 0, (struct bc_label *) 0);
else if (TREE_CONSTANT (DECL_SIZE (decl)))
@@ -3604,7 +3836,7 @@ expand_decl_init (decl)
/* Expand initialization for variable-sized types. Allocate array
using newlocalSI and set local variable, which is a pointer to the
- storage. */
+ storage. */
static void
bc_expand_variable_local_init (decl)
@@ -3628,7 +3860,7 @@ bc_expand_variable_local_init (decl)
using expand_address() since that would cause the pointer to be
pushed rather than its address. Hence the hard-coded reference;
notice also that the variable is always local (no global
- variable-size type variables). */
+ variable-size type variables). */
bc_load_localaddr (DECL_RTL (decl));
bc_emit_instruction (storeP);
@@ -3653,7 +3885,7 @@ bc_expand_decl_init (decl)
/* If the type is variable-size, we first create its space (we ASSUME
it CAN'T be static). We do this regardless of whether there's an
- initializer assignment or not. */
+ initializer assignment or not. */
if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
bc_expand_variable_local_init (decl);
@@ -3682,12 +3914,10 @@ bc_expand_decl_init (decl)
/* CLEANUP is an expression to be executed at exit from this binding contour;
for example, in C++, it might call the destructor for this variable.
- If CLEANUP contains any SAVE_EXPRs, then you must preevaluate them
- either before or after calling `expand_decl_cleanup' but before compiling
- any subsequent expressions. This is because CLEANUP may be expanded
- more than once, on different branches of execution.
- For the same reason, CLEANUP may not contain a CALL_EXPR
- except as its topmost node--else `preexpand_calls' would get confused.
+ We wrap CLEANUP in an UNSAVE_EXPR node, so that we can expand the
+ CLEANUP multiple times, and have the correct semantics. This
+ happens in exception handling, for gotos, returns, breaks that
+ leave the current scope.
If CLEANUP is nonzero and DECL is zero, we record a cleanup
that is not associated with any particular variable. */
@@ -3706,14 +3936,189 @@ expand_decl_cleanup (decl, cleanup)
if (cleanup != 0)
{
- thisblock->data.block.cleanups
- = temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
- /* If this block has a cleanup, it belongs in stack_block_stack. */
- stack_block_stack = thisblock;
- (*interim_eh_hook) (NULL_TREE);
+ tree t;
+ rtx seq;
+ tree *cleanups = &thisblock->data.block.cleanups;
+ int cond_context = conditional_context ();
+
+ if (cond_context)
+ {
+ rtx flag = gen_reg_rtx (word_mode);
+ rtx set_flag_0;
+ tree cond;
+
+ start_sequence ();
+ emit_move_insn (flag, const0_rtx);
+ set_flag_0 = get_insns ();
+ end_sequence ();
+
+ thisblock->data.block.last_unconditional_cleanup
+ = emit_insns_after (set_flag_0,
+ thisblock->data.block.last_unconditional_cleanup);
+
+ emit_move_insn (flag, const1_rtx);
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+
+ cond = build_decl (VAR_DECL, NULL_TREE, type_for_mode (word_mode, 1));
+ DECL_RTL (cond) = flag;
+
+ /* Conditionalize the cleanup. */
+ cleanup = build (COND_EXPR, void_type_node,
+ truthvalue_conversion (cond),
+ cleanup, integer_zero_node);
+ cleanup = fold (cleanup);
+
+ pop_obstacks ();
+
+ cleanups = thisblock->data.block.cleanup_ptr;
+ }
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+ cleanup = unsave_expr (cleanup);
+ pop_obstacks ();
+
+ t = *cleanups = temp_tree_cons (decl, cleanup, *cleanups);
+
+ if (! cond_context)
+ /* If this block has a cleanup, it belongs in stack_block_stack. */
+ stack_block_stack = thisblock;
+
+ if (cond_context)
+ {
+ start_sequence ();
+ }
+
+ /* If this was optimized so that there is no exception region for the
+ cleanup, then mark the TREE_LIST node, so that we can later tell
+ if we need to call expand_eh_region_end. */
+ if (! using_eh_for_cleanups_p
+ || expand_eh_region_start_tree (decl, cleanup))
+ TREE_ADDRESSABLE (t) = 1;
+ /* If that started a new EH region, we're in a new block. */
+ thisblock = block_stack;
+
+ if (cond_context)
+ {
+ seq = get_insns ();
+ end_sequence ();
+ if (seq)
+ thisblock->data.block.last_unconditional_cleanup
+ = emit_insns_after (seq,
+ thisblock->data.block.last_unconditional_cleanup);
+ }
+ else
+ {
+ thisblock->data.block.last_unconditional_cleanup
+ = get_last_insn ();
+ thisblock->data.block.cleanup_ptr = &thisblock->data.block.cleanups;
+ }
}
return 1;
}
+
+/* Like expand_decl_cleanup, but suppress generating an exception handler
+ to perform the cleanup. */
+
+int
+expand_decl_cleanup_no_eh (decl, cleanup)
+ tree decl, cleanup;
+{
+ int save_eh = using_eh_for_cleanups_p;
+ int result;
+
+ using_eh_for_cleanups_p = 0;
+ result = expand_decl_cleanup (decl, cleanup);
+ using_eh_for_cleanups_p = save_eh;
+
+ return result;
+}
+
+/* Arrange for the top element of the dynamic cleanup chain to be
+ popped if we exit the current binding contour. DECL is the
+ associated declaration, if any, otherwise NULL_TREE. If the
+ current contour is left via an exception, then __sjthrow will pop
+ the top element off the dynamic cleanup chain. The code that
+ avoids doing the action we push into the cleanup chain in the
+ exceptional case is contained in expand_cleanups.
+
+ This routine is only used by expand_eh_region_start, and that is
+ the only way in which an exception region should be started. This
+ routine is only used when using the setjmp/longjmp codegen method
+ for exception handling. */
+
+int
+expand_dcc_cleanup (decl)
+ tree decl;
+{
+ struct nesting *thisblock = block_stack;
+ tree cleanup;
+
+ /* Error if we are not in any block. */
+ if (thisblock == 0)
+ return 0;
+
+ /* Record the cleanup for the dynamic handler chain. */
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+ cleanup = make_node (POPDCC_EXPR);
+ pop_obstacks ();
+
+ /* Add the cleanup in a manner similar to expand_decl_cleanup. */
+ thisblock->data.block.cleanups
+ = temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
+
+ /* If this block has a cleanup, it belongs in stack_block_stack. */
+ stack_block_stack = thisblock;
+ return 1;
+}
+
+/* Arrange for the top element of the dynamic handler chain to be
+ popped if we exit the current binding contour. DECL is the
+ associated declaration, if any, otherwise NULL_TREE. If the current
+ contour is left via an exception, then __sjthrow will pop the top
+ element off the dynamic handler chain. The code that avoids doing
+ the action we push into the handler chain in the exceptional case
+ is contained in expand_cleanups.
+
+ This routine is only used by expand_eh_region_start, and that is
+ the only way in which an exception region should be started. This
+ routine is only used when using the setjmp/longjmp codegen method
+ for exception handling. */
+
+int
+expand_dhc_cleanup (decl)
+ tree decl;
+{
+ struct nesting *thisblock = block_stack;
+ tree cleanup;
+
+ /* Error if we are not in any block. */
+ if (thisblock == 0)
+ return 0;
+
+ /* Record the cleanup for the dynamic handler chain. */
+
+ /* All cleanups must be on the function_obstack. */
+ push_obstacks_nochange ();
+ resume_temporary_allocation ();
+ cleanup = make_node (POPDHC_EXPR);
+ pop_obstacks ();
+
+ /* Add the cleanup in a manner similar to expand_decl_cleanup. */
+ thisblock->data.block.cleanups
+ = temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
+
+ /* If this block has a cleanup, it belongs in stack_block_stack. */
+ stack_block_stack = thisblock;
+ return 1;
+}
/* DECL is an anonymous union. CLEANUP is a cleanup for DECL.
DECL_ELTS is the list of elements that belong to DECL's type.
@@ -3811,7 +4216,19 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
else
{
if (! in_fixup)
- (*interim_eh_hook) (TREE_VALUE (tail));
+ {
+ tree cleanup = TREE_VALUE (tail);
+
+ /* See expand_d{h,c}c_cleanup for why we avoid this. */
+ if (TREE_CODE (cleanup) != POPDHC_EXPR
+ && TREE_CODE (cleanup) != POPDCC_EXPR
+ /* See expand_eh_region_start_tree for this case. */
+ && ! TREE_ADDRESSABLE (tail))
+ {
+ cleanup = protect_with_terminate (cleanup);
+ expand_eh_region_end (cleanup);
+ }
+ }
if (reachable)
{
@@ -3830,6 +4247,35 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
}
}
+/* Mark when the context we are emitting RTL for as a conditional
+ context, so that any cleanup actions we register with
+ expand_decl_init will be properly conditionalized when those
+ cleanup actions are later performed. Must be called before any
+ expression (tree) is expanded that is within a conditional context. */
+
+void
+start_cleanup_deferral ()
+{
+ /* block_stack can be NULL if we are inside the parameter list. It is
+ OK to do nothing, because cleanups aren't possible here. */
+ if (block_stack)
+ ++block_stack->data.block.conditional_code;
+}
+
+/* Mark the end of a conditional region of code. Because cleanup
+ deferrals may be nested, we may still be in a conditional region
+ after we end the currently deferred cleanups, only after we end all
+ deferred cleanups, are we back in unconditional code. */
+
+void
+end_cleanup_deferral ()
+{
+ /* block_stack can be NULL if we are inside the parameter list. It is
+ OK to do nothing, because cleanups aren't possible here. */
+ if (block_stack)
+ --block_stack->data.block.conditional_code;
+}
+
/* Move all cleanups from the current block_stack
to the containing block_stack, where they are assumed to
have been created. If anything can cause a temporary to
@@ -3873,11 +4319,7 @@ any_pending_cleanups (this_contour)
if (this_contour && block_stack->data.block.cleanups != NULL)
return 1;
if (block_stack->data.block.cleanups == 0
- && (block_stack->data.block.outer_cleanups == 0
-#if 0
- || block_stack->data.block.outer_cleanups == empty_cleanup_list
-#endif
- ))
+ && block_stack->data.block.outer_cleanups == 0)
return 0;
for (block = block_stack->next; block; block = block->next)
@@ -3938,11 +4380,13 @@ expand_start_case (exit_flag, expr, type, printname)
emit_note (NULL_PTR, NOTE_INSN_DELETED);
thiscase->data.case_stmt.start = get_last_insn ();
+
+ start_cleanup_deferral ();
}
/* Enter a case statement. It is assumed that the caller has pushed
- the current context onto the case stack. */
+ the current context onto the case stack. */
static void
bc_expand_start_case (thiscase, expr, type, printname)
@@ -3990,6 +4434,7 @@ expand_start_case_dummy ()
thiscase->data.case_stmt.num_ranges = 0;
case_stack = thiscase;
nesting_stack = thiscase;
+ start_cleanup_deferral ();
}
/* End a dummy case statement. */
@@ -3997,6 +4442,7 @@ expand_start_case_dummy ()
void
expand_end_case_dummy ()
{
+ end_cleanup_deferral ();
POPSTACK (case_stack);
}
@@ -4021,7 +4467,7 @@ case_index_expr_type ()
If VALUE is a duplicate or overlaps, return 2 and do nothing
except store the (first) duplicate node in *DUPLICATE.
If VALUE is out of range, return 3 and do nothing.
- If we are jumping into the scope of a cleaup or var-sized array, return 5.
+ If we are jumping into the scope of a cleanup or var-sized array, return 5.
Return 0 on success.
Extended to handle range statements. */
@@ -4097,46 +4543,20 @@ pushcase (value, converter, label, duplicate)
case_stack->data.case_stmt.default_label = label;
}
else
- {
- /* Find the elt in the chain before which to insert the new value,
- to keep the chain sorted in increasing order.
- But report an error if this element is a duplicate. */
- for (l = &case_stack->data.case_stmt.case_list;
- /* Keep going past elements distinctly less than VALUE. */
- *l != 0 && tree_int_cst_lt ((*l)->high, value);
- l = &(*l)->right)
- ;
- if (*l)
- {
- /* Element we will insert before must be distinctly greater;
- overlap means error. */
- if (! tree_int_cst_lt (value, (*l)->low))
- {
- *duplicate = (*l)->code_label;
- return 2;
- }
- }
-
- /* Add this label to the chain, and succeed.
- Copy VALUE so it is on temporary rather than momentary
- obstack and will thus survive till the end of the case statement. */
- n = (struct case_node *) oballoc (sizeof (struct case_node));
- n->left = 0;
- n->right = *l;
- n->high = n->low = copy_node (value);
- n->code_label = label;
- *l = n;
- }
+ return add_case_node (value, value, label, duplicate);
expand_label (label);
return 0;
}
-/* Like pushcase but this case applies to all values
- between VALUE1 and VALUE2 (inclusive).
- The return value is the same as that of pushcase
- but there is one additional error code:
- 4 means the specified range was empty. */
+/* Like pushcase but this case applies to all values between VALUE1 and
+ VALUE2 (inclusive). If VALUE1 is NULL, the range starts at the lowest
+ value of the index type and ends at VALUE2. If VALUE2 is NULL, the range
+ starts at VALUE1 and ends at the highest value of the index type.
+ If both are NULL, this case applies to all values.
+
+ The return value is the same as that of pushcase but there is one
+ additional error code: 4 means the specified range was empty. */
int
pushcase_range (value1, value2, converter, label, duplicate)
@@ -4186,76 +4606,270 @@ pushcase_range (value1, value2, converter, label, duplicate)
}
case_stack->data.case_stmt.seenlabel = 1;
- /* Convert VALUEs to type in which the comparisons are nominally done. */
- if (value1 == 0) /* Negative infinity. */
- value1 = TYPE_MIN_VALUE(index_type);
- value1 = (*converter) (nominal_type, value1);
+ /* Convert VALUEs to type in which the comparisons are nominally done
+ and replace any unspecified value with the corresponding bound. */
+ if (value1 == 0)
+ value1 = TYPE_MIN_VALUE (index_type);
+ if (value2 == 0)
+ value2 = TYPE_MAX_VALUE (index_type);
+
+ /* Fail if the range is empty. Do this before any conversion since
+ we want to allow out-of-range empty ranges. */
+ if (tree_int_cst_lt (value2, value1))
+ return 4;
- if (value2 == 0) /* Positive infinity. */
- value2 = TYPE_MAX_VALUE(index_type);
+ value1 = (*converter) (nominal_type, value1);
value2 = (*converter) (nominal_type, value2);
/* Fail if these values are out of range. */
- if (! int_fits_type_p (value1, index_type))
+ if (TREE_CONSTANT_OVERFLOW (value1)
+ || ! int_fits_type_p (value1, index_type))
return 3;
- if (! int_fits_type_p (value2, index_type))
+ if (TREE_CONSTANT_OVERFLOW (value2)
+ || ! int_fits_type_p (value2, index_type))
return 3;
- /* Fail if the range is empty. */
- if (tree_int_cst_lt (value2, value1))
- return 4;
+ return add_case_node (value1, value2, label, duplicate);
+}
- /* If the bounds are equal, turn this into the one-value case. */
- if (tree_int_cst_equal (value1, value2))
- return pushcase (value1, converter, label, duplicate);
-
- /* Find the elt in the chain before which to insert the new value,
- to keep the chain sorted in increasing order.
- But report an error if this element is a duplicate. */
- for (l = &case_stack->data.case_stmt.case_list;
- /* Keep going past elements distinctly less than this range. */
- *l != 0 && tree_int_cst_lt ((*l)->high, value1);
- l = &(*l)->right)
- ;
- if (*l)
+/* Do the actual insertion of a case label for pushcase and pushcase_range
+ into case_stack->data.case_stmt.case_list. Use an AVL tree to avoid
+ slowdown for large switch statements. */
+
+static int
+add_case_node (low, high, label, duplicate)
+ tree low, high;
+ tree label;
+ tree *duplicate;
+{
+ struct case_node *p, **q, *r;
+
+ q = &case_stack->data.case_stmt.case_list;
+ p = *q;
+
+ while (r = *q)
{
- /* Element we will insert before must be distinctly greater;
- overlap means error. */
- if (! tree_int_cst_lt (value2, (*l)->low))
+ p = r;
+
+ /* Keep going past elements distinctly greater than HIGH. */
+ if (tree_int_cst_lt (high, p->low))
+ q = &p->left;
+
+ /* or distinctly less than LOW. */
+ else if (tree_int_cst_lt (p->high, low))
+ q = &p->right;
+
+ else
{
- *duplicate = (*l)->code_label;
+ /* We have an overlap; this is an error. */
+ *duplicate = p->code_label;
return 2;
}
}
/* Add this label to the chain, and succeed.
- Copy VALUE1, VALUE2 so they are on temporary rather than momentary
+ Copy LOW, HIGH so they are on temporary rather than momentary
obstack and will thus survive till the end of the case statement. */
- n = (struct case_node *) oballoc (sizeof (struct case_node));
- n->left = 0;
- n->right = *l;
- n->low = copy_node (value1);
- n->high = copy_node (value2);
- n->code_label = label;
- *l = n;
+ r = (struct case_node *) oballoc (sizeof (struct case_node));
+ r->low = copy_node (low);
+
+ /* If the bounds are equal, turn this into the one-value case. */
+
+ if (tree_int_cst_equal (low, high))
+ r->high = r->low;
+ else
+ {
+ r->high = copy_node (high);
+ case_stack->data.case_stmt.num_ranges++;
+ }
+ r->code_label = label;
expand_label (label);
- case_stack->data.case_stmt.num_ranges++;
+ *q = r;
+ r->parent = p;
+ r->left = 0;
+ r->right = 0;
+ r->balance = 0;
+
+ while (p)
+ {
+ struct case_node *s;
+
+ if (r == p->left)
+ {
+ int b;
+
+ if (! (b = p->balance))
+ /* Growth propagation from left side. */
+ p->balance = -1;
+ else if (b < 0)
+ {
+ if (r->balance < 0)
+ {
+ /* R-Rotation */
+ if (p->left = s = r->right)
+ s->parent = p;
+
+ r->right = p;
+ p->balance = 0;
+ r->balance = 0;
+ s = p->parent;
+ p->parent = r;
+
+ if (r->parent = s)
+ {
+ if (s->left == p)
+ s->left = r;
+ else
+ s->right = r;
+ }
+ else
+ case_stack->data.case_stmt.case_list = r;
+ }
+ else
+ /* r->balance == +1 */
+ {
+ /* LR-Rotation */
+
+ int b2;
+ struct case_node *t = r->right;
+
+ if (p->left = s = t->right)
+ s->parent = p;
+
+ t->right = p;
+ if (r->right = s = t->left)
+ s->parent = r;
+
+ t->left = r;
+ b = t->balance;
+ b2 = b < 0;
+ p->balance = b2;
+ b2 = -b2 - b;
+ r->balance = b2;
+ t->balance = 0;
+ s = p->parent;
+ p->parent = t;
+ r->parent = t;
+
+ if (t->parent = s)
+ {
+ if (s->left == p)
+ s->left = t;
+ else
+ s->right = t;
+ }
+ else
+ case_stack->data.case_stmt.case_list = t;
+ }
+ break;
+ }
+
+ else
+ {
+ /* p->balance == +1; growth of left side balances the node. */
+ p->balance = 0;
+ break;
+ }
+ }
+ else
+ /* r == p->right */
+ {
+ int b;
+
+ if (! (b = p->balance))
+ /* Growth propagation from right side. */
+ p->balance++;
+ else if (b > 0)
+ {
+ if (r->balance > 0)
+ {
+ /* L-Rotation */
+
+ if (p->right = s = r->left)
+ s->parent = p;
+
+ r->left = p;
+ p->balance = 0;
+ r->balance = 0;
+ s = p->parent;
+ p->parent = r;
+ if (r->parent = s)
+ {
+ if (s->left == p)
+ s->left = r;
+ else
+ s->right = r;
+ }
+
+ else
+ case_stack->data.case_stmt.case_list = r;
+ }
+
+ else
+ /* r->balance == -1 */
+ {
+ /* RL-Rotation */
+ int b2;
+ struct case_node *t = r->left;
+
+ if (p->right = s = t->left)
+ s->parent = p;
+
+ t->left = p;
+
+ if (r->left = s = t->right)
+ s->parent = r;
+
+ t->right = r;
+ b = t->balance;
+ b2 = b < 0;
+ r->balance = b2;
+ b2 = -b2 - b;
+ p->balance = b2;
+ t->balance = 0;
+ s = p->parent;
+ p->parent = t;
+ r->parent = t;
+
+ if (t->parent = s)
+ {
+ if (s->left == p)
+ s->left = t;
+ else
+ s->right = t;
+ }
+
+ else
+ case_stack->data.case_stmt.case_list = t;
+ }
+ break;
+ }
+ else
+ {
+ /* p->balance == -1; growth of right side balances the node. */
+ p->balance = 0;
+ break;
+ }
+ }
+
+ r = p;
+ p = p->parent;
+ }
return 0;
}
-
/* Accumulate one case or default label; VALUE is the value of the
case, or nil for a default label. If not currently inside a case,
return 1 and do nothing. If VALUE is a duplicate or overlaps, return
2 and do nothing. If VALUE is out of range, return 3 and do nothing.
Return 0 on success. This function is a leftover from the earlier
bytecode compiler, which was based on gcc 1.37. It should be
- merged into pushcase. */
+ merged into pushcase. */
static int
bc_pushcase (value, label)
@@ -4282,7 +4896,7 @@ bc_pushcase (value, label)
if (case_label != thiscase->data.case_stmt.case_list
&& ! tree_int_cst_lt (case_label->high, value)
- || case_label->left && ! tree_int_cst_lt (value, case_label->left->low))
+ || (case_label->left && ! tree_int_cst_lt (value, case_label->left->low)))
return 2;
new_label = (struct case_node *) oballoc (sizeof (struct case_node));
@@ -4339,7 +4953,7 @@ all_cases_count (type, spareness)
/* count
= TREE_INT_CST_LOW (TYPE_MAX_VALUE (type))
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (type)) + 1
- but with overflow checking. */
+ but with overflow checking. */
tree mint = TYPE_MIN_VALUE (type);
tree maxt = TYPE_MAX_VALUE (type);
HOST_WIDE_INT lo, hi;
@@ -4384,11 +4998,11 @@ all_cases_count (type, spareness)
#define BITARRAY_TEST(ARRAY, INDEX) \
- ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
- & (1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR)))
+ ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
+ & (1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR)))
#define BITARRAY_SET(ARRAY, INDEX) \
- ((ARRAY)[(unsigned)(INDEX) / HOST_BITS_PER_CHAR]\
- |= 1 << ((unsigned)(INDEX) % HOST_BITS_PER_CHAR))
+ ((ARRAY)[(unsigned) (INDEX) / HOST_BITS_PER_CHAR]\
+ |= 1 << ((unsigned) (INDEX) % HOST_BITS_PER_CHAR))
/* Set the elements of the bitstring CASES_SEEN (which has length COUNT),
with the case values we have seen, assuming the case expression
@@ -4410,36 +5024,62 @@ mark_seen_cases (type, cases_seen, count, sparseness)
tree next_node_to_try = NULL_TREE;
long next_node_offset = 0;
- register struct case_node *n;
+ register struct case_node *n, *root = case_stack->data.case_stmt.case_list;
tree val = make_node (INTEGER_CST);
TREE_TYPE (val) = type;
- for (n = case_stack->data.case_stmt.case_list; n;
- n = n->right)
+ if (! root)
+ ; /* Do nothing */
+ else if (sparseness == 2)
{
- TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
- TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
- while ( ! tree_int_cst_lt (n->high, val))
+ tree t;
+ HOST_WIDE_INT xlo;
+
+ /* This less efficient loop is only needed to handle
+ duplicate case values (multiple enum constants
+ with the same value). */
+ TREE_TYPE (val) = TREE_TYPE (root->low);
+ for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
+ t = TREE_CHAIN (t), xlo++)
{
- /* Calculate (into xlo) the "offset" of the integer (val).
- The element with lowest value has offset 0, the next smallest
- element has offset 1, etc. */
-
- HOST_WIDE_INT xlo, xhi;
- tree t;
- if (sparseness == 2)
+ TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (TREE_VALUE (t));
+ TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (TREE_VALUE (t));
+ n = root;
+ do
{
- /* This less efficient loop is only needed to handle
- duplicate case values (multiple enum constants
- with the same value). */
- for (t = TYPE_VALUES (type), xlo = 0; t != NULL_TREE;
- t = TREE_CHAIN (t), xlo++)
+ /* Keep going past elements distinctly greater than VAL. */
+ if (tree_int_cst_lt (val, n->low))
+ n = n->left;
+
+ /* or distinctly less than VAL. */
+ else if (tree_int_cst_lt (n->high, val))
+ n = n->right;
+
+ else
{
- if (tree_int_cst_equal (val, TREE_VALUE (t)))
- BITARRAY_SET (cases_seen, xlo);
+ /* We have found a matching range. */
+ BITARRAY_SET (cases_seen, xlo);
+ break;
}
}
- else
+ while (n);
+ }
+ }
+ else
+ {
+ if (root->left)
+ case_stack->data.case_stmt.case_list = root = case_tree2list (root, 0);
+ for (n = root; n; n = n->right)
+ {
+ TREE_INT_CST_LOW (val) = TREE_INT_CST_LOW (n->low);
+ TREE_INT_CST_HIGH (val) = TREE_INT_CST_HIGH (n->low);
+ while ( ! tree_int_cst_lt (n->high, val))
{
+ /* Calculate (into xlo) the "offset" of the integer (val).
+ The element with lowest value has offset 0, the next smallest
+ element has offset 1, etc. */
+
+ HOST_WIDE_INT xlo, xhi;
+ tree t;
if (sparseness && TYPE_VALUES (type) != NULL_TREE)
{
/* The TYPE_VALUES will be in increasing order, so
@@ -4463,7 +5103,10 @@ mark_seen_cases (type, cases_seen, count, sparseness)
xlo++;
t = TREE_CHAIN (t);
if (t == next_node_to_try)
- break;
+ {
+ xlo = -1;
+ break;
+ }
}
}
else
@@ -4481,10 +5124,10 @@ mark_seen_cases (type, cases_seen, count, sparseness)
if (xhi == 0 && xlo >= 0 && xlo < count)
BITARRAY_SET (cases_seen, xlo);
+ add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
+ 1, 0,
+ &TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
}
- add_double (TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val),
- 1, 0,
- &TREE_INT_CST_LOW (val), &TREE_INT_CST_HIGH (val));
}
}
}
@@ -4509,17 +5152,17 @@ check_for_full_enumeration_handling (type)
register tree chain;
int all_values = 1;
- /* True iff the selector type is a numbered set mode. */
+ /* True iff the selector type is a numbered set mode. */
int sparseness = 0;
- /* The number of possible selector values. */
+ /* The number of possible selector values. */
HOST_WIDE_INT size;
/* For each possible selector value. a one iff it has been matched
- by a case value alternative. */
+ by a case value alternative. */
unsigned char *cases_seen;
- /* The allocated size of cases_seen, in chars. */
+ /* The allocated size of cases_seen, in chars. */
long bytes_needed;
tree t;
@@ -4536,7 +5179,7 @@ check_for_full_enumeration_handling (type)
bytes_needed = (size + HOST_BITS_PER_CHAR) / HOST_BITS_PER_CHAR;
if (size > 0 && size < 600000
- /* We deliberately use malloc here - not xmalloc. */
+ /* We deliberately use malloc here - not xmalloc. */
&& (cases_seen = (unsigned char *) malloc (bytes_needed)) != NULL)
{
long i;
@@ -4546,7 +5189,7 @@ check_for_full_enumeration_handling (type)
/* The time complexity of this code is normally O(N), where
N being the number of members in the enumerated type.
However, if type is a ENUMERAL_TYPE whose values do not
- increase monotonically, quadratic time may be needed. */
+ increase monotonically, O(N*log(N)) time may be needed. */
mark_seen_cases (type, cases_seen, size, sparseness);
@@ -4563,8 +5206,12 @@ check_for_full_enumeration_handling (type)
/* Now we go the other way around; we warn if there are case
expressions that don't correspond to enumerators. This can
occur since C and C++ don't enforce type-checking of
- assignments to enumeration variables. */
+ assignments to enumeration variables. */
+ if (case_stack->data.case_stmt.case_list
+ && case_stack->data.case_stmt.case_list->left)
+ case_stack->data.case_stmt.case_list
+ = case_tree2list (case_stack->data.case_stmt.case_list, 0);
if (warn_switch)
for (n = case_stack->data.case_stmt.case_list; n; n = n->right)
{
@@ -4748,6 +5395,11 @@ expand_end_case (orig_index)
before_case = get_last_insn ();
+ if (thiscase->data.case_stmt.case_list
+ && thiscase->data.case_stmt.case_list->left)
+ thiscase->data.case_stmt.case_list
+ = case_tree2list(thiscase->data.case_stmt.case_list, 0);
+
/* Simplify the case-list before we count it. */
group_case_nodes (thiscase->data.case_stmt.case_list);
@@ -4791,6 +5443,8 @@ expand_end_case (orig_index)
if (count != 0)
range = fold (build (MINUS_EXPR, index_type, maxval, minval));
+ end_cleanup_deferral ();
+
if (count == 0)
{
expand_expr (index_expr, const0_rtx, VOIDmode, 0);
@@ -4818,6 +5472,9 @@ expand_end_case (orig_index)
|| count < CASE_VALUES_THRESHOLD
|| ((unsigned HOST_WIDE_INT) (TREE_INT_CST_LOW (range))
> 10 * count)
+#ifndef ASM_OUTPUT_ADDR_DIFF_ELT
+ || flag_pic
+#endif
|| TREE_CODE (index_expr) == INTEGER_CST
/* These will reduce to a constant. */
|| (TREE_CODE (index_expr) == CALL_EXPR
@@ -5055,6 +5712,8 @@ expand_end_case (orig_index)
reorder_insns (before_case, get_last_insn (),
thiscase->data.case_stmt.start);
}
+ else
+ end_cleanup_deferral ();
if (thiscase->exit_label)
emit_label (thiscase->exit_label);
@@ -5064,6 +5723,28 @@ expand_end_case (orig_index)
free_temp_slots ();
}
+/* Convert the tree NODE into a list linked by the right field, with the left
+ field zeroed. RIGHT is used for recursion; it is a list to be placed
+ rightmost in the resulting list. */
+
+static struct case_node *
+case_tree2list (node, right)
+ struct case_node *node, *right;
+{
+ struct case_node *left;
+
+ if (node->right)
+ right = case_tree2list (node->right, right);
+
+ node->right = right;
+ if (left = node->left)
+ {
+ node->left = 0;
+ return case_tree2list (left, node);
+ }
+
+ return node;
+}
/* Terminate a case statement. EXPR is the original index
expression. */
@@ -5159,7 +5840,7 @@ bc_expand_end_case (expr)
}
-/* Return unique bytecode ID. */
+/* Return unique bytecode ID. */
int
bc_new_uid ()
@@ -5286,12 +5967,18 @@ group_case_nodes (head)
while (node)
{
rtx lb = next_real_insn (label_rtx (node->code_label));
+ rtx lb2;
case_node_ptr np = node;
/* Try to group the successors of NODE with NODE. */
while (((np = np->right) != 0)
/* Do they jump to the same place? */
- && next_real_insn (label_rtx (np->code_label)) == lb
+ && ((lb2 = next_real_insn (label_rtx (np->code_label))) == lb
+ || (lb != 0 && lb2 != 0
+ && simplejump_p (lb)
+ && simplejump_p (lb2)
+ && rtx_equal_p (SET_SRC (PATTERN (lb)),
+ SET_SRC (PATTERN (lb2)))))
/* Are their ranges consecutive? */
&& tree_int_cst_equal (np->low,
fold (build (PLUS_EXPR,
@@ -5600,7 +6287,7 @@ emit_case_nodes (index, node, default_label, index_type)
else if (tree_int_cst_equal (node->low, node->high))
{
/* Node is single valued. First see if the index expression matches
- this node and then check our children, if any. */
+ this node and then check our children, if any. */
do_jump_if_equal (index, expand_expr (node->low, NULL_RTX, VOIDmode, 0),
label_rtx (node->code_label), unsignedp);
@@ -5866,10 +6553,6 @@ find_loop_tree_blocks ()
{
tree block = DECL_INITIAL (current_function_decl);
- /* There first block is for the function body, and does not have
- corresponding block notes. Don't include it in the block vector. */
- block = BLOCK_SUBBLOCKS (block);
-
block_vector = identify_blocks (block, get_insns ());
}
@@ -5880,4 +6563,3 @@ unroll_block_trees ()
reorder_blocks (block_vector, block, get_insns ());
}
-
diff --git a/gnu/usr.bin/gcc/stupid.c b/gnu/usr.bin/gcc/stupid.c
index ed1afcf7dbe..77cbab2ed60 100644
--- a/gnu/usr.bin/gcc/stupid.c
+++ b/gnu/usr.bin/gcc/stupid.c
@@ -1,5 +1,5 @@
/* Dummy data flow analysis for GNU compiler in nonoptimizing mode.
- Copyright (C) 1987, 1991, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -42,8 +42,8 @@ Boston, MA 02111-1307, USA. */
pseudo reg is computed. Then the pseudo regs are ordered by priority
and assigned hard regs in priority order. */
-#include <stdio.h>
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "hard-reg-set.h"
#include "regs.h"
@@ -65,6 +65,11 @@ static int *uid_suid;
static int last_call_suid;
+/* Record the suid of the last NOTE_INSN_SETJMP
+ so we can tell whether a pseudo reg crosses any setjmp. */
+
+static int last_setjmp_suid;
+
/* Element N is suid of insn where life span of pseudo reg N ends.
Element is 0 if register N has not been seen yet on backward scan. */
@@ -88,6 +93,10 @@ static char *regs_live;
static char *regs_change_size;
+/* Indexed by reg number, nonzero if reg crosses a setjmp. */
+
+static char *regs_crosses_setjmp;
+
/* Indexed by insn's suid, the set of hard regs live after that insn. */
static HARD_REG_SET *after_insn_hard_regs;
@@ -97,7 +106,7 @@ static HARD_REG_SET *after_insn_hard_regs;
#define MARK_LIVE_AFTER(INSN,REGNO) \
SET_HARD_REG_BIT (after_insn_hard_regs[INSN_SUID (INSN)], (REGNO))
-static int stupid_reg_compare PROTO((int *, int *));
+static int stupid_reg_compare PROTO((const GENERIC_PTR,const GENERIC_PTR));
static int stupid_find_reg PROTO((int, enum reg_class, enum machine_mode,
int, int, int));
static void stupid_mark_refs PROTO((rtx, rtx));
@@ -148,6 +157,7 @@ stupid_life_analysis (f, nregs, file)
}
last_call_suid = i + 1;
+ last_setjmp_suid = i + 1;
max_suid = i + 1;
max_regno = nregs;
@@ -166,13 +176,14 @@ stupid_life_analysis (f, nregs, file)
regs_change_size = (char *) alloca (nregs * sizeof (char));
bzero ((char *) regs_change_size, nregs * sizeof (char));
- reg_renumber = (short *) oballoc (nregs * sizeof (short));
+ regs_crosses_setjmp = (char *) alloca (nregs * sizeof (char));
+ bzero ((char *) regs_crosses_setjmp, nregs * sizeof (char));
+
+ /* Allocate the reg_renumber array */
+ allocate_reg_info (max_regno, FALSE, TRUE);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
reg_renumber[i] = i;
- for (i = FIRST_VIRTUAL_REGISTER; i < max_regno; i++)
- reg_renumber[i] = -1;
-
after_insn_hard_regs
= (HARD_REG_SET *) alloca (max_suid * sizeof (HARD_REG_SET));
@@ -184,7 +195,7 @@ stupid_life_analysis (f, nregs, file)
allocate_for_life_analysis ();
for (i = 0; i < max_regno; i++)
- reg_n_deaths[i] = 1;
+ REG_N_DEATHS (i) = 1;
bzero (regs_live, nregs);
@@ -215,6 +226,10 @@ stupid_life_analysis (f, nregs, file)
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
stupid_mark_refs (PATTERN (insn), insn);
+ if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+ last_setjmp_suid = INSN_SUID (insn);
+
/* Mark all call-clobbered regs as live after each call insn
so that a pseudo whose life span includes this insn
will not go in one of them.
@@ -253,13 +268,17 @@ stupid_life_analysis (f, nregs, file)
{
register int r = reg_order[i];
- /* Some regnos disappear from the rtl. Ignore them to avoid crash. */
- if (regno_reg_rtx[r] == 0)
+ /* Some regnos disappear from the rtl. Ignore them to avoid crash.
+ Also don't allocate registers that cross a setjmp, or live across
+ a call if this function receives a nonlocal goto. */
+ if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r]
+ || (REG_N_CALLS_CROSSED (r) > 0
+ && current_function_has_nonlocal_label))
continue;
/* Now find the best hard-register class for this pseudo register */
if (N_REG_CLASSES > 1)
- reg_renumber[r] = stupid_find_reg (reg_n_calls_crossed[r],
+ reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
reg_preferred_class (r),
PSEUDO_REGNO_MODE (r),
reg_where_born[r],
@@ -268,7 +287,7 @@ stupid_life_analysis (f, nregs, file)
/* If no reg available in that class, try alternate class. */
if (reg_renumber[r] == -1 && reg_alternate_class (r) != NO_REGS)
- reg_renumber[r] = stupid_find_reg (reg_n_calls_crossed[r],
+ reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
reg_alternate_class (r),
PSEUDO_REGNO_MODE (r),
reg_where_born[r],
@@ -285,9 +304,10 @@ stupid_life_analysis (f, nregs, file)
static int
stupid_reg_compare (r1p, r2p)
- int *r1p, *r2p;
+ const GENERIC_PTR r1p;
+ const GENERIC_PTR r2p;
{
- register int r1 = *r1p, r2 = *r2p;
+ register int r1 = *(int *)r1p, r2 = *(int *)r2p;
register int len1 = reg_where_dead[r1] - reg_where_born[r1];
register int len2 = reg_where_dead[r2] - reg_where_born[r2];
int tem;
@@ -296,7 +316,7 @@ stupid_reg_compare (r1p, r2p)
if (tem != 0)
return tem;
- tem = reg_n_refs[r1] - reg_n_refs[r2];
+ tem = REG_N_REFS (r1) - REG_N_REFS (r2);
if (tem != 0)
return tem;
@@ -308,8 +328,8 @@ stupid_reg_compare (r1p, r2p)
/* Find a block of SIZE words of hard registers in reg_class CLASS
that can hold a value of machine-mode MODE
(but actually we test only the first of the block for holding MODE)
- currently free from after insn whose suid is BIRTH
- through the insn whose suid is DEATH,
+ currently free from after insn whose suid is BORN_INSN
+ through the insn whose suid is DEAD_INSN,
and return the number of the first of them.
Return -1 if such a block cannot be found.
@@ -337,6 +357,13 @@ stupid_find_reg (call_preserved, class, mode,
static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
+ /* If this register's life is more than 5,000 insns, we probably
+ can't allocate it, so don't waste the time trying. This avoids
+ quadratic behavior on programs that have regularly-occurring
+ SAVE_EXPRs. */
+ if (dead_insn > born_insn + 5000)
+ return -1;
+
COPY_HARD_REG_SET (used,
call_preserved ? call_used_reg_set : fixed_reg_set);
@@ -450,13 +477,13 @@ stupid_mark_refs (x, insn)
/* The following line is for unused outputs;
they do get stored even though never used again. */
- MARK_LIVE_AFTER (insn, regno);
+ MARK_LIVE_AFTER (insn, regno+j);
/* When a hard reg is clobbered, mark it in use
just before this insn, so it is live all through. */
if (code == CLOBBER && INSN_SUID (insn) > 0)
SET_HARD_REG_BIT (after_insn_hard_regs[INSN_SUID (insn) - 1],
- regno);
+ regno+j);
}
}
/* For pseudo regs, record where born, where dead, number of
@@ -483,10 +510,26 @@ stupid_mark_refs (x, insn)
}
/* Count the refs of this reg. */
- reg_n_refs[regno]++;
+ REG_N_REFS (regno)++;
if (last_call_suid < reg_where_dead[regno])
- reg_n_calls_crossed[regno] += 1;
+ REG_N_CALLS_CROSSED (regno) += 1;
+
+ if (last_setjmp_suid < reg_where_dead[regno])
+ regs_crosses_setjmp[regno] = 1;
+
+ /* If this register is only used in this insn and is only
+ set, mark it unused. We have to do this even when not
+ optimizing so that MD patterns which count on this
+ behavior (e.g., it not causing an output reload on
+ an insn setting CC) will operate correctly. */
+ if (GET_CODE (SET_DEST (x)) == REG
+ && REGNO_FIRST_UID (regno) == INSN_UID (insn)
+ && REGNO_LAST_UID (regno) == INSN_UID (insn)
+ && (code == CLOBBER || ! reg_mentioned_p (SET_DEST (x),
+ SET_SRC (x))))
+ REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_UNUSED,
+ SET_DEST (x), REG_NOTES (insn));
}
}
@@ -531,7 +574,7 @@ stupid_mark_refs (x, insn)
/* Pseudo reg: record first use, last use and number of uses. */
reg_where_born[regno] = INSN_SUID (insn);
- reg_n_refs[regno]++;
+ REG_N_REFS (regno)++;
if (regs_live[regno] == 0)
{
regs_live[regno] = 1;
diff --git a/gnu/usr.bin/gcc/sys-protos.h b/gnu/usr.bin/gcc/sys-protos.h
index c9b8c4b1655..ab6e407e8f1 100644
--- a/gnu/usr.bin/gcc/sys-protos.h
+++ b/gnu/usr.bin/gcc/sys-protos.h
@@ -127,8 +127,8 @@ extern AUTH * authunix_create(char *, int, int, int, int *);
extern AUTH * authunix_create_default(void);
extern char * basename(char *);
extern int baudrate(void);
-extern int bcmp(const void *, const void *, int);
-extern void bcopy(const void *, void *, int);
+extern int bcmp(const void *, const void *, size_t);
+extern void bcopy(const void *, void *, size_t);
extern int beep(void);
extern void (* berk_signal(int, void (*) (int, ...))) (int, ...);
extern char * bgets(char *, size_t, FILE *, char *);
@@ -449,8 +449,12 @@ extern int getgroups(int, gid_t *);
extern struct hostent * gethostbyaddr(/* ??? */);
extern struct hostent * gethostbyname(/* ??? */);
extern struct hostent * gethostent(/* ??? */);
+#ifdef __alpha__
+extern int gethostid(void);
+#else
extern long gethostid(void);
-extern int gethostname(char *, int);
+#endif
+extern int gethostname(char *, size_t);
extern int getitimer(int, struct itimerval *);
extern char * getlogin(void);
extern int getmaxx(WINDOW *);
@@ -645,7 +649,7 @@ extern dl_t lmul(/* ??? */);
extern struct lconv * localeconv(void);
extern struct tm * localtime(const time_t *);
extern int lock(int, int, long);
-extern int lockf(int, int, long int);
+extern int lockf(int, int, off_t);
extern double log(double);
extern double log10(double);
extern float log10f(float);
@@ -858,9 +862,9 @@ extern int raise(int);
extern int rand(void);
extern long random(void);
extern int raw(void);
-extern int read(int, void *, size_t);
+extern ssize_t read(int, void *, size_t);
extern struct dirent * readdir(DIR *);
-extern int readlink(const char *, void *, int);
+extern ssize_t readlink(const char *, char *, size_t);
extern void * realloc(void *, size_t);
extern char * realpath(char *, char *);
extern int redrawwin(WINDOW *);
@@ -1048,6 +1052,7 @@ extern int slk_restore(void);
extern int slk_set(int, char *, int);
extern int slk_start(int, int *);
extern int slk_touch(void);
+extern int socket (int, int, int);
extern void * sprayproc_clear_1(/* ??? */);
extern spraycumul * sprayproc_get_1(/* ??? */);
extern void * sprayproc_spray_1(/* ??? */);
@@ -1069,6 +1074,7 @@ extern int stime(const time_t *);
extern struct netbuf * stoa(char *, struct netbuf *);
extern void store(datum, datum);
extern char * strcadd(char *, const char *);
+extern int strcasecmp(const char *, const char *);
extern char * strcat(char *, const char *);
extern char * strccpy(char *, const char *);
extern char * strchr(const char *, int);
@@ -1086,6 +1092,7 @@ extern char * strerror(int);
extern int strfind(const char *, const char *);
extern size_t strftime(char *, size_t, const char *, const struct tm *);
extern size_t strlen(const char *);
+extern int strncasecmp(const char *, const char *, size_t);
extern char * strncat(char *, const char *, size_t);
extern int strncmp(const char *, const char *, size_t);
extern char * strncpy(char *, const char *, size_t);
@@ -1264,7 +1271,7 @@ extern int wnoutrefresh(WINDOW *);
extern int wprintw(WINDOW *, ...);
extern int wredrawln(WINDOW *, int, int);
extern int wrefresh(WINDOW *);
-extern int write(int, const void *, size_t);
+extern ssize_t write(int, const void *, size_t);
extern int wscanw(WINDOW *, ...);
extern int wscrl(WINDOW *, int);
extern int wsetscrreg(WINDOW *, int, int);
diff --git a/gnu/usr.bin/gcc/sys-types.h b/gnu/usr.bin/gcc/sys-types.h
index 527472f060b..7db46f112c5 100644
--- a/gnu/usr.bin/gcc/sys-types.h
+++ b/gnu/usr.bin/gcc/sys-types.h
@@ -86,6 +86,7 @@ union wait;
#include <stddef.h>
/* #include "sys/types.h" */
+#define ssize_t int
/* The actual types used here are mostly wrong,
but it is not supposed to matter what types we use here. */
diff --git a/gnu/usr.bin/gcc/texinfo.tex b/gnu/usr.bin/gcc/texinfo.tex
index 62ba616290a..d20af2b03a0 100644
--- a/gnu/usr.bin/gcc/texinfo.tex
+++ b/gnu/usr.bin/gcc/texinfo.tex
@@ -1,6 +1,8 @@
-%% TeX macros to handle texinfo files
+%% TeX macros to handle Texinfo files.
+%% $Id: texinfo.tex,v 1.1.1.2 1998/02/14 19:13:57 niklas Exp $
-% Copyright (C) 1985, 86, 88, 90, 91, 92, 93, 1994 Free Software Foundation, Inc.
+% Copyright (C) 1985, 86, 88, 90, 91, 92, 93,
+% 94, 95, 96, 97 Free Software Foundation, Inc.
%This texinfo.tex file is free software; you can redistribute it and/or
%modify it under the terms of the GNU General Public License as
@@ -14,8 +16,8 @@
%You should have received a copy of the GNU General Public License
%along with this texinfo.tex file; see the file COPYING. If not, write
-%to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
-%USA.
+%to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+%Boston, MA 02111-1307, USA.
%In other words, you are welcome to use, share and improve this program.
@@ -34,7 +36,7 @@
% This automatically updates the version number based on RCS.
\def\deftexinfoversion$#1: #2 ${\def\texinfoversion{#2}}
-\deftexinfoversion$Revision: 1.1.1.1 $
+\deftexinfoversion$Revision: 1.1.1.2 $
\message{Loading texinfo package [Version \texinfoversion]:}
% If in a .fmt file, print the version number
@@ -45,20 +47,19 @@
% Save some parts of plain tex whose names we will redefine.
-\let\ptextilde=\~
-\let\ptexlbrace=\{
-\let\ptexrbrace=\}
-\let\ptexdots=\dots
-\let\ptexdot=\.
-\let\ptexstar=\*
-\let\ptexend=\end
-\let\ptexbullet=\bullet
\let\ptexb=\b
+\let\ptexbullet=\bullet
\let\ptexc=\c
+\let\ptexcomma=\,
+\let\ptexdot=\.
+\let\ptexdots=\dots
+\let\ptexend=\end
+\let\ptexequiv = \equiv
\let\ptexi=\i
+\let\ptexlbrace=\{
+\let\ptexrbrace=\}
+\let\ptexstar=\*
\let\ptext=\t
-\let\ptexl=\l
-\let\ptexL=\L
% Be sure we're in horizontal mode when doing a tie, since we make space
% equivalent to this in @example-like environments. Otherwise, a space
@@ -69,9 +70,9 @@
% Avoid using \@M directly, because that causes trouble
% if the definition is written into an index file.
\global\let\tiepenalty = \@M
- \gdef\tie{\lvvmode\penalty\tiepenalty\ }
+ \gdef\tie{\leavevmode\penalty\tiepenalty\ }
}
-\let\~ = \tie % And make it available as @~.
+
\message{Basics,}
\chardef\other=12
@@ -100,12 +101,12 @@
\hyphenation{ap-pen-dix}
\hyphenation{mini-buf-fer mini-buf-fers}
\hyphenation{eshell}
+\hyphenation{white-space}
% Margin to add to right of even pages, to left of odd pages.
-\newdimen \bindingoffset \bindingoffset=0pt
-\newdimen \normaloffset \normaloffset=\hoffset
+\newdimen \bindingoffset
+\newdimen \normaloffset
\newdimen\pagewidth \newdimen\pageheight
-\pagewidth=\hsize \pageheight=\vsize
% Sometimes it is convenient to have everything in the transcript file
% and nothing on the terminal. We don't just call \tracingall here,
@@ -118,71 +119,100 @@
\showboxbreadth\maxdimen\showboxdepth\maxdimen
}%
-%---------------------Begin change-----------------------
+% For @cropmarks command.
+% Do @cropmarks to get crop marks.
+%
+\newif\ifcropmarks
+\let\cropmarks = \cropmarkstrue
%
-%%%% For @cropmarks command.
-% Dimensions to add cropmarks at corners Added by P. A. MacKay, 12 Nov. 1986
+% Dimensions to add cropmarks at corners.
+% Added by P. A. MacKay, 12 Nov. 1986
%
\newdimen\cornerlong \newdimen\cornerthick
-\newdimen \topandbottommargin
-\newdimen \outerhsize \newdimen \outervsize
-\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
+\newdimen\topandbottommargin
+\newdimen\outerhsize \newdimen\outervsize
+\cornerlong=1pc\cornerthick=.3pt % These set size of cropmarks
\outerhsize=7in
%\outervsize=9.5in
% Alternative @smallbook page size is 9.25in
\outervsize=9.25in
\topandbottommargin=.75in
-%
-%---------------------End change-----------------------
+
+% Main output routine.
+\chardef\PAGE = 255
+\output = {\onepageout{\pagecontents\PAGE}}
+
+\newbox\headlinebox
+\newbox\footlinebox
% \onepageout takes a vbox as an argument. Note that \pagecontents
-% does insertions itself, but you have to call it yourself.
-\chardef\PAGE=255 \output={\onepageout{\pagecontents\PAGE}}
-\def\onepageout#1{\hoffset=\normaloffset
-\ifodd\pageno \advance\hoffset by \bindingoffset
-\else \advance\hoffset by -\bindingoffset\fi
-{\escapechar=`\\\relax % makes sure backslash is used in output files.
-\shipout\vbox{{\let\hsize=\pagewidth \makeheadline} \pagebody{#1}%
-{\let\hsize=\pagewidth \makefootline}}}%
-\advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
-
-%%%% For @cropmarks command %%%%
-
-% Here is a modification of the main output routine for Near East Publications
-% This provides right-angle cropmarks at all four corners.
-% The contents of the page are centerlined into the cropmarks,
-% and any desired binding offset is added as an \hskip on either
-% site of the centerlined box. (P. A. MacKay, 12 November, 1986)
-%
-\def\croppageout#1{\hoffset=0pt % make sure this doesn't mess things up
-{\escapechar=`\\\relax % makes sure backslash is used in output files.
- \shipout
- \vbox to \outervsize{\hsize=\outerhsize
- \vbox{\line{\ewtop\hfill\ewtop}}
- \nointerlineskip
- \line{\vbox{\moveleft\cornerthick\nstop}
- \hfill
- \vbox{\moveright\cornerthick\nstop}}
- \vskip \topandbottommargin
- \centerline{\ifodd\pageno\hskip\bindingoffset\fi
- \vbox{
- {\let\hsize=\pagewidth \makeheadline}
- \pagebody{#1}
- {\let\hsize=\pagewidth \makefootline}}
- \ifodd\pageno\else\hskip\bindingoffset\fi}
- \vskip \topandbottommargin plus1fill minus1fill
- \boxmaxdepth\cornerthick
- \line{\vbox{\moveleft\cornerthick\nsbot}
- \hfill
- \vbox{\moveright\cornerthick\nsbot}}
- \nointerlineskip
- \vbox{\line{\ewbot\hfill\ewbot}}
- }}
+% does insertions, but you have to call it yourself.
+\def\onepageout#1{%
+ \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi
+ %
+ \ifodd\pageno \advance\hoffset by \bindingoffset
+ \else \advance\hoffset by -\bindingoffset\fi
+ %
+ % Do this outside of the \shipout so @code etc. will be expanded in
+ % the headline as they should be, not taken literally (outputting ''code).
+ \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}%
+ \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}%
+ %
+ {%
+ % Have to do this stuff outside the \shipout because we want it to
+ % take effect in \write's, yet the group defined by the \vbox ends
+ % before the \shipout runs.
+ %
+ \escapechar = `\\ % use backslash in output files.
+ \indexdummies % don't expand commands in the output.
+ \normalturnoffactive % \ in index entries must not stay \, e.g., if
+ % the page break happens to be in the middle of an example.
+ \shipout\vbox{%
+ \ifcropmarks \vbox to \outervsize\bgroup
+ \hsize = \outerhsize
+ \line{\ewtop\hfil\ewtop}%
+ \nointerlineskip
+ \line{%
+ \vbox{\moveleft\cornerthick\nstop}%
+ \hfill
+ \vbox{\moveright\cornerthick\nstop}%
+ }%
+ \vskip\topandbottommargin
+ \line\bgroup
+ \hfil % center the page within the outer (page) hsize.
+ \ifodd\pageno\hskip\bindingoffset\fi
+ \vbox\bgroup
+ \fi
+ %
+ \unvbox\headlinebox
+ \pagebody{#1}%
+ \ifdim\ht\footlinebox > 0pt
+ % Only leave this space if the footline is nonempty.
+ % (We lessened \vsize for it in \oddfootingxxx.)
+ % The \baselineskip=24pt in plain's \makefootline has no effect.
+ \vskip 2\baselineskip
+ \unvbox\footlinebox
+ \fi
+ %
+ \ifcropmarks
+ \egroup % end of \vbox\bgroup
+ \hfil\egroup % end of (centering) \line\bgroup
+ \vskip\topandbottommargin plus1fill minus1fill
+ \boxmaxdepth = \cornerthick
+ \line{%
+ \vbox{\moveleft\cornerthick\nsbot}%
+ \hfill
+ \vbox{\moveright\cornerthick\nsbot}%
+ }%
+ \nointerlineskip
+ \line{\ewbot\hfil\ewbot}%
+ \egroup % \vbox from first cropmarks clause
+ \fi
+ }% end of \shipout\vbox
+ }% end of group with \turnoffactive
\advancepageno
- \ifnum\outputpenalty>-20000 \else\dosupereject\fi}
-%
-% Do @cropmarks to get crop marks
-\def\cropmarks{\let\onepageout=\croppageout }
+ \ifnum\outputpenalty>-20000 \else\dosupereject\fi
+}
\newinsert\margin \dimen\margin=\maxdimen
@@ -197,7 +227,6 @@
\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
}
-%
% Here are the rules for the cropmarks. Note that they are
% offset so that the space between them is truly \outerhsize or \outervsize
% (P. A. MacKay, 12 November, 1986)
@@ -365,11 +394,43 @@
%\def\'{{'}}
% Used to generate quoted braces.
-
\def\mylbrace {{\tt \char '173}}
\def\myrbrace {{\tt \char '175}}
\let\{=\mylbrace
\let\}=\myrbrace
+\begingroup
+ % Definitions to produce actual \{ & \} command in an index.
+ \catcode`\{ = 12 \catcode`\} = 12
+ \catcode`\[ = 1 \catcode`\] = 2
+ \catcode`\@ = 0 \catcode`\\ = 12
+ @gdef@lbracecmd[\{]%
+ @gdef@rbracecmd[\}]%
+@endgroup
+
+% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
+% Others are defined by plain TeX: @` @' @" @^ @~ @= @v @H.
+\let\, = \c
+\let\dotaccent = \.
+\def\ringaccent#1{{\accent23 #1}}
+\let\tieaccent = \t
+\let\ubaraccent = \b
+\let\udotaccent = \d
+
+% Other special characters: @questiondown @exclamdown
+% Plain TeX defines: @AA @AE @O @OE @L (and lowercase versions) @ss.
+\def\questiondown{?`}
+\def\exclamdown{!`}
+
+% Dotless i and dotless j, used for accents.
+\def\imacro{i}
+\def\jmacro{j}
+\def\dotless#1{%
+ \def\temp{#1}%
+ \ifx\temp\imacro \ptexi
+ \else\ifx\temp\jmacro \j
+ \else \errmessage{@dotless can be used only with i or j}%
+ \fi\fi
+}
% @: forces normal size whitespace following.
\def\:{\spacefactor=1000 }
@@ -380,14 +441,11 @@
% @. is an end-of-sentence period.
\def\.{.\spacefactor=3000 }
-% @enddots{} is an end-of-sentence ellipsis.
-\gdef\enddots{$\mathinner{\ldotp\ldotp\ldotp\ldotp}$\spacefactor=3000}
-
% @! is an end-of-sentence bang.
-\gdef\!{!\spacefactor=3000 }
+\def\!{!\spacefactor=3000 }
% @? is an end-of-sentence query.
-\gdef\?{?\spacefactor=3000 }
+\def\?{?\spacefactor=3000 }
% @w prevents a word break. Without the \leavevmode, @w at the
% beginning of a paragraph, when TeX is still in vertical mode, would
@@ -512,9 +570,27 @@ where each line of input produces a line of output.}
\let\br = \par
-% @dots{} output some dots
+% @dots{} output an ellipsis using the current font.
+% We do .5em per period so that it has the same spacing in a typewriter
+% font as three actual period characters.
+%
+\def\dots{\hbox to 1.5em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+}}
+
+% @enddots{} is an end-of-sentence ellipsis.
+%
+\def\enddots{%
+ \hbox to 2em{%
+ \hskip 0pt plus 0.25fil minus 0.25fil
+ .\hss.\hss.\hss.%
+ \hskip 0pt plus 0.5fil minus 0.5fil
+ }%
+ \spacefactor=3000
+}
-\def\dots{$\ldots$}
% @page forces the start of a new page
@@ -536,17 +612,34 @@ where each line of input produces a line of output.}
\def\nofillexdentyyy #1{{\advance \leftskip by -\exdentamount
\leftline{\hskip\leftskip{\rm#1}}}}
+% @inmargin{TEXT} puts TEXT in the margin next to the current paragraph.
+
+\def\inmargin#1{%
+\strut\vadjust{\nobreak\kern-\strutdepth
+ \vtop to \strutdepth{\baselineskip\strutdepth\vss
+ \llap{\rightskip=\inmarginspacing \vbox{\noindent #1}}\null}}}
+\newskip\inmarginspacing \inmarginspacing=1cm
+\def\strutdepth{\dp\strutbox}
+
%\hbox{{\rm#1}}\hfil\break}}
% @include file insert text of that file as input.
-
-\def\include{\parsearg\includezzz}
-%Use \input\thisfile to avoid blank after \input, which may be an active
-%char (in which case the blank would become the \input argument).
-%The grouping keeps the value of \thisfile correct even when @include
-%is nested.
-\def\includezzz #1{\begingroup
-\def\thisfile{#1}\input\thisfile
+% Allow normal characters that we make active in the argument (a file name).
+\def\include{\begingroup
+ \catcode`\\=12
+ \catcode`~=12
+ \catcode`^=12
+ \catcode`_=12
+ \catcode`|=12
+ \catcode`<=12
+ \catcode`>=12
+ \catcode`+=12
+ \parsearg\includezzz}
+% Restore active chars for included file.
+\def\includezzz#1{\endgroup\begingroup
+ % Read the included file in a group so nested @include's work.
+ \def\thisfile{#1}%
+ \input\thisfile
\endgroup}
\def\thisfile{}
@@ -561,7 +654,7 @@ where each line of input produces a line of output.}
% @sp n outputs n lines of vertical space
\def\sp{\parsearg\spxxx}
-\def\spxxx #1{\par \vskip #1\baselineskip}
+\def\spxxx #1{\vskip #1\baselineskip}
% @comment ...line which is ignored...
% @c is the same as @comment
@@ -574,6 +667,9 @@ where each line of input produces a line of output.}
\let\c=\comment
+% @paragraphindent is defined for the Info formatting commands only.
+\let\paragraphindent=\comment
+
% Prevent errors for section commands.
% Used in @ignore and in failing conditionals.
\def\ignoresections{%
@@ -608,6 +704,7 @@ where each line of input produces a line of output.}
% incorrectly.
%
\def\ignoremorecommands{%
+ \let\defcodeindex = \relax
\let\defcv = \relax
\let\deffn = \relax
\let\deffnx = \relax
@@ -631,6 +728,15 @@ where each line of input produces a line of output.}
\let\printindex = \relax
\let\pxref = \relax
\let\settitle = \relax
+ \let\setchapternewpage = \relax
+ \let\setchapterstyle = \relax
+ \let\everyheading = \relax
+ \let\evenheading = \relax
+ \let\oddheading = \relax
+ \let\everyfooting = \relax
+ \let\evenfooting = \relax
+ \let\oddfooting = \relax
+ \let\headings = \relax
\let\include = \relax
\let\lowersections = \relax
\let\down = \relax
@@ -639,21 +745,31 @@ where each line of input produces a line of output.}
\let\set = \relax
\let\clear = \relax
\let\item = \relax
- \let\message = \relax
}
% Ignore @ignore ... @end ignore.
%
\def\ignore{\doignore{ignore}}
-% Also ignore @ifinfo, @ifhtml, @html, @menu, and @direntry text.
+% Ignore @ifinfo, @ifhtml, @ifnottex, @html, @menu, and @direntry text.
%
\def\ifinfo{\doignore{ifinfo}}
\def\ifhtml{\doignore{ifhtml}}
+\def\ifnottex{\doignore{ifnottex}}
\def\html{\doignore{html}}
\def\menu{\doignore{menu}}
\def\direntry{\doignore{direntry}}
+% Also ignore @macro ... @end macro. The user must run texi2dvi,
+% which runs makeinfo to do macro expansion. Ignore @unmacro, too.
+\def\macro{\doignore{macro}}
+\let\unmacro = \comment
+
+
+% @dircategory CATEGORY -- specify a category of the dir file
+% which this file should belong to. Ignore this in TeX.
+\let\dircategory = \comment
+
% Ignore text until a line `@end #1'.
%
\def\doignore#1{\begingroup
@@ -666,6 +782,10 @@ where each line of input produces a line of output.}
% Make sure that spaces turn into tokens that match what \doignoretext wants.
\catcode32 = 10
%
+ % Ignore braces, too, so mismatched braces don't cause trouble.
+ \catcode`\{ = 9
+ \catcode`\} = 9
+ %
% And now expand that command.
\doignoretext
}
@@ -685,11 +805,12 @@ where each line of input produces a line of output.}
\immediate\write16{If you are running another version of TeX, relax.}
\immediate\write16{If you are running Unix TeX 3.0, kill this TeX process.}
\immediate\write16{ Then upgrade your TeX installation if you can.}
+ \immediate\write16{ (See ftp://ftp.gnu.ai.mit.edu/pub/gnu/TeX.README.)}
\immediate\write16{If you are stuck with version 3.0, run the}
\immediate\write16{ script ``tex3patch'' from the Texinfo distribution}
\immediate\write16{ to use a workaround.}
\immediate\write16{}
- \warnedobstrue
+ \global\warnedobstrue
\fi
}
@@ -756,7 +877,7 @@ where each line of input produces a line of output.}
\pretolerance = 10000
%
% Do not execute instructions in @tex
- \def\tex{\doignore{tex}}
+ \def\tex{\doignore{tex}}%
}
% @set VAR sets the variable VAR to an empty value.
@@ -765,15 +886,19 @@ where each line of input produces a line of output.}
% Since we want to separate VAR from REST-OF-LINE (which might be
% empty), we can't just use \parsearg; we have to insert a space of our
% own to delimit the rest of the line, and then take it out again if we
-% didn't need it.
+% didn't need it. Make sure the catcode of space is correct to avoid
+% losing inside @example, for instance.
%
-\def\set{\parsearg\setxxx}
+\def\set{\begingroup\catcode` =10
+ \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
+ \parsearg\setxxx}
\def\setxxx#1{\setyyy#1 \endsetyyy}
\def\setyyy#1 #2\endsetyyy{%
\def\temp{#2}%
\ifx\temp\empty \global\expandafter\let\csname SET#1\endcsname = \empty
\else \setzzz{#1}#2\endsetzzz % Remove the trailing space \setxxx inserted.
\fi
+ \endgroup
}
% Can't use \xdef to pre-expand #2 and save some time, since \temp or
% \next or other control sequences that we've defined might get us into
@@ -787,10 +912,16 @@ where each line of input produces a line of output.}
% @value{foo} gets the text saved in variable foo.
%
-\def\value#1{\expandafter
- \ifx\csname SET#1\endcsname\relax
- {\{No value for ``#1''\}}
- \else \csname SET#1\endcsname \fi}
+\def\value{\begingroup
+ \catcode`\-=12 \catcode`\_=12 % Allow - and _ in VAR.
+ \valuexxx}
+\def\valuexxx#1{%
+ \expandafter\ifx\csname SET#1\endcsname\relax
+ {\{No value for ``#1''\}}%
+ \else
+ \csname SET#1\endcsname
+ \fi
+\endgroup}
% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
% with @set.
@@ -822,11 +953,16 @@ where each line of input produces a line of output.}
\def\ifclearfail{\nestedignore{ifclear}}
\defineunmatchedend{ifclear}
-% @iftex always succeeds; we read the text following, through @end
-% iftex). But `@end iftex' should be valid only after an @iftex.
+% @iftex, @ifnothtml, @ifnotinfo always succeed; we read the text
+% following, through the first @end iftex (etc.). Make `@end iftex'
+% (etc.) valid only after an @iftex.
%
\def\iftex{\conditionalsucceed{iftex}}
+\def\ifnothtml{\conditionalsucceed{ifnothtml}}
+\def\ifnotinfo{\conditionalsucceed{ifnotinfo}}
\defineunmatchedend{iftex}
+\defineunmatchedend{ifnothtml}
+\defineunmatchedend{ifnotinfo}
% We can't just want to start a group at @iftex (for example) and end it
% at @end iftex, since then @set commands inside the conditional have no
@@ -890,6 +1026,7 @@ where each line of input produces a line of output.}
\expandafter\expandafter\expandafter\appendixsetref{\lastnode}\fi
\global\let\lastnode=\relax}
+% @refill is a no-op.
\let\refill=\relax
% @setfilename is done at the beginning of every texinfo file.
@@ -901,14 +1038,36 @@ where each line of input produces a line of output.}
\openindices
\fixbackslash % Turn off hack to swallow `\input texinfo'.
\global\let\setfilename=\comment % Ignore extra @setfilename cmds.
+ %
+ % If texinfo.cnf is present on the system, read it.
+ % Useful for site-wide @afourpaper, etc.
+ % Just to be on the safe side, close the input stream before the \input.
+ \openin 1 texinfo.cnf
+ \ifeof1 \let\temp=\relax \else \def\temp{\input texinfo.cnf }\fi
+ \closein1
+ \temp
+ %
\comment % Ignore the actual filename.
}
+% @bye.
\outer\def\bye{\pagealignmacro\tracingstats=1\ptexend}
-\def\inforef #1{\inforefzzz #1,,,,**}
-\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
- node \samp{\ignorespaces#1{}}}
+% \def\macro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\macroxxx}
+% \def\macroxxx#1#2 \end macro{%
+% \expandafter\gdef\macrotemp#1{#2}%
+% \endgroup}
+
+%\def\linemacro#1{\begingroup\ignoresections\catcode`\#=6\def\macrotemp{#1}\parsearg\linemacroxxx}
+%\def\linemacroxxx#1#2 \end linemacro{%
+%\let\parsearg=\relax
+%\edef\macrotempx{\csname M\butfirst\expandafter\string\macrotemp\endcsname}%
+%\expandafter\xdef\macrotemp{\parsearg\macrotempx}%
+%\expandafter\gdef\macrotempx#1{#2}%
+%\endgroup}
+
+%\def\butfirst#1{}
+
\message{fonts,}
@@ -920,12 +1079,17 @@ where each line of input produces a line of output.}
\def\sf{\fam=\sffam \tensf}
\let\li = \sf % Sometimes we call it \li, not \sf.
-%% Try out Computer Modern fonts at \magstephalf
-\let\mainmagstep=\magstephalf
+% We don't need math for this one.
+\def\ttsl{\tenttsl}
+
+% Use Computer Modern fonts at \magstephalf (11pt).
+\newcount\mainmagstep
+\mainmagstep=\magstephalf
% Set the font macro #1 to the font named #2, adding on the
% specified font prefix (normally `cm').
-\def\setfont#1#2{\font#1=\fontprefix#2}
+% #3 is the font's design size, #4 is a scale factor
+\def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4}
% Use cm as the default font prefix.
% To specify the font prefix, you must define \fontprefix
@@ -933,98 +1097,130 @@ where each line of input produces a line of output.}
\ifx\fontprefix\undefined
\def\fontprefix{cm}
\fi
+% Support font families that don't use the same naming scheme as CM.
+\def\rmshape{r}
+\def\rmbshape{bx} %where the normal face is bold
+\def\bfshape{b}
+\def\bxshape{bx}
+\def\ttshape{tt}
+\def\ttbshape{tt}
+\def\ttslshape{sltt}
+\def\itshape{ti}
+\def\itbshape{bxti}
+\def\slshape{sl}
+\def\slbshape{bxsl}
+\def\sfshape{ss}
+\def\sfbshape{ss}
+\def\scshape{csc}
+\def\scbshape{csc}
\ifx\bigger\relax
\let\mainmagstep=\magstep1
-\setfont\textrm{r12}
-\setfont\texttt{tt12}
+\setfont\textrm\rmshape{12}{1000}
+\setfont\texttt\ttshape{12}{1000}
\else
-\setfont\textrm{r10 scaled \mainmagstep}
-\setfont\texttt{tt10 scaled \mainmagstep}
+\setfont\textrm\rmshape{10}{\mainmagstep}
+\setfont\texttt\ttshape{10}{\mainmagstep}
\fi
% Instead of cmb10, you many want to use cmbx10.
% cmbx10 is a prettier font on its own, but cmb10
% looks better when embedded in a line with cmr10.
-\setfont\textbf{b10 scaled \mainmagstep}
-\setfont\textit{ti10 scaled \mainmagstep}
-\setfont\textsl{sl10 scaled \mainmagstep}
-\setfont\textsf{ss10 scaled \mainmagstep}
-\setfont\textsc{csc10 scaled \mainmagstep}
+\setfont\textbf\bfshape{10}{\mainmagstep}
+\setfont\textit\itshape{10}{\mainmagstep}
+\setfont\textsl\slshape{10}{\mainmagstep}
+\setfont\textsf\sfshape{10}{\mainmagstep}
+\setfont\textsc\scshape{10}{\mainmagstep}
+\setfont\textttsl\ttslshape{10}{\mainmagstep}
\font\texti=cmmi10 scaled \mainmagstep
\font\textsy=cmsy10 scaled \mainmagstep
% A few fonts for @defun, etc.
-\setfont\defbf{bx10 scaled \magstep1} %was 1314
-\setfont\deftt{tt10 scaled \magstep1}
+\setfont\defbf\bxshape{10}{\magstep1} %was 1314
+\setfont\deftt\ttshape{10}{\magstep1}
\def\df{\let\tentt=\deftt \let\tenbf = \defbf \bf}
-% Fonts for indices and small examples.
+% Fonts for indices and small examples (9pt).
% We actually use the slanted font rather than the italic,
% because texinfo normally uses the slanted fonts for that.
% Do not make many font distinctions in general in the index, since they
% aren't very useful.
-\setfont\ninett{tt9}
-\setfont\indrm{r9}
-\setfont\indit{sl9}
+\setfont\ninett\ttshape{9}{1000}
+\setfont\indrm\rmshape{9}{1000}
+\setfont\indit\slshape{9}{1000}
\let\indsl=\indit
\let\indtt=\ninett
+\let\indttsl=\ninett
\let\indsf=\indrm
\let\indbf=\indrm
-\setfont\indsc{csc10 at 9pt}
+\setfont\indsc\scshape{10}{900}
\font\indi=cmmi9
\font\indsy=cmsy9
-% Fonts for headings
-\setfont\chaprm{bx12 scaled \magstep2}
-\setfont\chapit{ti12 scaled \magstep2}
-\setfont\chapsl{sl12 scaled \magstep2}
-\setfont\chaptt{tt12 scaled \magstep2}
-\setfont\chapsf{ss12 scaled \magstep2}
+% Fonts for title page:
+\setfont\titlerm\rmbshape{12}{\magstep3}
+\setfont\titleit\itbshape{10}{\magstep4}
+\setfont\titlesl\slbshape{10}{\magstep4}
+\setfont\titlett\ttbshape{12}{\magstep3}
+\setfont\titlettsl\ttslshape{10}{\magstep4}
+\setfont\titlesf\sfbshape{17}{\magstep1}
+\let\titlebf=\titlerm
+\setfont\titlesc\scbshape{10}{\magstep4}
+\font\titlei=cmmi12 scaled \magstep3
+\font\titlesy=cmsy10 scaled \magstep4
+\def\authorrm{\secrm}
+
+% Chapter (and unnumbered) fonts (17.28pt).
+\setfont\chaprm\rmbshape{12}{\magstep2}
+\setfont\chapit\itbshape{10}{\magstep3}
+\setfont\chapsl\slbshape{10}{\magstep3}
+\setfont\chaptt\ttbshape{12}{\magstep2}
+\setfont\chapttsl\ttslshape{10}{\magstep3}
+\setfont\chapsf\sfbshape{17}{1000}
\let\chapbf=\chaprm
-\setfont\chapsc{csc10 scaled\magstep3}
+\setfont\chapsc\scbshape{10}{\magstep3}
\font\chapi=cmmi12 scaled \magstep2
\font\chapsy=cmsy10 scaled \magstep3
-\setfont\secrm{bx12 scaled \magstep1}
-\setfont\secit{ti12 scaled \magstep1}
-\setfont\secsl{sl12 scaled \magstep1}
-\setfont\sectt{tt12 scaled \magstep1}
-\setfont\secsf{ss12 scaled \magstep1}
-\setfont\secbf{bx12 scaled \magstep1}
-\setfont\secsc{csc10 scaled\magstep2}
+% Section fonts (14.4pt).
+\setfont\secrm\rmbshape{12}{\magstep1}
+\setfont\secit\itbshape{10}{\magstep2}
+\setfont\secsl\slbshape{10}{\magstep2}
+\setfont\sectt\ttbshape{12}{\magstep1}
+\setfont\secttsl\ttslshape{10}{\magstep2}
+\setfont\secsf\sfbshape{12}{\magstep1}
+\let\secbf\secrm
+\setfont\secsc\scbshape{10}{\magstep2}
\font\seci=cmmi12 scaled \magstep1
\font\secsy=cmsy10 scaled \magstep2
-% \setfont\ssecrm{bx10 scaled \magstep1} % This size an font looked bad.
-% \setfont\ssecit{cmti10 scaled \magstep1} % The letters were too crowded.
-% \setfont\ssecsl{sl10 scaled \magstep1}
-% \setfont\ssectt{tt10 scaled \magstep1}
-% \setfont\ssecsf{ss10 scaled \magstep1}
+% \setfont\ssecrm\bxshape{10}{\magstep1} % This size an font looked bad.
+% \setfont\ssecit\itshape{10}{\magstep1} % The letters were too crowded.
+% \setfont\ssecsl\slshape{10}{\magstep1}
+% \setfont\ssectt\ttshape{10}{\magstep1}
+% \setfont\ssecsf\sfshape{10}{\magstep1}
-%\setfont\ssecrm{b10 scaled 1315} % Note the use of cmb rather than cmbx.
-%\setfont\ssecit{ti10 scaled 1315} % Also, the size is a little larger than
-%\setfont\ssecsl{sl10 scaled 1315} % being scaled magstep1.
-%\setfont\ssectt{tt10 scaled 1315}
-%\setfont\ssecsf{ss10 scaled 1315}
+%\setfont\ssecrm\bfshape{10}{1315} % Note the use of cmb rather than cmbx.
+%\setfont\ssecit\itshape{10}{1315} % Also, the size is a little larger than
+%\setfont\ssecsl\slshape{10}{1315} % being scaled magstep1.
+%\setfont\ssectt\ttshape{10}{1315}
+%\setfont\ssecsf\sfshape{10}{1315}
%\let\ssecbf=\ssecrm
-\setfont\ssecrm{bx12 scaled \magstephalf}
-\setfont\ssecit{ti12 scaled \magstephalf}
-\setfont\ssecsl{sl12 scaled \magstephalf}
-\setfont\ssectt{tt12 scaled \magstephalf}
-\setfont\ssecsf{ss12 scaled \magstephalf}
-\setfont\ssecbf{bx12 scaled \magstephalf}
-\setfont\ssecsc{csc10 scaled \magstep1}
+% Subsection fonts (13.15pt).
+\setfont\ssecrm\rmbshape{12}{\magstephalf}
+\setfont\ssecit\itbshape{10}{1315}
+\setfont\ssecsl\slbshape{10}{1315}
+\setfont\ssectt\ttbshape{12}{\magstephalf}
+\setfont\ssecttsl\ttslshape{10}{1315}
+\setfont\ssecsf\sfbshape{12}{\magstephalf}
+\let\ssecbf\ssecrm
+\setfont\ssecsc\scbshape{10}{\magstep1}
\font\sseci=cmmi12 scaled \magstephalf
-\font\ssecsy=cmsy10 scaled \magstep1
+\font\ssecsy=cmsy10 scaled 1315
% The smallcaps and symbol fonts should actually be scaled \magstep1.5,
% but that is not a standard magnification.
-% Fonts for title page:
-\setfont\titlerm{bx12 scaled \magstep3}
-\let\authorrm = \secrm
-
% In order for the font changes to affect most math symbols and letters,
% we have to define the \textfont of the standard families. Since
% texinfo doesn't allow for producing subscripts and superscripts, we
@@ -1041,34 +1237,42 @@ where each line of input produces a line of output.}
% The font-changing commands redefine the meanings of \tenSTYLE, instead
% of just \STYLE. We do this so that font changes will continue to work
% in math mode, where it is the current \fam that is relevant in most
-% cases, not the current. Plain TeX does, for example,
-% \def\bf{\fam=\bffam \tenbf} By redefining \tenbf, we obviate the need
-% to redefine \bf itself.
+% cases, not the current font. Plain TeX does \def\bf{\fam=\bffam
+% \tenbf}, for example. By redefining \tenbf, we obviate the need to
+% redefine \bf itself.
\def\textfonts{%
\let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl
\let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc
- \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy
+ \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl
\resetmathfonts}
+\def\titlefonts{%
+ \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl
+ \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc
+ \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy
+ \let\tenttsl=\titlettsl
+ \resetmathfonts \setleading{25pt}}
+\def\titlefont#1{{\titlefonts\rm #1}}
\def\chapfonts{%
\let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl
\let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc
- \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy
- \resetmathfonts}
+ \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl
+ \resetmathfonts \setleading{19pt}}
\def\secfonts{%
\let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl
\let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc
- \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy
- \resetmathfonts}
+ \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl
+ \resetmathfonts \setleading{16pt}}
\def\subsecfonts{%
\let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl
\let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc
- \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy
- \resetmathfonts}
+ \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl
+ \resetmathfonts \setleading{15pt}}
+\let\subsubsecfonts = \subsecfonts % Maybe make sssec fonts scaled magstephalf?
\def\indexfonts{%
\let\tenrm=\indrm \let\tenit=\indit \let\tensl=\indsl
\let\tenbf=\indbf \let\tentt=\indtt \let\smallcaps=\indsc
- \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy
- \resetmathfonts}
+ \let\tensf=\indsf \let\teni=\indi \let\tensy=\indsy \let\tenttsl=\indttsl
+ \resetmathfonts \setleading{12pt}}
% Set up the default fonts, so we can use them for creating boxes.
%
@@ -1078,9 +1282,9 @@ where each line of input produces a line of output.}
\newcount\fontdepth \fontdepth=0
% Fonts for short table of contents.
-\setfont\shortcontrm{r12}
-\setfont\shortcontbf{bx12}
-\setfont\shortcontsl{sl12}
+\setfont\shortcontrm\rmshape{12}{1000}
+\setfont\shortcontbf\bxshape{12}{1000}
+\setfont\shortcontsl\slshape{12}{1000}
%% Add scribe-like font environments, plus @l for inline lisp (usually sans
%% serif) and @ii for TeX italic
@@ -1112,7 +1316,16 @@ where each line of input produces a line of output.}
}
\let\ttfont=\t
\def\samp #1{`\tclose{#1}'\null}
-\def\key #1{{\tt \nohyphenation \uppercase{#1}}\null}
+\setfont\smallrm\rmshape{8}{1000}
+\font\smallsy=cmsy9
+\def\key#1{{\smallrm\textfont2=\smallsy \leavevmode\hbox{%
+ \raise0.4pt\hbox{$\langle$}\kern-.08em\vtop{%
+ \vbox{\hrule\kern-0.4pt
+ \hbox{\raise0.4pt\hbox{\vphantom{$\langle$}}#1}}%
+ \kern-0.4pt\hrule}%
+ \kern-.06em\raise0.4pt\hbox{$\rangle$}}}}
+% The old definition, with no lozenge:
+%\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null}
\def\ctrl #1{{\tt \rawbackslash \hat}#1}
\let\file=\samp
@@ -1141,29 +1354,34 @@ where each line of input produces a line of output.}
}
% We *must* turn on hyphenation at `-' and `_' in \code.
-% Otherwise, it is too hard to avoid overful hboxes
+% Otherwise, it is too hard to avoid overfull hboxes
% in the Emacs manual, the Library manual, etc.
% Unfortunately, TeX uses one parameter (\hyphenchar) to control
% both hyphenation at - and hyphenation within words.
% We must therefore turn them both off (\tclose does that)
-% and arrange explicitly to hyphenate an a dash.
+% and arrange explicitly to hyphenate at a dash.
% -- rms.
{
\catcode`\-=\active
\catcode`\_=\active
+\catcode`\|=\active
\global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex}
% The following is used by \doprintindex to insure that long function names
% wrap around. It is necessary for - and _ to be active before the index is
% read from the file, as \entry parses the arguments long before \code is
% ever called. -- mycroft
-\global\def\indexbreaks{\catcode`\-=\active \let-\realdash \catcode`\_=\active \let_\realunder}
+% _ is always active; and it shouldn't be \let = to an _ that is a
+% subscript character anyway. Then, @cindex @samp{_} (for example)
+% fails. --karl
+\global\def\indexbreaks{%
+ \catcode`\-=\active \let-\realdash
+}
}
\def\realdash{-}
-\def\realunder{_}
\def\codedash{-\discretionary{}{}{}}
-\def\codeunder{\normalunderscore\discretionary{}{}{}}
+\def\codeunder{\ifusingtt{\normalunderscore\discretionary{}{}{}}{\_}}
\def\codex #1{\tclose{#1}\endgroup}
%\let\exp=\tclose %Was temporary
@@ -1171,11 +1389,62 @@ where each line of input produces a line of output.}
% @kbd is like @code, except that if the argument is just one @key command,
% then @kbd has no effect.
+% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
+% `example' (@kbd uses ttsl only inside of @example and friends),
+% or `code' (@kbd uses normal tty font always).
+\def\kbdinputstyle{\parsearg\kbdinputstylexxx}
+\def\kbdinputstylexxx#1{%
+ \def\arg{#1}%
+ \ifx\arg\worddistinct
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
+ \else\ifx\arg\wordexample
+ \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
+ \else\ifx\arg\wordcode
+ \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
+ \fi\fi\fi
+}
+\def\worddistinct{distinct}
+\def\wordexample{example}
+\def\wordcode{code}
+
+% Default is kbdinputdistinct. (Too much of a hassle to call the macro,
+% the catcodes are wrong for parsearg to work.)
+\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}
+
\def\xkey{\key}
\def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}%
\ifx\one\xkey\ifx\threex\three \key{#2}%
-\else\tclose{\look}\fi
-\else\tclose{\look}\fi}
+\else{\tclose{\kbdfont\look}}\fi
+\else{\tclose{\kbdfont\look}}\fi}
+
+% @url. Quotes do not seem necessary, so use \code.
+\let\url=\code
+
+% @uref (abbreviation for `urlref') takes an optional second argument
+% specifying the text to display. First (mandatory) arg is the url.
+% Perhaps eventually put in a hypertex \special here.
+%
+\def\uref#1{\urefxxx #1,,\finish}
+\def\urefxxx#1,#2,#3\finish{%
+ \setbox0 = \hbox{\ignorespaces #2}%
+ \ifdim\wd0 > 0pt
+ \unhbox0\ (\code{#1})%
+ \else
+ \code{#1}%
+ \fi
+}
+
+% rms does not like the angle brackets --karl, 17may97.
+% So now @email is just like @uref.
+%\def\email#1{$\langle${\tt #1}$\rangle$}
+\let\email=\uref
+
+% Check if we are currently using a typewriter font. Since all the
+% Computer Modern typewriter fonts have zero interword stretch (and
+% shrink), and it is reasonable to expect all typewriter fonts to have
+% this property, we can check that font parameter.
+%
+\def\ifmonospace{\ifdim\fontdimen3\font=0pt }
% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
% argument is to make the input look right: @dmn{pt} instead of
@@ -1185,12 +1454,19 @@ where each line of input produces a line of output.}
\def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par}
-\def\l#1{{\li #1}\null} %
+% @l was never documented to mean ``switch to the Lisp font'',
+% and it is not used as such in any manual I can find. We need it for
+% Polish suppressed-l. --karl, 22sep96.
+%\def\l#1{{\li #1}\null}
-\def\r#1{{\rm #1}} % roman font
+\def\r#1{{\rm #1}} % roman font
% Use of \lowercase was suggested.
-\def\sc#1{{\smallcaps#1}} % smallcaps font
-\def\ii#1{{\it #1}} % italic font
+\def\sc#1{{\smallcaps#1}} % smallcaps font
+\def\ii#1{{\it #1}} % italic font
+
+% @pounds{} is a sterling sign.
+\def\pounds{{\it\$}}
+
\message{page headings,}
@@ -1198,14 +1474,12 @@ where each line of input produces a line of output.}
\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
% First the title page. Must do @settitle before @titlepage.
-\def\titlefont#1{{\titlerm #1}}
-
\newif\ifseenauthor
\newif\iffinishedtitlepage
\def\shorttitlepage{\parsearg\shorttitlepagezzz}
\def\shorttitlepagezzz #1{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}%
- \endgroup\page\hbox{}\page}
+ \endgroup\page\hbox{}\page}
\def\titlepage{\begingroup \parindent=0pt \textfonts
\let\subtitlerm=\tenrm
@@ -1221,10 +1495,10 @@ where each line of input produces a line of output.}
%
% Now you can print the title using @title.
\def\title{\parsearg\titlezzz}%
- \def\titlezzz##1{\leftline{\titlefont{##1}}
- % print a rule at the page bottom also.
- \finishedtitlepagefalse
- \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
+ \def\titlezzz##1{\leftline{\titlefonts\rm ##1}
+ % print a rule at the page bottom also.
+ \finishedtitlepagefalse
+ \vskip4pt \hrule height 4pt width \hsize \vskip4pt}%
% No rule at page bottom unless we print one at the top with @title.
\finishedtitlepagetrue
%
@@ -1242,7 +1516,7 @@ where each line of input produces a line of output.}
\let\oldpage = \page
\def\page{%
\iffinishedtitlepage\else
- \finishtitlepage
+ \finishtitlepage
\fi
\oldpage
\let\page = \oldpage
@@ -1310,10 +1584,7 @@ where each line of input produces a line of output.}
\gdef\oddheadingyyy #1@|#2@|#3@|#4\finish{%
\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
-\gdef\everyheadingxxx #1{\everyheadingyyy #1@|@|@|@|\finish}
-\gdef\everyheadingyyy #1@|#2@|#3@|#4\finish{%
-\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
-\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+\gdef\everyheadingxxx#1{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
\gdef\evenfootingxxx #1{\evenfootingyyy #1@|@|@|@|\finish}
\gdef\evenfootingyyy #1@|#2@|#3@|#4\finish{%
@@ -1321,23 +1592,27 @@ where each line of input produces a line of output.}
\gdef\oddfootingxxx #1{\oddfootingyyy #1@|@|@|@|\finish}
\gdef\oddfootingyyy #1@|#2@|#3@|#4\finish{%
-\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+ \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
+ %
+ % Leave some space for the footline. Hopefully ok to assume
+ % @evenfooting will not be used by itself.
+ \global\advance\pageheight by -\baselineskip
+ \global\advance\vsize by -\baselineskip
+}
-\gdef\everyfootingxxx #1{\everyfootingyyy #1@|@|@|@|\finish}
-\gdef\everyfootingyyy #1@|#2@|#3@|#4\finish{%
-\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
-\global\oddfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
+\gdef\everyfootingxxx#1{\oddfootingxxx{#1}\evenfootingxxx{#1}}
%
}% unbind the catcode of @.
-% @headings double turns headings on for double-sided printing.
-% @headings single turns headings on for single-sided printing.
-% @headings off turns them off.
-% @headings on same as @headings double, retained for compatibility.
-% @headings after turns on double-sided headings after this page.
-% @headings doubleafter turns on double-sided headings after this page.
+% @headings double turns headings on for double-sided printing.
+% @headings single turns headings on for single-sided printing.
+% @headings off turns them off.
+% @headings on same as @headings double, retained for compatibility.
+% @headings after turns on double-sided headings after this page.
+% @headings doubleafter turns on double-sided headings after this page.
% @headings singleafter turns on single-sided headings after this page.
-% By default, they are off.
+% By default, they are off at the start of a document,
+% and turned `on' after @end titlepage.
\def\headings #1 {\csname HEADINGS#1\endcsname}
@@ -1351,22 +1626,24 @@ where each line of input produces a line of output.}
% title on inside top of left hand pages, and page numbers on outside top
% edge of all pages.
\def\HEADINGSdouble{
-%\pagealignmacro
\global\pageno=1
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\folio\hfil\thistitle}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
}
+\let\contentsalignmacro = \chappager
+
% For single-sided printing, chapter title goes across top left of page,
% page number on top right.
\def\HEADINGSsingle{
-%\pagealignmacro
\global\pageno=1
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
}
\def\HEADINGSon{\HEADINGSdouble}
@@ -1377,6 +1654,7 @@ where each line of input produces a line of output.}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\folio\hfil\thistitle}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chapoddpage
}
\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex}
@@ -1385,6 +1663,7 @@ where each line of input produces a line of output.}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
+\global\let\contentsalignmacro = \chappager
}
% Subroutines used in generating headings
@@ -1408,6 +1687,7 @@ July\or August\or September\or October\or November\or December\fi
\def\settitle{\parsearg\settitlezzz}
\def\settitlezzz #1{\gdef\thistitle{#1}}
+
\message{tables,}
% @tabs -- simple alignment
@@ -1440,7 +1720,7 @@ July\or August\or September\or October\or November\or December\fi
\newif\ifitemxneedsnegativevskip
-\def\itemxpar{\par\ifitemxneedsnegativevskip\vskip-\parskip\nobreak\fi}
+\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
\def\internalBitem{\smallbreak \parsearg\itemzzz}
\def\internalBitemx{\itemxpar \parsearg\itemzzz}
@@ -1704,17 +1984,17 @@ July\or August\or September\or October\or November\or December\fi
\def\itemizeitem{%
\advance\itemno by 1
{\let\par=\endgraf \smallbreak}%
-\ifhmode \errmessage{\in hmode at itemizeitem}\fi
+\ifhmode \errmessage{In hmode at itemizeitem}\fi
{\parskip=0in \hskip 0pt
\hbox to 0pt{\hss \itemcontents\hskip \itemmargin}%
\vadjust{\penalty 1200}}%
\flushcr}
% @multitable macros
-% Amy Hendrickson, 8/18/94
+% Amy Hendrickson, 8/18/94, 3/6/96
%
-% @multitable ... @endmultitable will make as many columns as desired.
-% Contents of each column will wrap at width given in preamble. Width
+% @multitable ... @end multitable will make as many columns as desired.
+% Contents of each column will wrap at width given in preamble. Width
% can be specified either with sample text given in a template line,
% or in percent of \hsize, the current width of text on page.
@@ -1722,121 +2002,146 @@ July\or August\or September\or October\or November\or December\fi
% To make preamble:
%
-% Either define widths of columns in terms of percent of \hsize:
-% @multitable @percentofhsize .2 .3 .5
+% Either define widths of columns in terms of percent of \hsize:
+% @multitable @columnfractions .25 .3 .45
% @item ...
%
-% Numbers following @percentofhsize are the percent of the total
+% Numbers following @columnfractions are the percent of the total
% current hsize to be used for each column. You may use as many
% columns as desired.
+
% Or use a template:
% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
% @item ...
% using the widest term desired in each column.
+%
+% For those who want to use more than one line's worth of words in
+% the preamble, break the line within one argument and it
+% will parse correctly, i.e.,
+%
+% @multitable {Column 1 template} {Column 2 template} {Column 3
+% template}
+% Not:
+% @multitable {Column 1 template} {Column 2 template}
+% {Column 3 template}
-
-% Each new table line starts with @item, each subsequent new column
+% Each new table line starts with @item, each subsequent new column
% starts with @tab. Empty columns may be produced by supplying @tab's
% with nothing between them for as many times as empty columns are needed,
% ie, @tab@tab@tab will produce two empty columns.
-% @item, @tab, @multicolumn or @endmulticolumn do not need to be on their
+% @item, @tab, @multitable or @end multitable do not need to be on their
% own lines, but it will not hurt if they are.
% Sample multitable:
% @multitable {Column 1 template} {Column 2 template} {Column 3 template}
% @item first col stuff @tab second col stuff @tab third col
-% @item
-% first col stuff
-% @tab
-% second col stuff
-% @tab
-% third col
-% @item first col stuff @tab second col stuff
+% @item
+% first col stuff
+% @tab
+% second col stuff
+% @tab
+% third col
+% @item first col stuff @tab second col stuff
% @tab Many paragraphs of text may be used in any column.
-%
+%
% They will wrap at the width determined by the template.
% @item@tab@tab This will be in third column.
-% @endmultitable
+% @end multitable
% Default dimensions may be reset by user.
-% @intableparskip will set vertical space between paragraphs in table.
-% @intableparindent will set paragraph indent in table.
-% @spacebetweencols will set horizontal space to be left between columns.
-% @spacebetweenlines will set vertical space to be left between lines.
+% @multitableparskip is vertical space between paragraphs in table.
+% @multitableparindent is paragraph indent in table.
+% @multitablecolmargin is horizontal space to be left between columns.
+% @multitablelinespace is space to leave between table items, baseline
+% to baseline.
+% 0pt means it depends on current normal line spacing.
%%%%
-% Dimensions
+% Dimensions
-\newdimen\intableparskip
-\newdimen\intableparindent
-\newdimen\spacebetweencols
-\newdimen\spacebetweenlines
-\intableparskip=0pt
-\intableparindent=6pt
-\spacebetweencols=12pt
-\spacebetweenlines=12pt
+\newskip\multitableparskip
+\newskip\multitableparindent
+\newdimen\multitablecolspace
+\newskip\multitablelinespace
+\multitableparskip=0pt
+\multitableparindent=6pt
+\multitablecolspace=12pt
+\multitablelinespace=0pt
%%%%
% Macros used to set up halign preamble:
\let\endsetuptable\relax
\def\xendsetuptable{\endsetuptable}
-\let\percentofhsize\relax
-\def\xpercentofhsize{\percentofhsize}
+\let\columnfractions\relax
+\def\xcolumnfractions{\columnfractions}
\newif\ifsetpercent
+%% 2/1/96, to allow fractions to be given with more than one digit.
+\def\pickupwholefraction#1 {\global\advance\colcount by1 %
+\expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}%
+\setuptable}
+
\newcount\colcount
\def\setuptable#1{\def\firstarg{#1}%
\ifx\firstarg\xendsetuptable\let\go\relax%
\else
- \ifx\firstarg\xpercentofhsize\global\setpercenttrue%
+ \ifx\firstarg\xcolumnfractions\global\setpercenttrue%
\else
\ifsetpercent
- \if#1.\else%
- \global\advance\colcount by1 %
- \expandafter\xdef\csname col\the\colcount\endcsname{.#1\hsize}%
- \fi
+ \let\go\pickupwholefraction % In this case arg of setuptable
+ % is the decimal point before the
+ % number given in percent of hsize.
+ % We don't need this so we don't use it.
\else
\global\advance\colcount by1
- \setbox0=\hbox{#1}%
+ \setbox0=\hbox{#1 }% Add a normal word space as a separator;
+ % typically that is always in the input, anyway.
\expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
\fi%
\fi%
- \let\go\setuptable%
+\ifx\go\pickupwholefraction\else\let\go\setuptable\fi%
\fi\go}
+
%%%%
% multitable syntax
-\def\tab{&}
+\def\tab{&\hskip1sp\relax} % 2/2/96
+ % tiny skip here makes sure this column space is
+ % maintained, even if it is never used.
+
%%%%
-% @multitable ... @endmultitable definitions:
+% @multitable ... @end multitable definitions:
-\def\multitable#1\item{\bgroup
+\def\multitable{\parsearg\dotable}
+
+\def\dotable#1{\bgroup
\let\item\cr
\tolerance=9500
\hbadness=9500
-\parskip=\intableparskip
-\parindent=\intableparindent
+\setmultitablespacing
+\parskip=\multitableparskip
+\parindent=\multitableparindent
\overfullrule=0pt
\global\colcount=0\relax%
\def\Emultitable{\global\setpercentfalse\global\everycr{}\cr\egroup\egroup}%
% To parse everything between @multitable and @item :
-\def\one{#1}\expandafter\setuptable\one\endsetuptable
+\setuptable#1 \endsetuptable
% Need to reset this to 0 after \setuptable.
-\global\colcount=0\relax%
+\global\colcount=0\relax%
%
% This preamble sets up a generic column definition, which will
% be used as many times as user calls for columns.
- % \vtop will set a single line and will also let text wrap and
+ % \vtop will set a single line and will also let text wrap and
% continue for many paragraphs if desired.
\halign\bgroup&\global\advance\colcount by 1\relax%
-\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
+\multistrut\vtop{\hsize=\expandafter\csname col\the\colcount\endcsname
% In order to keep entries from bumping into each other
- % we will add a \leftskip of \spacebetweencols to all columns after
+ % we will add a \leftskip of \multitablecolspace to all columns after
% the first one.
- % If a template has been used, we will add \spacebetweencols
+ % If a template has been used, we will add \multitablecolspace
% to the width of each template entry.
% If user has set preamble in terms of percent of \hsize
% we will use that dimension as the width of the column, and
@@ -1848,20 +2153,58 @@ July\or August\or September\or October\or November\or December\fi
\ifsetpercent
\else
% If user has <not> set preamble in terms of percent of \hsize
- % we will advance \hsize by \spacebetweencols
- \advance\hsize by \spacebetweencols
+ % we will advance \hsize by \multitablecolspace
+ \advance\hsize by \multitablecolspace
\fi
- % In either case we will make \leftskip=\spacebetweencols:
-\leftskip=\spacebetweencols
+ % In either case we will make \leftskip=\multitablecolspace:
+\leftskip=\multitablecolspace
\fi
-\noindent##}\cr%
+ % Ignoring space at the beginning and end avoids an occasional spurious
+ % blank line, when TeX decides to break the line at the space before the
+ % box from the multistrut, so the strut ends up on a line by itself.
+ % For example:
+ % @multitable @columnfractions .11 .89
+ % @item @code{#}
+ % @tab Legal holiday which is valid in major parts of the whole country.
+ % Is automatically provided with highlighting sequences respectively marking
+ % characters.
+ \noindent\ignorespaces##\unskip\multistrut}\cr
% \everycr will reset column counter, \colcount, at the end of
- % each line. Every column entry will cause \colcount to advance by one.
+ % each line. Every column entry will cause \colcount to advance by one.
% The table preamble
% looks at the current \colcount to find the correct column width.
-\global\everycr{\noalign{\nointerlineskip\vskip\spacebetweenlines
-\filbreak%% keeps underfull box messages off when table breaks over pages.
-\global\colcount=0\relax}}}
+\global\everycr{\noalign{%
+% \filbreak%% keeps underfull box messages off when table breaks over pages.
+% Maybe so, but it also creates really weird page breaks when the table
+% breaks over pages Wouldn't \vfil be better? Wait until the problem
+% manifests itself, so it can be fixed for real --karl.
+\global\colcount=0\relax}}
+}
+
+\def\setmultitablespacing{% test to see if user has set \multitablelinespace.
+% If so, do nothing. If not, give it an appropriate dimension based on
+% current baselineskip.
+\ifdim\multitablelinespace=0pt
+%% strut to put in table in case some entry doesn't have descenders,
+%% to keep lines equally spaced
+\let\multistrut = \strut
+%% Test to see if parskip is larger than space between lines of
+%% table. If not, do nothing.
+%% If so, set to same dimension as multitablelinespace.
+\else
+\gdef\multistrut{\vrule height\multitablelinespace depth\dp0
+width0pt\relax} \fi
+\ifdim\multitableparskip>\multitablelinespace
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi%
+\ifdim\multitableparskip=0pt
+\global\multitableparskip=\multitablelinespace
+\global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller
+ %% than skip between lines in the table.
+\fi}
+
\message{indexing,}
% Index generation facilities
@@ -1875,14 +2218,14 @@ July\or August\or September\or October\or November\or December\fi
% It automatically defines \fooindex such that
% \fooindex ...rest of line... puts an entry in the index foo.
% It also defines \fooindfile to be the number of the output channel for
-% the file that accumulates this index. The file's extension is foo.
+% the file that accumulates this index. The file's extension is foo.
% The name of an index should be no more than 2 characters long
% for the sake of vms.
\def\newindex #1{
\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
-\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
-\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
\noexpand\doindex {#1}}
}
@@ -1894,8 +2237,8 @@ July\or August\or September\or October\or November\or December\fi
\def\newcodeindex #1{
\expandafter\newwrite \csname#1indfile\endcsname% Define number for output file
-\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
-\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\openout \csname#1indfile\endcsname \jobname.#1 % Open the file
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
\noexpand\docodeindex {#1}}
}
@@ -1906,7 +2249,7 @@ July\or August\or September\or October\or November\or December\fi
\def\synindex #1 #2 {%
\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
\expandafter\let\csname#1indfile\endcsname=\synindexfoo
-\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
\noexpand\doindex {#2}}%
}
@@ -1915,7 +2258,7 @@ July\or August\or September\or October\or November\or December\fi
\def\syncodeindex #1 #2 {%
\expandafter\let\expandafter\synindexfoo\expandafter=\csname#2indfile\endcsname
\expandafter\let\csname#1indfile\endcsname=\synindexfoo
-\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
+\expandafter\xdef\csname#1index\endcsname{% % Define \xxxindex
\noexpand\docodeindex {#2}}%
}
@@ -1963,27 +2306,41 @@ July\or August\or September\or October\or November\or December\fi
\def\L{\realbackslash L}%
\def\ss{\realbackslash ss}%
% Take care of texinfo commands likely to appear in an index entry.
+% (Must be a way to avoid doing expansion at all, and thus not have to
+% laboriously list every single command here.)
+\def\@{@}% will be @@ when we switch to @ as escape char.
+%\let\{ = \lbracecmd
+%\let\} = \rbracecmd
\def\_{{\realbackslash _}}%
\def\w{\realbackslash w }%
\def\bf{\realbackslash bf }%
-\def\rm{\realbackslash rm }%
+%\def\rm{\realbackslash rm }%
\def\sl{\realbackslash sl }%
\def\sf{\realbackslash sf}%
\def\tt{\realbackslash tt}%
\def\gtr{\realbackslash gtr}%
\def\less{\realbackslash less}%
\def\hat{\realbackslash hat}%
-\def\char{\realbackslash char}%
+%\def\char{\realbackslash char}%
\def\TeX{\realbackslash TeX}%
\def\dots{\realbackslash dots }%
-\def\copyright{\realbackslash copyright }%
+\def\result{\realbackslash result}%
+\def\equiv{\realbackslash equiv}%
+\def\expansion{\realbackslash expansion}%
+\def\print{\realbackslash print}%
+\def\error{\realbackslash error}%
+\def\point{\realbackslash point}%
+\def\copyright{\realbackslash copyright}%
\def\tclose##1{\realbackslash tclose {##1}}%
\def\code##1{\realbackslash code {##1}}%
+\def\dotless##1{\realbackslash dotless {##1}}%
\def\samp##1{\realbackslash samp {##1}}%
-\def\t##1{\realbackslash r {##1}}%
+\def\,##1{\realbackslash ,{##1}}%
+\def\t##1{\realbackslash t {##1}}%
\def\r##1{\realbackslash r {##1}}%
\def\i##1{\realbackslash i {##1}}%
\def\b##1{\realbackslash b {##1}}%
+\def\sc##1{\realbackslash sc {##1}}%
\def\cite##1{\realbackslash cite {##1}}%
\def\key##1{\realbackslash key {##1}}%
\def\file##1{\realbackslash file {##1}}%
@@ -1991,6 +2348,7 @@ July\or August\or September\or October\or November\or December\fi
\def\kbd##1{\realbackslash kbd {##1}}%
\def\dfn##1{\realbackslash dfn {##1}}%
\def\emph##1{\realbackslash emph {##1}}%
+\def\value##1{\realbackslash value {##1}}%
\unsepspaces
}
@@ -2008,6 +2366,7 @@ July\or August\or September\or October\or November\or December\fi
\def\indexnofonts{%
% Just ignore accents.
+\let\,=\indexdummyfont
\let\"=\indexdummyfont
\let\`=\indexdummyfont
\let\'=\indexdummyfont
@@ -2020,6 +2379,7 @@ July\or August\or September\or October\or November\or December\fi
\let\u=\indexdummyfont
\let\v=\indexdummyfont
\let\H=\indexdummyfont
+\let\dotless=\indexdummyfont
% Take care of the plain tex special European modified letters.
\def\oe{oe}%
\def\ae{ae}%
@@ -2053,6 +2413,7 @@ July\or August\or September\or October\or November\or December\fi
\let\var=\indexdummyfont
\let\TeX=\indexdummytex
\let\dots=\indexdummydots
+\def\@{@}%
}
% To define \realbackslash, we must make \ not be an escape.
@@ -2068,29 +2429,37 @@ July\or August\or September\or October\or November\or December\fi
% workhorse for all \fooindexes
% #1 is name of index, #2 is stuff to put there
\def\doind #1#2{%
-% Put the index entry in the margin if desired.
-\ifx\SETmarginindex\relax\else%
-\insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
-\fi%
-{\count10=\lastpenalty %
-{\indexdummies % Must do this here, since \bf, etc expand at this stage
-\escapechar=`\\%
-{\let\folio=0% Expand all macros now EXCEPT \folio
-\def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
-% so it will be output as is; and it will print as backslash in the indx.
-%
-% Now process the index-string once, with all font commands turned off,
-% to get the string to sort the index by.
-{\indexnofonts
-\xdef\temp1{#2}%
-}%
-% Now produce the complete index entry. We process the index-string again,
-% this time with font commands expanded, to get what to print in the index.
-\edef\temp{%
-\write \csname#1indfile\endcsname{%
-\realbackslash entry {\temp1}{\folio}{#2}}}%
-\temp }%
-}\penalty\count10}}
+ % Put the index entry in the margin if desired.
+ \ifx\SETmarginindex\relax\else
+ \insert\margin{\hbox{\vrule height8pt depth3pt width0pt #2}}%
+ \fi
+ {%
+ \count255=\lastpenalty
+ {%
+ \indexdummies % Must do this here, since \bf, etc expand at this stage
+ \escapechar=`\\
+ {%
+ \let\folio=0% We will expand all macros now EXCEPT \folio.
+ \def\rawbackslashxx{\indexbackslash}% \indexbackslash isn't defined now
+ % so it will be output as is; and it will print as backslash.
+ %
+ % First process the index-string with all font commands turned off
+ % to get the string to sort by.
+ {\indexnofonts \xdef\indexsorttmp{#2}}%
+ %
+ % Now produce the complete index entry, with both the sort key and the
+ % original text, including any font commands.
+ \toks0 = {#2}%
+ \edef\temp{%
+ \write\csname#1indfile\endcsname{%
+ \realbackslash entry{\indexsorttmp}{\folio}{\the\toks0}}%
+ }%
+ \temp
+ }%
+ }%
+ \penalty\count255
+ }%
+}
\def\dosubind #1#2#3{%
{\count10=\lastpenalty %
@@ -2144,34 +2513,16 @@ July\or August\or September\or October\or November\or December\fi
% Define the macros used in formatting output of the sorted index material.
-% This is what you call to cause a particular index to get printed.
-% Write
-% @unnumbered Function Index
-% @printindex fn
-
+% @printindex causes a particular index (the ??s file) to get printed.
+% It does not print any chapter heading (usually an @unnumbered).
+%
\def\printindex{\parsearg\doprintindex}
-
-\def\doprintindex#1{%
- \tex
- \dobreak \chapheadingskip {10000}
- \catcode`\%=\other\catcode`\&=\other\catcode`\#=\other
- \catcode`\$=\other
- \catcode`\~=\other
- \indexbreaks
+\def\doprintindex#1{\begingroup
+ \dobreak \chapheadingskip{10000}%
%
- % The following don't help, since the chars were translated
- % when the raw index was written, and their fonts were discarded
- % due to \indexnofonts.
- %\catcode`\"=\active
- %\catcode`\^=\active
- %\catcode`\_=\active
- %\catcode`\|=\active
- %\catcode`\<=\active
- %\catcode`\>=\active
- % %
- \def\indexbackslash{\rawbackslashxx}
- \indexfonts\rm \tolerance=9500 \advance\baselineskip -1pt
- \begindoublecolumns
+ \indexfonts \rm
+ \tolerance = 9500
+ \indexbreaks
%
% See if the index file exists and is nonempty.
\openin 1 \jobname.#1s
@@ -2181,7 +2532,7 @@ July\or August\or September\or October\or November\or December\fi
% index. The easiest way to prevent this problem is to make sure
% there is some text.
(Index is nonexistent)
- \else
+ \else
%
% If the index file exists but is empty, then \openin leaves \ifeof
% false. We have to make TeX try to read something from the file, so
@@ -2190,13 +2541,20 @@ July\or August\or September\or October\or November\or December\fi
\ifeof 1
(Index is empty)
\else
+ % Index files are almost Texinfo source, but we use \ as the escape
+ % character. It would be better to use @, but that's too big a change
+ % to make right now.
+ \def\indexbackslash{\rawbackslashxx}%
+ \catcode`\\ = 0
+ \catcode`\@ = 11
+ \escapechar = `\\
+ \begindoublecolumns
\input \jobname.#1s
+ \enddoublecolumns
\fi
\fi
\closein 1
- \enddoublecolumns
- \Etex
-}
+\endgroup}
% These macros are used by the sorted index file itself.
% Change them to control the appearance of the index.
@@ -2287,34 +2645,49 @@ July\or August\or September\or October\or November\or December\fi
\noindent\hskip\secondaryindent\hbox{#1}\indexdotfill #2\par
}}
-%% Define two-column mode, which is used in indexes.
-%% Adapted from the TeXbook, page 416.
-\catcode `\@=11
+% Define two-column mode, which we use to typeset indexes.
+% Adapted from the TeXbook, page 416, which is to say,
+% the manmac.tex format used to print the TeXbook itself.
+\catcode`\@=11
\newbox\partialpage
-
\newdimen\doublecolumnhsize
-\def\begindoublecolumns{\begingroup
+\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
% Grab any single-column material above us.
- \output = {\global\setbox\partialpage
- =\vbox{\unvbox255\kern -\topskip \kern \baselineskip}}%
+ \output = {\global\setbox\partialpage = \vbox{%
+ %
+ % Here is a possibility not foreseen in manmac: if we accumulate a
+ % whole lot of material, we might end up calling this \output
+ % routine twice in a row (see the doublecol-lose test, which is
+ % essentially a couple of indexes with @setchapternewpage off). In
+ % that case, we must prevent the second \partialpage from
+ % simply overwriting the first, causing us to lose the page.
+ % This will preserve it until a real output routine can ship it
+ % out. Generally, \partialpage will be empty when this runs and
+ % this will be a no-op.
+ \unvbox\partialpage
+ %
+ % Unvbox the main output page.
+ \unvbox255
+ \kern-\topskip \kern\baselineskip
+ }}%
\eject
%
- % Now switch to the double-column output routine.
- \output={\doublecolumnout}%
+ % Use the double-column output routine for subsequent pages.
+ \output = {\doublecolumnout}%
%
% Change the page size parameters. We could do this once outside this
% routine, in each of @smallbook, @afourpaper, and the default 8.5x11
% format, but then we repeat the same computation. Repeating a couple
% of assignments once per index is clearly meaningless for the
- % execution time, so we may as well do it once.
+ % execution time, so we may as well do it in one place.
%
% First we halve the line length, less a little for the gutter between
% the columns. We compute the gutter based on the line length, so it
% changes automatically with the paper format. The magic constant
- % below is chosen so that the gutter has the same value (well, +- <
- % 1pt) as it did when we hard-coded it.
+ % below is chosen so that the gutter has the same value (well, +-<1pt)
+ % as it did when we hard-coded it.
%
% We put the result in a separate register, \doublecolumhsize, so we
% can restore it in \pagesofar, after \hsize itself has (potentially)
@@ -2328,107 +2701,116 @@ July\or August\or September\or October\or November\or December\fi
% Double the \vsize as well. (We don't need a separate register here,
% since nobody clobbers \vsize.)
\vsize = 2\vsize
- \doublecolumnpagegoal
}
-
-\def\enddoublecolumns{\eject \endgroup \pagegoal=\vsize \unvbox\partialpage}
-
-\def\doublecolumnsplit{\splittopskip=\topskip \splitmaxdepth=\maxdepth
- \global\dimen@=\pageheight \global\advance\dimen@ by-\ht\partialpage
- \global\setbox1=\vsplit255 to\dimen@ \global\setbox0=\vbox{\unvbox1}
- \global\setbox3=\vsplit255 to\dimen@ \global\setbox2=\vbox{\unvbox3}
- \ifdim\ht0>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
- \ifdim\ht2>\dimen@ \setbox255=\vbox{\unvbox0\unvbox2} \global\setbox255=\copy5 \fi
+\def\doublecolumnout{%
+ \splittopskip=\topskip \splitmaxdepth=\maxdepth
+ % Get the available space for the double columns -- the normal
+ % (undoubled) page height minus any material left over from the
+ % previous page.
+ \dimen@=\pageheight \advance\dimen@ by-\ht\partialpage
+ % box0 will be the left-hand column, box2 the right.
+ \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@
+ \onepageout\pagesofar
+ \unvbox255
+ \penalty\outputpenalty
}
-\def\doublecolumnpagegoal{%
- \dimen@=\vsize \advance\dimen@ by-2\ht\partialpage \global\pagegoal=\dimen@
+\def\pagesofar{%
+ % Re-output the contents of the output page -- any previous material,
+ % followed by the two boxes we just split.
+ \unvbox\partialpage
+ \hsize = \doublecolumnhsize
+ \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}%
}
-\def\pagesofar{\unvbox\partialpage %
- \hsize=\doublecolumnhsize % have to restore this since output routine
- \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}}
-\def\doublecolumnout{%
- \setbox5=\copy255
- {\vbadness=10000 \doublecolumnsplit}
- \ifvbox255
- \setbox0=\vtop to\dimen@{\unvbox0}
- \setbox2=\vtop to\dimen@{\unvbox2}
- \onepageout\pagesofar \unvbox255 \penalty\outputpenalty
- \else
- \setbox0=\vbox{\unvbox5}
- \ifvbox0
- \dimen@=\ht0 \advance\dimen@ by\topskip \advance\dimen@ by-\baselineskip
- \divide\dimen@ by2 \splittopskip=\topskip \splitmaxdepth=\maxdepth
- {\vbadness=10000
- \loop \global\setbox5=\copy0
- \setbox1=\vsplit5 to\dimen@
- \setbox3=\vsplit5 to\dimen@
- \ifvbox5 \global\advance\dimen@ by1pt \repeat
- \setbox0=\vbox to\dimen@{\unvbox1}
- \setbox2=\vbox to\dimen@{\unvbox3}
- \global\setbox\partialpage=\vbox{\pagesofar}
- \doublecolumnpagegoal
- }
- \fi
- \fi
+\def\enddoublecolumns{%
+ \output = {\balancecolumns}\eject % split what we have
+ \endgroup % started in \begindoublecolumns
+ %
+ % Back to normal single-column typesetting, but take account of the
+ % fact that we just accumulated some stuff on the output page.
+ \pagegoal = \vsize
+}
+\def\balancecolumns{%
+ % Called at the end of the double column material.
+ \setbox0 = \vbox{\unvbox255}%
+ \dimen@ = \ht0
+ \advance\dimen@ by \topskip
+ \advance\dimen@ by-\baselineskip
+ \divide\dimen@ by 2
+ \splittopskip = \topskip
+ % Loop until we get a decent breakpoint.
+ {\vbadness=10000 \loop
+ \global\setbox3=\copy0
+ \global\setbox1=\vsplit3 to\dimen@
+ \ifdim\ht3>\dimen@ \global\advance\dimen@ by1pt
+ \repeat}%
+ \setbox0=\vbox to\dimen@{\unvbox1}%
+ \setbox2=\vbox to\dimen@{\unvbox3}%
+ \pagesofar
}
+\catcode`\@ = \other
+
-\catcode `\@=\other
\message{sectioning,}
% Define chapters, sections, etc.
-\newcount \chapno
-\newcount \secno \secno=0
-\newcount \subsecno \subsecno=0
-\newcount \subsubsecno \subsubsecno=0
+\newcount\chapno
+\newcount\secno \secno=0
+\newcount\subsecno \subsecno=0
+\newcount\subsubsecno \subsubsecno=0
% This counter is funny since it counts through charcodes of letters A, B, ...
-\newcount \appendixno \appendixno = `\@
+\newcount\appendixno \appendixno = `\@
\def\appendixletter{\char\the\appendixno}
-\newwrite \contentsfile
+\newwrite\contentsfile
% This is called from \setfilename.
-\def\opencontents{\openout \contentsfile = \jobname.toc}
+\def\opencontents{\openout\contentsfile = \jobname.toc }
% Each @chapter defines this as the name of the chapter.
% page headings and footings can use it. @section does likewise
\def\thischapter{} \def\thissection{}
-\def\seccheck#1{\if \pageno<0 %
-\errmessage{@#1 not allowed after generating table of contents}\fi
-%
-}
+\def\seccheck#1{\ifnum \pageno<0
+ \errmessage{@#1 not allowed after generating table of contents}%
+\fi}
\def\chapternofonts{%
-\let\rawbackslash=\relax%
-\let\frenchspacing=\relax%
-\def\result{\realbackslash result}
-\def\equiv{\realbackslash equiv}
-\def\expansion{\realbackslash expansion}
-\def\print{\realbackslash print}
-\def\TeX{\realbackslash TeX}
-\def\dots{\realbackslash dots}
-\def\copyright{\realbackslash copyright}
-\def\tt{\realbackslash tt}
-\def\bf{\realbackslash bf }
-\def\w{\realbackslash w}
-\def\less{\realbackslash less}
-\def\gtr{\realbackslash gtr}
-\def\hat{\realbackslash hat}
-\def\char{\realbackslash char}
-\def\tclose##1{\realbackslash tclose {##1}}
-\def\code##1{\realbackslash code {##1}}
-\def\samp##1{\realbackslash samp {##1}}
-\def\r##1{\realbackslash r {##1}}
-\def\b##1{\realbackslash b {##1}}
-\def\key##1{\realbackslash key {##1}}
-\def\file##1{\realbackslash file {##1}}
-\def\kbd##1{\realbackslash kbd {##1}}
-% These are redefined because @smartitalic wouldn't work inside xdef.
-\def\i##1{\realbackslash i {##1}}
-\def\cite##1{\realbackslash cite {##1}}
-\def\var##1{\realbackslash var {##1}}
-\def\emph##1{\realbackslash emph {##1}}
-\def\dfn##1{\realbackslash dfn {##1}}
+ \let\rawbackslash=\relax
+ \let\frenchspacing=\relax
+ \def\result{\realbackslash result}%
+ \def\equiv{\realbackslash equiv}%
+ \def\expansion{\realbackslash expansion}%
+ \def\print{\realbackslash print}%
+ \def\TeX{\realbackslash TeX}%
+ \def\dots{\realbackslash dots}%
+ \def\result{\realbackslash result}%
+ \def\equiv{\realbackslash equiv}%
+ \def\expansion{\realbackslash expansion}%
+ \def\print{\realbackslash print}%
+ \def\error{\realbackslash error}%
+ \def\point{\realbackslash point}%
+ \def\copyright{\realbackslash copyright}%
+ \def\tt{\realbackslash tt}%
+ \def\bf{\realbackslash bf}%
+ \def\w{\realbackslash w}%
+ \def\less{\realbackslash less}%
+ \def\gtr{\realbackslash gtr}%
+ \def\hat{\realbackslash hat}%
+ \def\char{\realbackslash char}%
+ \def\tclose##1{\realbackslash tclose{##1}}%
+ \def\code##1{\realbackslash code{##1}}%
+ \def\samp##1{\realbackslash samp{##1}}%
+ \def\r##1{\realbackslash r{##1}}%
+ \def\b##1{\realbackslash b{##1}}%
+ \def\key##1{\realbackslash key{##1}}%
+ \def\file##1{\realbackslash file{##1}}%
+ \def\kbd##1{\realbackslash kbd{##1}}%
+ % These are redefined because @smartitalic wouldn't work inside xdef.
+ \def\i##1{\realbackslash i{##1}}%
+ \def\cite##1{\realbackslash cite{##1}}%
+ \def\var##1{\realbackslash var{##1}}%
+ \def\emph##1{\realbackslash emph{##1}}%
+ \def\dfn##1{\realbackslash dfn{##1}}%
}
\newcount\absseclevel % used to calculate proper heading level
@@ -2515,7 +2897,8 @@ July\or August\or September\or October\or November\or December\fi
% because we don't want its macros evaluated now.
\xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}%
{\chapternofonts%
-\edef\temp{{\realbackslash chapentry {#1}{\the\chapno}{\noexpand\folio}}}%
+\toks0 = {#1}%
+\edef\temp{{\realbackslash chapentry{\the\toks0}{\the\chapno}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\donoderef %
@@ -2534,8 +2917,9 @@ July\or August\or September\or October\or November\or December\fi
\gdef\thischaptername{#1}%
\xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}%
{\chapternofonts%
-\edef\temp{{\realbackslash chapentry
- {#1}{\putwordAppendix{} \appendixletter}{\noexpand\folio}}}%
+\toks0 = {#1}%
+\edef\temp{{\realbackslash chapentry{\the\toks0}%
+ {\putwordAppendix{} \appendixletter}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\appendixnoderef %
@@ -2544,6 +2928,10 @@ July\or August\or September\or October\or November\or December\fi
\global\let\subsubsection = \appendixsubsubsec
}}
+% @centerchap is like @unnumbered, but the heading is centered.
+\outer\def\centerchap{\parsearg\centerchapyyy}
+\def\centerchapyyy #1{{\let\unnumbchapmacro=\centerchapmacro \unnumberedyyy{#1}}}
+
\outer\def\top{\parsearg\unnumberedyyy}
\outer\def\unnumbered{\parsearg\unnumberedyyy}
\def\unnumberedyyy #1{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz
@@ -2565,7 +2953,8 @@ July\or August\or September\or October\or November\or December\fi
\unnumbchapmacro {#1}%
\gdef\thischapter{#1}\gdef\thissection{#1}%
{\chapternofonts%
-\edef\temp{{\realbackslash unnumbchapentry {#1}{\noexpand\folio}}}%
+\toks0 = {#1}%
+\edef\temp{{\realbackslash unnumbchapentry{\the\toks0}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\unnumbnoderef %
@@ -2580,8 +2969,9 @@ July\or August\or September\or October\or November\or December\fi
\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
\gdef\thissection{#1}\secheading {#1}{\the\chapno}{\the\secno}%
{\chapternofonts%
+\toks0 = {#1}%
\edef\temp{{\realbackslash secentry %
-{#1}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
+{\the\toks0}{\the\chapno}{\the\secno}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\donoderef %
@@ -2595,8 +2985,9 @@ July\or August\or September\or October\or November\or December\fi
\subsecno=0 \subsubsecno=0 \global\advance \secno by 1 %
\gdef\thissection{#1}\secheading {#1}{\appendixletter}{\the\secno}%
{\chapternofonts%
+\toks0 = {#1}%
\edef\temp{{\realbackslash secentry %
-{#1}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
+{\the\toks0}{\appendixletter}{\the\secno}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\appendixnoderef %
@@ -2608,7 +2999,8 @@ July\or August\or September\or October\or November\or December\fi
\def\unnumberedseczzz #1{\seccheck{unnumberedsec}%
\plainsecheading {#1}\gdef\thissection{#1}%
{\chapternofonts%
-\edef\temp{{\realbackslash unnumbsecentry{#1}{\noexpand\folio}}}%
+\toks0 = {#1}%
+\edef\temp{{\realbackslash unnumbsecentry{\the\toks0}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\unnumbnoderef %
@@ -2621,8 +3013,9 @@ July\or August\or September\or October\or November\or December\fi
\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
\subsecheading {#1}{\the\chapno}{\the\secno}{\the\subsecno}%
{\chapternofonts%
+\toks0 = {#1}%
\edef\temp{{\realbackslash subsecentry %
-{#1}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+{\the\toks0}{\the\chapno}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\donoderef %
@@ -2635,8 +3028,9 @@ July\or August\or September\or October\or November\or December\fi
\gdef\thissection{#1}\subsubsecno=0 \global\advance \subsecno by 1 %
\subsecheading {#1}{\appendixletter}{\the\secno}{\the\subsecno}%
{\chapternofonts%
+\toks0 = {#1}%
\edef\temp{{\realbackslash subsecentry %
-{#1}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
+{\the\toks0}{\appendixletter}{\the\secno}{\the\subsecno}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\appendixnoderef %
@@ -2646,9 +3040,10 @@ July\or August\or September\or October\or November\or December\fi
\outer\def\unnumberedsubsec{\parsearg\unnumberedsubsecyyy}
\def\unnumberedsubsecyyy #1{\unnmhead2{#1}} %normally calls unnumberedsubseczzz
\def\unnumberedsubseczzz #1{\seccheck{unnumberedsubsec}%
-\plainsecheading {#1}\gdef\thissection{#1}%
+\plainsubsecheading {#1}\gdef\thissection{#1}%
{\chapternofonts%
-\edef\temp{{\realbackslash unnumbsubsecentry{#1}{\noexpand\folio}}}%
+\toks0 = {#1}%
+\edef\temp{{\realbackslash unnumbsubsecentry{\the\toks0}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\unnumbnoderef %
@@ -2662,8 +3057,8 @@ July\or August\or September\or October\or November\or December\fi
\subsubsecheading {#1}
{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
{\chapternofonts%
-\edef\temp{{\realbackslash subsubsecentry %
- {#1}
+\toks0 = {#1}%
+\edef\temp{{\realbackslash subsubsecentry{\the\toks0}
{\the\chapno}{\the\secno}{\the\subsecno}{\the\subsubsecno}
{\noexpand\folio}}}%
\escapechar=`\\%
@@ -2679,7 +3074,8 @@ July\or August\or September\or October\or November\or December\fi
\subsubsecheading {#1}
{\appendixletter}{\the\secno}{\the\subsecno}{\the\subsubsecno}%
{\chapternofonts%
-\edef\temp{{\realbackslash subsubsecentry{#1}%
+\toks0 = {#1}%
+\edef\temp{{\realbackslash subsubsecentry{\the\toks0}%
{\appendixletter}
{\the\secno}{\the\subsecno}{\the\subsubsecno}{\noexpand\folio}}}%
\escapechar=`\\%
@@ -2691,9 +3087,10 @@ July\or August\or September\or October\or November\or December\fi
\outer\def\unnumberedsubsubsec{\parsearg\unnumberedsubsubsecyyy}
\def\unnumberedsubsubsecyyy #1{\unnmhead3{#1}} %normally unnumberedsubsubseczzz
\def\unnumberedsubsubseczzz #1{\seccheck{unnumberedsubsubsec}%
-\plainsecheading {#1}\gdef\thissection{#1}%
+\plainsubsubsecheading {#1}\gdef\thissection{#1}%
{\chapternofonts%
-\edef\temp{{\realbackslash unnumbsubsubsecentry{#1}{\noexpand\folio}}}%
+\toks0 = {#1}%
+\edef\temp{{\realbackslash unnumbsubsubsecentry{\the\toks0}{\noexpand\folio}}}%
\escapechar=`\\%
\write \contentsfile \temp %
\unnumbnoderef %
@@ -2729,10 +3126,10 @@ July\or August\or September\or October\or November\or December\fi
% NOTE on use of \vbox for chapter headings, section headings, and
% such:
-% 1) We use \vbox rather than the earlier \line to permit
-% overlong headings to fold.
-% 2) \hyphenpenalty is set to 10000 because hyphenation in a
-% heading is obnoxious; this forbids it.
+% 1) We use \vbox rather than the earlier \line to permit
+% overlong headings to fold.
+% 2) \hyphenpenalty is set to 10000 because hyphenation in a
+% heading is obnoxious; this forbids it.
% 3) Likewise, headings look best if no \parindent is used, and
% if justification is not attempted. Hence \raggedright.
@@ -2750,11 +3147,10 @@ July\or August\or September\or October\or November\or December\fi
\parindent=0pt\raggedright
\rm #1\hfill}}\bigskip \par\penalty 200}
-\def\heading{\parsearg\secheadingi}
-
-\def\subheading{\parsearg\subsecheadingi}
-
-\def\subsubheading{\parsearg\subsubsecheadingi}
+% @heading, @subheading, @subsubheading.
+\def\heading{\parsearg\plainsecheading}
+\def\subheading{\parsearg\plainsubsecheading}
+\def\subsubheading{\parsearg\plainsubsubsecheading}
% These macros generate a chapter, section, etc. heading only
% (including whitespace, linebreaking, etc. around it),
@@ -2768,7 +3164,7 @@ July\or August\or September\or October\or November\or December\fi
%%% Define plain chapter starts, and page on/off switching for it
% Parameter controlling skip before chapter headings (if needed)
-\newskip \chapheadingskip \chapheadingskip = 30pt plus 8pt minus 4pt
+\newskip\chapheadingskip
\def\chapbreak{\dobreak \chapheadingskip {-4000}}
\def\chappager{\par\vfill\supereject}
@@ -2777,15 +3173,18 @@ July\or August\or September\or October\or November\or December\fi
\def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname}
\def\CHAPPAGoff{
+\global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chapbreak
\global\let\pagealignmacro=\chappager}
\def\CHAPPAGon{
+\global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chappager
\global\let\pagealignmacro=\chappager
\global\def\HEADINGSon{\HEADINGSsingle}}
\def\CHAPPAGodd{
+\global\let\contentsalignmacro = \chapoddpage
\global\let\pchapsepmacro=\chapoddpage
\global\let\pagealignmacro=\chapoddpage
\global\def\HEADINGSon{\HEADINGSdouble}}
@@ -2794,25 +3193,39 @@ July\or August\or September\or October\or November\or December\fi
\def\CHAPFplain{
\global\let\chapmacro=\chfplain
-\global\let\unnumbchapmacro=\unnchfplain}
+\global\let\unnumbchapmacro=\unnchfplain
+\global\let\centerchapmacro=\centerchfplain}
-\def\chfplain #1#2{%
+% Plain chapter opening.
+% #1 is the text, #2 the chapter number or empty if unnumbered.
+\def\chfplain#1#2{%
\pchapsepmacro
{%
- \chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
- \parindent=0pt\raggedright
- \rm #2\enspace #1}%
+ \chapfonts \rm
+ \def\chapnum{#2}%
+ \setbox0 = \hbox{#2\ifx\chapnum\empty\else\enspace\fi}%
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 \centerparametersmaybe
+ \unhbox0 #1\par}%
}%
- \bigskip
- \penalty5000
+ \nobreak\bigskip % no page break after a chapter title
+ \nobreak
}
-\def\unnchfplain #1{%
-\pchapsepmacro %
-{\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
- \parindent=0pt\raggedright
- \rm #1\hfill}}\bigskip \par\penalty 10000 %
-}
+% Plain opening for unnumbered.
+\def\unnchfplain#1{\chfplain{#1}{}}
+
+% @centerchap -- centered and unnumbered.
+\let\centerparametersmaybe = \relax
+\def\centerchfplain#1{{%
+ \def\centerparametersmaybe{%
+ \advance\rightskip by 3\rightskip
+ \leftskip = \rightskip
+ \parfillskip = 0pt
+ }%
+ \chfplain{#1}{}%
+}}
+
\CHAPFplain % The default
\def\unnchfopen #1{%
@@ -2826,75 +3239,85 @@ July\or August\or September\or October\or November\or December\fi
\par\penalty 5000 %
}
+\def\centerchfopen #1{%
+\chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000
+ \parindent=0pt
+ \hfill {\rm #1}\hfill}}\bigskip \par\penalty 10000 %
+}
+
\def\CHAPFopen{
\global\let\chapmacro=\chfopen
-\global\let\unnumbchapmacro=\unnchfopen}
+\global\let\unnumbchapmacro=\unnchfopen
+\global\let\centerchapmacro=\centerchfopen}
+
-% Parameter controlling skip before section headings.
+% Section titles.
+\newskip\secheadingskip
+\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+\def\secheading#1#2#3{\sectionheading{sec}{#2.#3}{#1}}
+\def\plainsecheading#1{\sectionheading{sec}{}{#1}}
-\newskip \subsecheadingskip \subsecheadingskip = 17pt plus 8pt minus 4pt
+% Subsection titles.
+\newskip \subsecheadingskip
\def\subsecheadingbreak{\dobreak \subsecheadingskip {-500}}
+\def\subsecheading#1#2#3#4{\sectionheading{subsec}{#2.#3.#4}{#1}}
+\def\plainsubsecheading#1{\sectionheading{subsec}{}{#1}}
-\newskip \secheadingskip \secheadingskip = 21pt plus 8pt minus 4pt
-\def\secheadingbreak{\dobreak \secheadingskip {-1000}}
+% Subsubsection titles.
+\let\subsubsecheadingskip = \subsecheadingskip
+\let\subsubsecheadingbreak = \subsecheadingbreak
+\def\subsubsecheading#1#2#3#4#5{\sectionheading{subsubsec}{#2.#3.#4.#5}{#1}}
+\def\plainsubsubsecheading#1{\sectionheading{subsubsec}{}{#1}}
-% @paragraphindent is defined for the Info formatting commands only.
-\let\paragraphindent=\comment
-% Section fonts are the base font at magstep2, which produces
-% a size a bit more than 14 points in the default situation.
-
-\def\secheading #1#2#3{\secheadingi {#2.#3\enspace #1}}
-\def\plainsecheading #1{\secheadingi {#1}}
-\def\secheadingi #1{{\advance \secheadingskip by \parskip %
-\secheadingbreak}%
-{\secfonts \vbox{\hyphenpenalty=10000\tolerance=5000
- \parindent=0pt\raggedright
- \rm #1\hfill}}%
-\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
-
-
-% Subsection fonts are the base font at magstep1,
-% which produces a size of 12 points.
-
-\def\subsecheading #1#2#3#4{\subsecheadingi {#2.#3.#4\enspace #1}}
-\def\subsecheadingi #1{{\advance \subsecheadingskip by \parskip %
-\subsecheadingbreak}%
-{\subsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
- \parindent=0pt\raggedright
- \rm #1\hfill}}%
-\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000 }
-
-\def\subsubsecfonts{\subsecfonts} % Maybe this should change:
- % Perhaps make sssec fonts scaled
- % magstep half
-\def\subsubsecheading #1#2#3#4#5{\subsubsecheadingi {#2.#3.#4.#5\enspace #1}}
-\def\subsubsecheadingi #1{{\advance \subsecheadingskip by \parskip %
-\subsecheadingbreak}%
-{\subsubsecfonts \vbox{\hyphenpenalty=10000\tolerance=5000
- \parindent=0pt\raggedright
- \rm #1\hfill}}%
-\ifdim \parskip<10pt \kern 10pt\kern -\parskip\fi \penalty 10000}
+% Print any size section title.
+%
+% #1 is the section type (sec/subsec/subsubsec), #2 is the section
+% number (maybe empty), #3 the text.
+\def\sectionheading#1#2#3{%
+ {%
+ \expandafter\advance\csname #1headingskip\endcsname by \parskip
+ \csname #1headingbreak\endcsname
+ }%
+ {%
+ % Switch to the right set of fonts.
+ \csname #1fonts\endcsname \rm
+ %
+ % Only insert the separating space if we have a section number.
+ \def\secnum{#2}%
+ \setbox0 = \hbox{#2\ifx\secnum\empty\else\enspace\fi}%
+ %
+ \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright
+ \hangindent = \wd0 % zero if no section number
+ \unhbox0 #3}%
+ }%
+ \ifdim\parskip<10pt \nobreak\kern10pt\nobreak\kern-\parskip\fi \nobreak
+}
\message{toc printing,}
-
% Finish up the main text and prepare to read what we've written
% to \contentsfile.
\newskip\contentsrightmargin \contentsrightmargin=1in
\def\startcontents#1{%
- \pagealignmacro
+ % If @setchapternewpage on, and @headings double, the contents should
+ % start on an odd page, unlike chapters. Thus, we maintain
+ % \contentsalignmacro in parallel with \pagealignmacro.
+ % From: Torbjorn Granlund <tege@matematik.su.se>
+ \contentsalignmacro
\immediate\closeout \contentsfile
\ifnum \pageno>0
- \pageno = -1 % Request roman numbered pages.
+ \pageno = -1 % Request roman numbered pages.
\fi
% Don't need to put `Contents' or `Short Contents' in the headline.
% It is abundantly clear what they are.
\unnumbchapmacro{#1}\def\thischapter{}%
- \begingroup % Set up to handle contents files properly.
+ \begingroup % Set up to handle contents files properly.
\catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11
- \catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
+ % We can't do this, because then an actual ^ in a section
+ % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97.
+ %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi
\raggedbottom % Worry more about breakpoints than the bottom.
\advance\hsize by -\contentsrightmargin % Don't use the full line length.
}
@@ -2918,6 +3341,7 @@ July\or August\or September\or October\or November\or December\fi
\secfonts
\let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl
\rm
+ \hyphenpenalty = 10000
\advance\baselineskip by 1pt % Open it up a little.
\def\secentry ##1##2##3##4{}
\def\unnumbsecentry ##1##2{}
@@ -2961,7 +3385,7 @@ July\or August\or September\or October\or November\or December\fi
% This space should be plenty, since a single number is .5em, and the
% widest letter (M) is 1em, at least in the Computer Modern fonts.
% (This space doesn't include the extra space that gets added after
- % the label; that gets put in in \shortchapentry above.)
+ % the label; that gets put in by \shortchapentry above.)
\advance\dimen0 by 1.1em
\hbox to \dimen0{#1\hfil}%
}
@@ -2982,22 +3406,21 @@ July\or August\or September\or October\or November\or December\fi
\dosubsubsecentry{#2.#3.#4.#5\labelspace#1}{#6}}
\def\unnumbsubsubsecentry#1#2{\dosubsubsecentry{#1}{#2}}
-
% This parameter controls the indentation of the various levels.
\newdimen\tocindent \tocindent = 3pc
% Now for the actual typesetting. In all these, #1 is the text and #2 is the
% page number.
%
-% If the toc has to be broken over pages, we would want to be at chapters
+% If the toc has to be broken over pages, we want it to be at chapters
% if at all possible; hence the \penalty.
\def\dochapentry#1#2{%
- \penalty-300 \vskip\baselineskip
+ \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
\begingroup
\chapentryfonts
\tocentry{#1}{\dopageno{#2}}%
\endgroup
- \nobreak\vskip .25\baselineskip
+ \nobreak\vskip .25\baselineskip plus.1\baselineskip
}
\def\dosecentry#1#2{\begingroup
@@ -3022,7 +3445,7 @@ July\or August\or September\or October\or November\or December\fi
%
% \turnoffactive is for the sake of @" used for umlauts.
\def\tocentry#1#2{\begingroup
- \hyphenpenalty = 10000
+ \vskip 0pt plus1pt % allow a little stretch for the sake of nice page breaks
\entry{\turnoffactive #1}{\turnoffactive #2}%
\endgroup}
@@ -3047,8 +3470,6 @@ July\or August\or September\or October\or November\or December\fi
\newbox\pushcharbox \newbox\bullbox
\newbox\equivbox \newbox\errorbox
-\let\ptexequiv = \equiv
-
%{\tentt
%\global\setbox\dblarrowbox = \hbox to 1em{\hfil$\Rightarrow$\hfil}
%\global\setbox\longdblarrowbox = \hbox to 1em{\hfil$\mapsto$\hfil}
@@ -3059,12 +3480,11 @@ July\or August\or September\or October\or November\or December\fi
% depth .1ex\hfil}
%}
+% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
\def\point{$\star$}
-
\def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
\def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}}
\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
-
\def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}}
% Adapted from the TeXbook's \boxit.
@@ -3096,7 +3516,7 @@ July\or August\or September\or October\or November\or December\fi
\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
\catcode `\^=7 \catcode `\_=8 \catcode `\~=13 \let~=\tie
\catcode `\%=14
-\catcode 43=12
+\catcode 43=12 % plus
\catcode`\"=12
\catcode`\==12
\catcode`\|=12
@@ -3104,16 +3524,17 @@ July\or August\or September\or October\or November\or December\fi
\catcode`\>=12
\escapechar=`\\
%
-\let\~=\ptextilde
+\let\,=\ptexcomma
\let\{=\ptexlbrace
\let\}=\ptexrbrace
\let\.=\ptexdot
\let\*=\ptexstar
\let\dots=\ptexdots
+\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
+\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
\def\@{@}%
\let\bullet=\ptexbullet
-\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext \let\l=\ptexl
-\let\L=\ptexL
+\let\b=\ptexb \let\c=\ptexc \let\i=\ptexi \let\t=\ptext
%
\let\Etex=\endgroup}
@@ -3172,50 +3593,50 @@ July\or August\or September\or October\or November\or December\fi
\def\cbl{{\circle\char'012\hskip -6pt}}
\def\cbr{{\hskip 6pt\circle\char'011}}
\def\carttop{\hbox to \cartouter{\hskip\lskip
- \ctl\leaders\hrule height\circthick\hfil\ctr
- \hskip\rskip}}
+ \ctl\leaders\hrule height\circthick\hfil\ctr
+ \hskip\rskip}}
\def\cartbot{\hbox to \cartouter{\hskip\lskip
- \cbl\leaders\hrule height\circthick\hfil\cbr
- \hskip\rskip}}
+ \cbl\leaders\hrule height\circthick\hfil\cbr
+ \hskip\rskip}}
%
\newskip\lskip\newskip\rskip
\long\def\cartouche{%
\begingroup
- \lskip=\leftskip \rskip=\rightskip
- \leftskip=0pt\rightskip=0pt %we want these *outside*.
- \cartinner=\hsize \advance\cartinner by-\lskip
- \advance\cartinner by-\rskip
- \cartouter=\hsize
- \advance\cartouter by 18pt % allow for 3pt kerns on either
-% side, and for 6pt waste from
-% each corner char
- \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
- % Flag to tell @lisp, etc., not to narrow margin.
- \let\nonarrowing=\comment
- \vbox\bgroup
- \baselineskip=0pt\parskip=0pt\lineskip=0pt
- \carttop
- \hbox\bgroup
- \hskip\lskip
- \vrule\kern3pt
- \vbox\bgroup
- \hsize=\cartinner
- \kern3pt
- \begingroup
- \baselineskip=\normbskip
- \lineskip=\normlskip
- \parskip=\normpskip
- \vskip -\parskip
+ \lskip=\leftskip \rskip=\rightskip
+ \leftskip=0pt\rightskip=0pt %we want these *outside*.
+ \cartinner=\hsize \advance\cartinner by-\lskip
+ \advance\cartinner by-\rskip
+ \cartouter=\hsize
+ \advance\cartouter by 18pt % allow for 3pt kerns on either
+% side, and for 6pt waste from
+% each corner char
+ \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
+ % Flag to tell @lisp, etc., not to narrow margin.
+ \let\nonarrowing=\comment
+ \vbox\bgroup
+ \baselineskip=0pt\parskip=0pt\lineskip=0pt
+ \carttop
+ \hbox\bgroup
+ \hskip\lskip
+ \vrule\kern3pt
+ \vbox\bgroup
+ \hsize=\cartinner
+ \kern3pt
+ \begingroup
+ \baselineskip=\normbskip
+ \lineskip=\normlskip
+ \parskip=\normpskip
+ \vskip -\parskip
\def\Ecartouche{%
- \endgroup
- \kern3pt
- \egroup
- \kern3pt\vrule
- \hskip\rskip
- \egroup
- \cartbot
- \egroup
+ \endgroup
+ \kern3pt
+ \egroup
+ \kern3pt\vrule
+ \hskip\rskip
+ \egroup
+ \cartbot
+ \egroup
\endgroup
}}
@@ -3251,11 +3672,12 @@ July\or August\or September\or October\or November\or December\fi
%
\def\nonfillfinish{\afterenvbreak\endgroup}%
-% This macro is
\def\lisp{\begingroup
\nonfillstart
\let\Elisp = \nonfillfinish
\tt
+ % Make @kbd do something special, if requested.
+ \let\kbdfont\kbdexamplefont
\rawbackslash % have \ input char produce \ char from current font
\gobble
}
@@ -3278,8 +3700,7 @@ July\or August\or September\or October\or November\or December\fi
\let\Esmalllisp = \nonfillfinish
\let\Esmallexample = \nonfillfinish
%
- % Smaller interline space and fonts for small examples.
- \setleading{10pt}%
+ % Smaller fonts for small examples.
\indexfonts \tt
\rawbackslash % make \ output the \ character from the current font (tt)
\gobble
@@ -3374,16 +3795,17 @@ July\or August\or September\or October\or November\or December\fi
% Definitions of (, ) and & used in args for functions.
% This is the definition of ( outside of all parentheses.
-\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested %
-\global\advance\parencount by 1 }
+\gdef\oprm#1 {{\rm\char`\(}#1 \bf \let(=\opnested
+ \global\advance\parencount by 1
+}
%
% This is the definition of ( when already inside a level of parens.
\gdef\opnested{\char`\(\global\advance\parencount by 1 }
%
\gdef\clrm{% Print a paren in roman if it is taking us back to depth of 0.
-% also in that case restore the outer-level definition of (.
-\ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
-\global\advance \parencount by -1 }
+ % also in that case restore the outer-level definition of (.
+ \ifnum \parencount=1 {\rm \char `\)}\sl \let(=\oprm \else \char `\) \fi
+ \global\advance \parencount by -1 }
% If we encounter &foo, then turn on ()-hacking afterwards
\gdef\amprm#1 {{\rm\&#1}\let(=\oprm \let)=\clrm\ }
%
@@ -3391,8 +3813,11 @@ July\or August\or September\or October\or November\or December\fi
} % End of definition inside \activeparens
%% These parens (in \boldbrax) actually are a little bolder than the
%% contained text. This is especially needed for [ and ]
-\def\opnr{{\sf\char`\(}} \def\clnr{{\sf\char`\)}} \def\ampnr{\&}
-\def\lbrb{{\bf\char`\[}} \def\rbrb{{\bf\char`\]}}
+\def\opnr{{\sf\char`\(}\global\advance\parencount by 1 }
+\def\clnr{{\sf\char`\)}\global\advance\parencount by -1 }
+\def\ampnr{\&}
+\def\lbrb{{\bf\char`\[}}
+\def\rbrb{{\bf\char`\]}}
% First, defname, which formats the header line itself.
% #1 should be the function name.
@@ -3485,7 +3910,7 @@ July\or August\or September\or October\or November\or December\fi
% This is used for \def{tp,vr}parsebody. It could probably be used for
% some of the others, too, with some judicious conditionals.
-%
+%
\def\parsebodycommon#1#2#3{%
\begingroup\inENV %
\medbreak %
@@ -3519,17 +3944,16 @@ July\or August\or September\or October\or November\or December\fi
}
% Fine, but then we have to eventually remove the \empty *and* the
-% braces (if any). That's what this does, putting the result in \tptemp.
-%
-\def\removeemptybraces\empty#1\relax{\def\tptemp{#1}}%
+% braces (if any). That's what this does.
+%
+\def\removeemptybraces\empty#1\relax{#1}
% After \spacesplit has done its work, this is called -- #1 is the final
% thing to call, #2 the type name (which starts with \empty), and #3
% (which might be empty) the arguments.
-%
+%
\def\parsetpheaderline#1#2#3{%
- \removeemptybraces#2\relax
- #1{\tptemp}{#3}%
+ #1{\removeemptybraces#2\relax}{#3}%
}%
\def\defopvarparsebody #1#2#3#4#5 {\begingroup\inENV %
@@ -3570,7 +3994,7 @@ July\or August\or September\or October\or November\or December\fi
\hyphenchar\tensl=0
#1%
\hyphenchar\tensl=45
-\ifnum\parencount=0 \else \errmessage{unbalanced parens in @def arguments}\fi%
+\ifnum\parencount=0 \else \errmessage{Unbalanced parentheses in @def}\fi%
\interlinepenalty=10000
\advance\rightskip by 0pt plus 1fil
\endgraf\penalty 10000\vskip -\parskip\penalty 10000%
@@ -3671,6 +4095,7 @@ July\or August\or September\or October\or November\or December\fi
\def\defmacx #1 {\errmessage{@defmacx in invalid context}}
\def\defspecx #1 {\errmessage{@defspecx in invalid context}}
\def\deftypefnx #1 {\errmessage{@deftypefnx in invalid context}}
+\def\deftypemethodx #1 {\errmessage{@deftypemethodx in invalid context}}
\def\deftypeunx #1 {\errmessage{@deftypeunx in invalid context}}
% @defmethod, and so on
@@ -3686,6 +4111,16 @@ July\or August\or September\or October\or November\or December\fi
\defunargs {#3}\endgroup %
}
+% @deftypemethod foo-class return-type foo-method args
+%
+\def\deftypemethod{%
+ \defmethparsebody\Edeftypemethod\deftypemethodx\deftypemethodheader}
+%
+% #1 is the class name, #2 the data type, #3 the method name, #4 the args.
+\def\deftypemethodheader#1#2#3#4{%
+ \deftypefnheaderx{Method on #1}{#2}#3 #4\relax
+}
+
% @defmethod == @defop Method
\def\defmethod{\defmethparsebody\Edefmethod\defmethodx\defmethodheader}
@@ -3763,19 +4198,21 @@ July\or August\or September\or October\or November\or December\fi
\def\deftypevar{\defvarparsebody\Edeftypevar\deftypevarx\deftypevarheader}
-% #1 is the data type. #2 is the name.
+% #1 is the data type. #2 is the name, perhaps followed by text that
+% is actually part of the data type, which should not be put into the index.
\def\deftypevarheader #1#2{%
-\doind {vr}{\code{#2}}% Make entry in variables index
+\dovarind#2 \relax% Make entry in variables index
\begingroup\defname {\defheaderxcond#1\relax$$$#2}{Variable}%
\interlinepenalty=10000
\endgraf\penalty 10000\vskip -\parskip\penalty 10000
\endgroup}
+\def\dovarind#1 #2\relax{\doind{vr}{\code{#1}}}
% @deftypevr {Global Flag} int enable
\def\deftypevr{\defvrparsebody\Edeftypevr\deftypevrx\deftypevrheader}
-\def\deftypevrheader #1#2#3{\doind {vr}{\code{#3}}%
+\def\deftypevrheader #1#2#3{\dovarind#3 \relax%
\begingroup\defname {\defheaderxcond#2\relax$$$#3}{#1}
\interlinepenalty=10000
\endgraf\penalty 10000\vskip -\parskip\penalty 10000
@@ -3807,6 +4244,7 @@ July\or August\or September\or October\or November\or December\fi
\def\deftpx #1 {\errmessage{@deftpx in invalid context}}
+
\message{cross reference,}
% Define cross-reference macros
\newwrite \auxfile
@@ -3814,6 +4252,11 @@ July\or August\or September\or October\or November\or December\fi
\newif\ifhavexrefs % True if xref values are known.
\newif\ifwarnedxrefs % True if we warned once that they aren't known.
+% @inforef is simple.
+\def\inforef #1{\inforefzzz #1,,,,**}
+\def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
+ node \samp{\ignorespaces#1{}}}
+
% \setref{foo} defines a cross-reference point named foo.
\def\setref#1{%
@@ -3847,7 +4290,7 @@ July\or August\or September\or October\or November\or December\fi
\setbox0=\hbox{\printednodename}%
\ifdim \wd0 = 0pt
% No printed node name was explicitly given.
- \ifx\SETxref-automatic-section-title\thisisundefined
+ \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax
% Use the node name inside the square brackets.
\def\printednodename{\ignorespaces #1}%
\else
@@ -3892,7 +4335,7 @@ July\or August\or September\or October\or November\or December\fi
% Use \turnoffactive so that punctuation chars such as underscore
% work in node names.
-\def\dosetq #1#2{{\let\folio=0 \turnoffactive \auxhat%
+\def\dosetq #1#2{{\let\folio=0 \turnoffactive
\edef\next{\write\auxfile{\internalsetq {#1}{#2}}}%
\next}}
@@ -3961,84 +4404,99 @@ July\or August\or September\or October\or November\or December\fi
#2% Output the suffix in any case.
}
-% Read the last existing aux file, if any. No error if none exists.
-
% This is the macro invoked by entries in the aux file.
-\def\xrdef #1#2{
-{\catcode`\'=\other\expandafter \gdef \csname X#1\endcsname {#2}}}
+\def\xrdef #1#2{{%
+ \catcode`\'=\other
+ \expandafter\gdef\csname X#1\endcsname{#2}%
+}}
-\def\readauxfile{%
-\begingroup
-\catcode `\^^@=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\^^C=\other
-\catcode `\^^D=\other
-\catcode `\^^E=\other
-\catcode `\^^F=\other
-\catcode `\^^G=\other
-\catcode `\^^H=\other
-\catcode `\ =\other
-\catcode `\^^L=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode `\=\other
-\catcode 26=\other
-\catcode `\^^[=\other
-\catcode `\^^\=\other
-\catcode `\^^]=\other
-\catcode `\^^^=\other
-\catcode `\^^_=\other
-\catcode `\@=\other
-\catcode `\^=\other
-\catcode `\~=\other
-\catcode `\[=\other
-\catcode `\]=\other
-\catcode`\"=\other
-\catcode`\_=\other
-\catcode`\|=\other
-\catcode`\<=\other
-\catcode`\>=\other
-\catcode `\$=\other
-\catcode `\#=\other
-\catcode `\&=\other
-% `\+ does not work, so use 43.
-\catcode 43=\other
-% Make the characters 128-255 be printing characters
-{%
- \count 1=128
- \def\loop{%
- \catcode\count 1=\other
- \advance\count 1 by 1
- \ifnum \count 1<256 \loop \fi
+% Read the last existing aux file, if any. No error if none exists.
+\def\readauxfile{\begingroup
+ \catcode`\^^@=\other
+ \catcode`\^^A=\other
+ \catcode`\^^B=\other
+ \catcode`\^^C=\other
+ \catcode`\^^D=\other
+ \catcode`\^^E=\other
+ \catcode`\^^F=\other
+ \catcode`\^^G=\other
+ \catcode`\^^H=\other
+ \catcode`\^^K=\other
+ \catcode`\^^L=\other
+ \catcode`\^^N=\other
+ \catcode`\^^P=\other
+ \catcode`\^^Q=\other
+ \catcode`\^^R=\other
+ \catcode`\^^S=\other
+ \catcode`\^^T=\other
+ \catcode`\^^U=\other
+ \catcode`\^^V=\other
+ \catcode`\^^W=\other
+ \catcode`\^^X=\other
+ \catcode`\^^Z=\other
+ \catcode`\^^[=\other
+ \catcode`\^^\=\other
+ \catcode`\^^]=\other
+ \catcode`\^^^=\other
+ \catcode`\^^_=\other
+ \catcode`\@=\other
+ \catcode`\^=\other
+ % It was suggested to define this as 7, which would allow ^^e4 etc.
+ % in xref tags, i.e., node names. But since ^^e4 notation isn't
+ % supported in the main text, it doesn't seem desirable. Furthermore,
+ % that is not enough: for node names that actually contain a ^
+ % character, we would end up writing a line like this: 'xrdef {'hat
+ % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first
+ % argument, and \hat is not an expandable control sequence. It could
+ % all be worked out, but why? Either we support ^^ or we don't.
+ %
+ % The other change necessary for this was to define \auxhat:
+ % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter
+ % and then to call \auxhat in \setq.
+ %
+ \catcode`\~=\other
+ \catcode`\[=\other
+ \catcode`\]=\other
+ \catcode`\"=\other
+ \catcode`\_=\other
+ \catcode`\|=\other
+ \catcode`\<=\other
+ \catcode`\>=\other
+ \catcode`\$=\other
+ \catcode`\#=\other
+ \catcode`\&=\other
+ % `\+ does not work, so use 43.
+ \catcode43=\other
+ % Make the characters 128-255 be printing characters
+ {%
+ \count 1=128
+ \def\loop{%
+ \catcode\count 1=\other
+ \advance\count 1 by 1
+ \ifnum \count 1<256 \loop \fi
+ }%
}%
-}%
-% the aux file uses ' as the escape.
-% Turn off \ as an escape so we do not lose on
-% entries which were dumped with control sequences in their names.
-% For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
-% Reference to such entries still does not work the way one would wish,
-% but at least they do not bomb out when the aux file is read in.
-\catcode `\{=1 \catcode `\}=2
-\catcode `\%=\other
-\catcode `\'=0
-\catcode`\^=7 % to make ^^e4 etc usable in xref tags
-\catcode `\\=\other
-\openin 1 \jobname.aux
-\ifeof 1 \else \closein 1 \input \jobname.aux \global\havexrefstrue
-\global\warnedobstrue
-\fi
-% Open the new aux file. Tex will close it automatically at exit.
-\openout \auxfile=\jobname.aux
+ % The aux file uses ' as the escape (for now).
+ % Turn off \ as an escape so we do not lose on
+ % entries which were dumped with control sequences in their names.
+ % For example, 'xrdef {$\leq $-fun}{page ...} made by @defun ^^
+ % Reference to such entries still does not work the way one would wish,
+ % but at least they do not bomb out when the aux file is read in.
+ \catcode`\{=1
+ \catcode`\}=2
+ \catcode`\%=\other
+ \catcode`\'=0
+ \catcode`\\=\other
+ %
+ \openin 1 \jobname.aux
+ \ifeof 1 \else
+ \closein 1
+ \input \jobname.aux
+ \global\havexrefstrue
+ \global\warnedobstrue
+ \fi
+ % Open the new aux file. TeX will close it automatically at exit.
+ \openout\auxfile=\jobname.aux
\endgroup}
@@ -4049,10 +4507,11 @@ July\or August\or September\or October\or November\or December\fi
% The trailing space in the following definition for supereject is
% vital for proper filling; pages come out unaligned when you do a
% pagealignmacro call if that space before the closing brace is
-% removed.
+% removed. (Generally, numeric constants should always be followed by a
+% space to prevent strange expansion errors.)
\def\supereject{\par\penalty -20000\footnoteno =0 }
-% @footnotestyle is meaningful for info output only..
+% @footnotestyle is meaningful for info output only.
\let\footnotestyle=\comment
\let\ptexfootnote=\footnote
@@ -4078,7 +4537,11 @@ July\or August\or September\or October\or November\or December\fi
% Don't bother with the trickery in plain.tex to not require the
% footnote text as a parameter. Our footnotes don't need to be so general.
%
-\long\gdef\footnotezzz#1{\insert\footins{%
+% Oh yes, they do; otherwise, @ifset and anything else that uses
+% \parseargline fail inside footnotes because the tokens are fixed when
+% the footnote is read. --karl, 16nov96.
+%
+\long\gdef\footnotezzz{\insert\footins\bgroup
% We want to typeset this text as a normal paragraph, even if the
% footnote reference occurs in (for example) a display environment.
% So reset some parameters.
@@ -4100,8 +4563,13 @@ July\or August\or September\or October\or November\or December\fi
% expands into a box, it must come within the paragraph, lest it
% provide a place where TeX can split the footnote.
\footstrut
- #1\strut}%
+ \futurelet\next\fo@t
}
+\def\fo@t{\ifcat\bgroup\noexpand\next \let\next\f@@t
+ \else\let\next\f@t\fi \next}
+\def\f@@t{\bgroup\aftergroup\@foot\let\next}
+\def\f@t#1{#1\@foot}
+\def\@foot{\strut\egroup}
}%end \catcode `\@=11
@@ -4158,9 +4626,51 @@ July\or August\or September\or October\or November\or December\fi
%
\def\finalout{\overfullrule=0pt}
+% @image. We use the macros from epsf.tex to support this.
+% If epsf.tex is not installed and @image is used, we complain.
+%
+% Check for and read epsf.tex up front. If we read it only at @image
+% time, we might be inside a group, and then its definitions would get
+% undone and the next image would fail.
+\openin 1 = epsf.tex
+\ifeof 1 \else
+ \closein 1
+ \def\epsfannounce{\toks0 = }% do not bother showing banner
+ \input epsf.tex
+\fi
+%
+\newif\ifwarnednoepsf
+\newhelp\noepsfhelp{epsf.tex must be installed for images to
+ work. It is also included in the Texinfo distribution, or you can get
+ it from ftp://ftp.tug.org/tex/epsf.tex.}
+%
+% Only complain once about lack of epsf.tex.
+\def\image#1{%
+ \ifx\epsfbox\undefined
+ \ifwarnednoepsf \else
+ \errhelp = \noepsfhelp
+ \errmessage{epsf.tex not found, images will be ignored}%
+ \global\warnednoepsftrue
+ \fi
+ \else
+ \imagexxx #1,,,\finish
+ \fi
+}
+%
+% Arguments to @image:
+% #1 is (mandatory) image filename; we tack on .eps extension.
+% #2 is (optional) width, #3 is (optional) height.
+% #4 is just the usual extra ignored arg for parsing this stuff.
+\def\imagexxx#1,#2,#3,#4\finish{%
+ % \epsfbox itself resets \epsf?size at each figure.
+ \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
+ \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
+ \epsfbox{#1.eps}%
+}
% End of control word definitions.
+
\message{and turning on texinfo input format.}
\def\openindices{%
@@ -4174,13 +4684,18 @@ July\or August\or September\or October\or November\or December\fi
% Set some numeric style parameters, for 8.5 x 11 format.
-%\hsize = 6.5in
+\hsize = 6in
+\hoffset = .25in
\newdimen\defaultparindent \defaultparindent = 15pt
\parindent = \defaultparindent
-\parskip 18pt plus 1pt
-\setleading{15pt}
+\parskip 3pt plus 2pt minus 1pt
+\setleading{13.2pt}
\advance\topskip by 1.2cm
+\chapheadingskip = 15pt plus 4pt minus 2pt
+\secheadingskip = 12pt plus 3pt minus 2pt
+\subsecheadingskip = 9pt plus 2pt minus 2pt
+
% Prevent underfull vbox error messages.
\vbadness=10000
@@ -4203,30 +4718,28 @@ July\or August\or September\or October\or November\or December\fi
% Use @smallbook to reset parameters for 7x9.5 format (or else 7x9.25)
\def\smallbook{
-
-% These values for secheadingskip and subsecheadingskip are
-% experiments. RJC 7 Aug 1992
-\global\secheadingskip = 17pt plus 6pt minus 3pt
-\global\subsecheadingskip = 14pt plus 6pt minus 3pt
-
-\global\lispnarrowing = 0.3in
-\setleading{12pt}
-\advance\topskip by -1cm
-\global\parskip 3pt plus 1pt
-\global\hsize = 5in
-\global\vsize=7.5in
-\global\tolerance=700
-\global\hfuzz=1pt
-\global\contentsrightmargin=0pt
-\global\deftypemargin=0pt
-\global\defbodyindent=.5cm
-
-\global\pagewidth=\hsize
-\global\pageheight=\vsize
-
-\global\let\smalllisp=\smalllispx
-\global\let\smallexample=\smalllispx
-\global\def\Esmallexample{\Esmalllisp}
+ \global\chapheadingskip = 15pt plus 4pt minus 2pt
+ \global\secheadingskip = 12pt plus 3pt minus 2pt
+ \global\subsecheadingskip = 9pt plus 2pt minus 2pt
+ %
+ \global\lispnarrowing = 0.3in
+ \setleading{12pt}
+ \advance\topskip by -1cm
+ \global\parskip 2pt plus 1pt
+ \global\hsize = 5in
+ \global\vsize=7.5in
+ \global\tolerance=700
+ \global\hfuzz=1pt
+ \global\contentsrightmargin=0pt
+ \global\deftypemargin=0pt
+ \global\defbodyindent=.5cm
+ %
+ \global\pagewidth=\hsize
+ \global\pageheight=\vsize
+ %
+ \global\let\smalllisp=\smalllispx
+ \global\let\smallexample=\smalllispx
+ \global\def\Esmallexample{\Esmalllisp}
}
% Use @afourpaper to print on European A4 paper.
@@ -4249,12 +4762,19 @@ July\or August\or September\or October\or November\or December\fi
\global\pageheight=\vsize
}
+\bindingoffset=0pt
+\normaloffset=\hoffset
+\pagewidth=\hsize
+\pageheight=\vsize
+
% Allow control of the text dimensions. Parameters in order: textheight;
-% textwidth; \voffset; \hoffset (!); binding offset. All require a dimension;
+% textwidth; voffset; hoffset; binding offset; topskip.
+% All require a dimension;
% header is additional; added length extends the bottom of the page.
-\def\changepagesizes#1#2#3#4#5{
+\def\changepagesizes#1#2#3#4#5#6{
\global\vsize= #1
+ \global\topskip= #6
\advance\vsize by \topskip
\global\voffset= #3
\global\hsize= #2
@@ -4267,13 +4787,20 @@ July\or August\or September\or October\or November\or December\fi
\global\normaloffset= #4
\global\bindingoffset= #5}
-% This layout is compatible with Latex on A4 paper.
-
-\def\afourlatex{\changepagesizes{22cm}{15cm}{7mm}{4.6mm}{5mm}}
+% A specific text layout, 24x15cm overall, intended for A4 paper. Top margin
+% 29mm, hence bottom margin 28mm, nominal side margin 3cm.
+\def\afourlatex
+ {\global\tolerance=700
+ \global\hfuzz=1pt
+ \setleading{12pt}
+ \global\parskip 15pt plus 1pt
+ \advance\baselineskip by 1.6pt
+ \changepagesizes{237mm}{150mm}{3.6mm}{3.6mm}{3mm}{7mm}
+ }
% Use @afourwide to print on European A4 paper in wide format.
\def\afourwide{\afourpaper
-\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}}
+\changepagesizes{9.5in}{6.5in}{\hoffset}{\normaloffset}{\bindingoffset}{7mm}}
% Define macros to output various characters with catcode for normal text.
\catcode`\"=\other
@@ -4316,20 +4843,12 @@ July\or August\or September\or October\or November\or December\fi
\def~{{\tt \char '176}}
\chardef\hat=`\^
\catcode`\^=\active
-\def\auxhat{\def^{'hat}}
\def^{{\tt \hat}}
\catcode`\_=\active
\def_{\ifusingtt\normalunderscore\_}
% Subroutine for the previous macro.
-\def\_{\lvvmode \kern.06em \vbox{\hrule width.3em height.1ex}}
-
-% \lvvmode is equivalent in function to \leavevmode.
-% Using \leavevmode runs into trouble when written out to
-% an index file due to the expansion of \leavevmode into ``\unhbox
-% \voidb@x'' ---which looks to TeX like ``\unhbox \voidb\x'' due to our
-% magic tricks with @.
-\def\lvvmode{\vbox to 0pt{}}
+\def\_{\leavevmode \kern.06em \vbox{\hrule width.3em height.1ex}}
\catcode`\|=\active
\def|{{\tt \char '174}}
diff --git a/gnu/usr.bin/gcc/tm.texi b/gnu/usr.bin/gcc/tm.texi
index 85bdf3a2b11..ff3500f8855 100644
--- a/gnu/usr.bin/gcc/tm.texi
+++ b/gnu/usr.bin/gcc/tm.texi
@@ -1,4 +1,4 @@
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
+@c Copyright (C) 1988,89,92,93,94,96,1997 Free Software Foundation, Inc.
@c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi.
@@ -55,9 +55,12 @@ A C expression which determines whether the option @samp{-@var{char}}
takes arguments. The value should be the number of arguments that
option takes--zero, for many options.
-By default, this macro is defined to handle the standard options
-properly. You need not define it unless you wish to add additional
-options which take arguments.
+By default, this macro is defined as
+@code{DEFAULT_SWITCH_TAKES_ARG}, which handles the standard options
+properly. You need not define @code{SWITCH_TAKES_ARG} unless you
+wish to add additional options which take arguments. Any redefinition
+should call @code{DEFAULT_SWITCH_TAKES_ARG} and then check for
+additional options.
@findex WORD_SWITCH_TAKES_ARG
@item WORD_SWITCH_TAKES_ARG (@var{name})
@@ -75,10 +78,10 @@ additional options.
@findex SWITCHES_NEED_SPACES
@item SWITCHES_NEED_SPACES
-A string-valued C expression which is nonempty if the linker needs a
-space between the @samp{-L} or @samp{-o} option and its argument.
+A string-valued C expression which enumerates the options for which
+the linker needs a space between the option and its argument.
-If this macro is not defined, the default value is 0.
+If this macro is not defined, the default value is @code{""}.
@findex CPP_SPEC
@item CPP_SPEC
@@ -197,6 +200,58 @@ the very end of the command given to the linker.
Do not define this macro if it does not need to do anything.
+@findex EXTRA_SPECS
+@item EXTRA_SPECS
+Define this macro to provide additional specifications to put in the
+@file{specs} file that can be used in various specifications like
+@code{CC1_SPEC}.
+
+The definition should be an initializer for an array of structures,
+containing a string constant, that defines the specification name, and a
+string constant that provides the specification.
+
+Do not define this macro if it does not need to do anything.
+
+@code{EXTRA_SPECS} is useful when an architecture contains several
+related targets, which have various @code{..._SPECS} which are similar
+to each other, and the maintainer would like one central place to keep
+these definitions.
+
+For example, the PowerPC System V.4 targets use @code{EXTRA_SPECS} to
+define either @code{_CALL_SYSV} when the System V calling sequence is
+used or @code{_CALL_AIX} when the older AIX-based calling sequence is
+used.
+
+The @file{config/rs6000/rs6000.h} target file defines:
+
+@example
+#define EXTRA_SPECS \
+ @{ "cpp_sysv_default", CPP_SYSV_DEFAULT @},
+
+#define CPP_SYS_DEFAULT ""
+@end example
+
+The @file{config/rs6000/sysv.h} target file defines:
+@smallexample
+#undef CPP_SPEC
+#define CPP_SPEC \
+"%@{posix: -D_POSIX_SOURCE @} \
+%@{mcall-sysv: -D_CALL_SYSV @} %@{mcall-aix: -D_CALL_AIX @} \
+%@{!mcall-sysv: %@{!mcall-aix: %(cpp_sysv_default) @}@} \
+%@{msoft-float: -D_SOFT_FLOAT@} %@{mcpu=403: -D_SOFT_FLOAT@}"
+
+#undef CPP_SYSV_DEFAULT
+#define CPP_SYSV_DEFAULT "-D_CALL_SYSV"
+@end smallexample
+
+while the @file{config/rs6000/eabiaix.h} target file defines
+@code{CPP_SYSV_DEFAULT} as:
+
+@smallexample
+#undef CPP_SYSV_DEFAULT
+#define CPP_SYSV_DEFAULT "-D_CALL_AIX"
+@end smallexample
+
@findex LINK_LIBGCC_SPECIAL
@item LINK_LIBGCC_SPECIAL
Define this macro if the driver program should find the library
@@ -218,7 +273,7 @@ not affect @samp{-L} options.
Define this macro as a C expression for the initializer of an array of
string to tell the driver program which options are defaults for this
target and thus do not need to be handled specially when using
-@code{MULTILIB_OPTIONS}.
+@code{MULTILIB_OPTIONS}.
Do not define this macro if @code{MULTILIB_OPTIONS} is not defined in
the target makefile fragment or if none of the options listed in
@@ -265,7 +320,7 @@ used, or when the compiler is built as a cross compiler.
@findex INIT_ENVIRONMENT
@item INIT_ENVIRONMENT
-Define this macro as a C string constant if you with to set environment
+Define this macro as a C string constant if you wish to set environment
variables for programs called by the driver, such as the assembler and
loader. The driver passes the value of this macro to @code{putenv} to
initialize the necessary environment variables.
@@ -299,11 +354,17 @@ try when searching for header files.
Cross compilers do not use this macro and do not search either
@file{/usr/include} or its replacement.
+@findex STANDARD_INCLUDE_COMPONENT
+@item STANDARD_INCLUDE_COMPONENT
+The ``component'' corresponding to @code{STANDARD_INCLUDE_DIR}.
+See @code{INCLUDE_DEFAULTS}, below, for the description of components.
+If you do not define this macro, no component is used.
+
@findex INCLUDE_DEFAULTS
@item INCLUDE_DEFAULTS
Define this macro if you wish to override the entire default search path
-for include files. The default search path includes
-@code{GCC_INCLUDE_DIR}, @code{LOCAL_INCLUDE_DIR},
+for include files. For a native compiler, the default search path
+usually consists of @code{GCC_INCLUDE_DIR}, @code{LOCAL_INCLUDE_DIR},
@code{SYSTEM_INCLUDE_DIR}, @code{GPLUSPLUS_INCLUDE_DIR}, and
@code{STANDARD_INCLUDE_DIR}. In addition, @code{GPLUSPLUS_INCLUDE_DIR}
and @code{GCC_INCLUDE_DIR} are defined automatically by @file{Makefile},
@@ -311,19 +372,28 @@ and specify private search areas for GCC. The directory
@code{GPLUSPLUS_INCLUDE_DIR} is used only for C++ programs.
The definition should be an initializer for an array of structures.
-Each array element should have two elements: the directory name (a
-string constant) and a flag for C++-only directories. Mark the end of
-the array with a null element. For example, here is the definition used
-for VMS:
+Each array element should have four elements: the directory name (a
+string constant), the component name, and flag for C++-only directories,
+and a flag showing that the includes in the directory don't need to be
+wrapped in @code{extern @samp{C}} when compiling C++. Mark the end of
+the array with a null element.
+
+The component name denotes what GNU package the include file is part of,
+if any, in all upper-case letters. For example, it might be @samp{GCC}
+or @samp{BINUTILS}. If the package is part of the a vendor-supplied
+operating system, code the component name as @samp{0}.
+
+
+For example, here is the definition used for VAX/VMS:
@example
#define INCLUDE_DEFAULTS \
@{ \
- @{ "GNU_GXX_INCLUDE:", 1@}, \
- @{ "GNU_CC_INCLUDE:", 0@}, \
- @{ "SYS$SYSROOT:[SYSLIB.]", 0@}, \
- @{ ".", 0@}, \
- @{ 0, 0@} \
+ @{ "GNU_GXX_INCLUDE:", "G++", 1, 1@}, \
+ @{ "GNU_CC_INCLUDE:", "GCC", 0, 0@}, \
+ @{ "SYS$SYSROOT:[SYSLIB.]", 0, 0, 0@}, \
+ @{ ".", 0, 0, 0@}, \
+ @{ 0, 0, 0, 0@} \
@}
@end example
@end table
@@ -475,17 +545,17 @@ with opposite meanings, and picks the latter as the default:
@item TARGET_OPTIONS
This macro is similar to @code{TARGET_SWITCHES} but defines names of command
options that have values. Its definition is an initializer with a
-subgrouping for each command option.
+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
@code{char *}, is set to the variable part of the given option if the fixed
part matches. The actual option name is made by appending @samp{-m} to the
-specified name.
+specified name.
Here is an example which defines @samp{-mshort-data-@var{number}}. If the
given option is @samp{-mshort-data-512}, the variable @code{m88k_short_data}
-will be set to the string @code{"512"}.
+will be set to the string @code{"512"}.
@smallexample
extern char *m88k_short_data;
@@ -534,7 +604,7 @@ specified, 1 if @samp{-O} is specified, and 0 if neither is specified.
You should not use this macro to change options that are not
machine-specific. These should uniformly selected by the same
optimization level on all supported machines. Use this macro to enable
-machbine-specific optimizations.
+machine-specific optimizations.
@strong{Do not examine @code{write_symbols} in
this macro!} The debugging options are not supposed to alter the
@@ -632,7 +702,7 @@ you must define @code{POINTERS_EXTEND_UNSIGNED}.
@findex POINTERS_EXTEND_UNSIGNED
@item POINTERS_EXTEND_UNSIGNED
-A C expression whose value is nonzero if pointers that need to be
+A C expression whose value is nonzero if pointers that need to be
extended from being @code{POINTER_SIZE} bits wide to @code{Pmode}
are sign-extended and zero if they are zero-extended.
@@ -665,7 +735,7 @@ Do not define this macro if it would never modify @var{m}.
@findex PROMOTE_FUNCTION_ARGS
@item PROMOTE_FUNCTION_ARGS
Define this macro if the promotion described by @code{PROMOTE_MODE}
-should also be done for outgoing function arguments.
+should also be done for outgoing function arguments.
@findex PROMOTE_FUNCTION_RETURN
@item PROMOTE_FUNCTION_RETURN
@@ -709,12 +779,26 @@ Alignment required for a function entry point, in bits.
@item BIGGEST_ALIGNMENT
Biggest alignment that any data type can require on this machine, in bits.
+@findex MINIMUM_ATOMIC_ALIGNMENT
+@item MINIMUM_ATOMIC_ALIGNMENT
+If defined, the smallest alignment, in bits, that can be given to an
+object that can be referenced in one operation, without disturbing any
+nearby object. Normally, this is @code{BITS_PER_UNIT}, but may be larger
+on machines that don't have byte or half-word store operations.
+
@findex BIGGEST_FIELD_ALIGNMENT
@item BIGGEST_FIELD_ALIGNMENT
Biggest alignment that any structure field can require on this machine,
in bits. If defined, this overrides @code{BIGGEST_ALIGNMENT} for
structure fields only.
+@findex ADJUST_FIELD_ALIGN
+@item ADJUST_FIELD_ALIGN (@var{field}, @var{computed})
+An expression for the alignment of a structure field @var{field} if the
+alignment computed in the usual way is @var{computed}. GNU CC uses
+this value instead of the value in @code{BIGGEST_ALIGNMENT} or
+@code{BIGGEST_FIELD_ALIGNMENT}, if defined, for structure fields only.
+
@findex MAX_OFILE_ALIGNMENT
@item MAX_OFILE_ALIGNMENT
Biggest alignment supported by the object file format of this machine.
@@ -845,7 +929,7 @@ aligning a bitfield within the structure.
@findex ROUND_TYPE_SIZE
@item ROUND_TYPE_SIZE (@var{struct}, @var{size}, @var{align})
-Define this macro as an expression for the overall size of a structure
+Define this macro as an expression for the overall size of a structure
(given by @var{struct} as a tree node) when the size computed from the
fields is @var{size} and the alignment is @var{align}.
@@ -853,7 +937,7 @@ The default is to round @var{size} up to a multiple of @var{align}.
@findex ROUND_TYPE_ALIGN
@item ROUND_TYPE_ALIGN (@var{struct}, @var{computed}, @var{specified})
-Define this macro as an expression for the alignment of a structure
+Define this macro as an expression for the alignment of a structure
(given by @var{struct} as a tree node) if the alignment computed in the
usual way is @var{computed} and the alignment explicitly specified was
@var{specified}.
@@ -913,6 +997,20 @@ supported machines, new codes should be defined for them.
The ordering of the component words of floating point values stored in
memory is controlled by @code{FLOAT_WORDS_BIG_ENDIAN} for the target
machine and @code{HOST_FLOAT_WORDS_BIG_ENDIAN} for the host.
+
+@findex DEFAULT_VTABLE_THUNKS
+@item DEFAULT_VTABLE_THUNKS
+GNU CC supports two ways of implementing C++ vtables: traditional or with
+so-called ``thunks''. The flag @samp{-fvtable-thunk} chooses between them.
+Define this macro to be a C expression for the default value of that flag.
+If @code{DEFAULT_VTABLE_THUNKS} is 0, GNU CC uses the traditional
+implementation by default. The ``thunk'' implementation is more efficient
+(especially if you have provided an implementation of
+@code{ASM_OUTPUT_MI_THUNK}, see @ref{Function Entry}), but is not binary
+compatible with code compiled using the traditional implementation.
+If you are writing a new ports, define @code{DEFAULT_VTABLE_THUNKS} to 1.
+
+If you do not define this macro, the default for @samp{-fvtable-thunk} is 0.
@end table
@node Type Layout
@@ -995,6 +1093,14 @@ A C expression for the size in bits of the type @code{long double} on
the target machine. If you don't define this, the default is two
words.
+@findex WIDEST_HARDWARE_FP_SIZE
+@item WIDEST_HARDWARE_FP_SIZE
+A C expression for the size in bits of the widest floating-point format
+supported by the hardware. If you define this macro, you must specify a
+value less than or equal to the value of @code{LONG_DOUBLE_TYPE_SIZE}.
+If you do not define this macro, the value of @code{LONG_DOUBLE_TYPE_SIZE}
+is the default.
+
@findex DEFAULT_SIGNED_CHAR
@item DEFAULT_SIGNED_CHAR
An expression whose value is 1 or 0, according to whether the type
@@ -1004,7 +1110,7 @@ and @samp{-funsigned-char}.
@findex DEFAULT_SHORT_ENUMS
@item DEFAULT_SHORT_ENUMS
-A C expression to determine whether to give an @code{enum} type
+A C expression to determine whether to give an @code{enum} type
only as many bytes as it takes to represent the range of possible values
of that type. A nonzero value means to do that; a zero value means all
@code{enum} types should be allocated like @code{int}.
@@ -1188,7 +1294,7 @@ on target flags.
You need not define this macro if it has no work to do.
@cindex disabling certain registers
-@cindex controlling register usage
+@cindex controlling register usage
If the usage of an entire class of registers depends on the target
flags, you may indicate this to GCC by using this macro to modify
@code{fixed_regs} and @code{call_used_regs} to 1 for each of the
@@ -1255,7 +1361,7 @@ One use of this macro is on machines where the highest numbered
registers must always be saved and the save-multiple-registers
instruction supports only sequences of consecutive registers. On such
machines, define @code{REG_ALLOC_ORDER} to be an initializer that lists
-the highest numbered allocatable register first.
+the highest numbered allocable register first.
@findex ORDER_REGS_FOR_LOCAL_ALLOC
@item ORDER_REGS_FOR_LOCAL_ALLOC
@@ -1306,30 +1412,21 @@ are equivalent, a suitable definition is
#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
@end smallexample
-It is not necessary for this macro to check for the numbers of fixed
-registers, because the allocation mechanism considers them to be always
-occupied.
+You need not include code to check for the numbers of fixed registers,
+because the allocation mechanism considers them to be always occupied.
@cindex register pairs
On some machines, double-precision values must be kept in even/odd
-register pairs. The way to implement that is to define this macro
-to reject odd register numbers for such modes.
-
-@ignore
-@c I think this is not true now
-GNU CC assumes that it can always move values between registers and
-(suitably addressed) memory locations. If it is impossible to move a
-value of a certain mode between memory and certain registers, then
-@code{HARD_REGNO_MODE_OK} must not allow this mode in those registers.
-@end ignore
+register pairs. You can implement that by defining this macro to reject
+odd register numbers for such modes.
The minimum requirement for a mode to be OK in a register is that the
@samp{mov@var{mode}} instruction pattern support moves between the
-register and any other hard register for which the mode is OK; and that
-moving a value into the register and back out not alter it.
+register and other hard register in the same class and that moving a
+value into the register and back out not alter it.
-Since the same instruction used to move @code{SImode} will work for all
-narrower integer modes, it is not necessary on any machine for
+Since the same instruction used to move @code{word_mode} will work for
+all narrower integer modes, it is not necessary on any machine for
@code{HARD_REGNO_MODE_OK} to distinguish between these modes, provided
you define patterns @samp{movhi}, etc., to take advantage of this. This
is useful because of the interaction between @code{HARD_REGNO_MODE_OK}
@@ -1367,14 +1464,19 @@ be used unless some pattern's constraint asks for one.
@findex MODES_TIEABLE_P
@item MODES_TIEABLE_P (@var{mode1}, @var{mode2})
-A C expression that is nonzero if it is desirable to choose register
-allocation so as to avoid move instructions between a value of mode
-@var{mode1} and a value of mode @var{mode2}.
+A C expression that is nonzero if a value of mode
+@var{mode1} is accessible in mode @var{mode2} without copying.
If @code{HARD_REGNO_MODE_OK (@var{r}, @var{mode1})} and
-@code{HARD_REGNO_MODE_OK (@var{r}, @var{mode2})} are ever different
-for any @var{r}, then @code{MODES_TIEABLE_P (@var{mode1},
-@var{mode2})} must be zero.
+@code{HARD_REGNO_MODE_OK (@var{r}, @var{mode2})} are always the same for
+any @var{r}, then @code{MODES_TIEABLE_P (@var{mode1}, @var{mode2})}
+should be nonzero. If they differ for any @var{r}, you should define
+this macro to return zero unless some other mechanism ensures the
+accessibility of the value in a narrower mode.
+
+You should define this macro to return nonzero in as many cases as
+possible since doing so will allow GNU CC to perform better register
+allocation.
@end table
@node Leaf Functions
@@ -1437,7 +1539,7 @@ treat leaf functions specially. It can test the C variable
@code{leaf_function} is defined only if @code{LEAF_REGISTERS} is
defined.)
@c changed this to fix overfull. ALSO: why the "it" at the beginning
-@c of the next paragraph?! --mew 2feb93
+@c of the next paragraph?! --mew 2feb93
@node Stack Registers
@subsection Registers That Form a Stack
@@ -1475,7 +1577,7 @@ be required to generate correct code for the 80387 coprocessor of the
removed in a later version of the compiler. Don't use them!
@table @code
-@findex OVERLAPPING_REGNO_P
+@findex OVERLAPPING_REGNO_P
@item OVERLAPPING_REGNO_P (@var{regno})
If defined, this is a C expression whose value is nonzero if hard
register number @var{regno} is an overlapping register. This means a
@@ -1504,12 +1606,9 @@ it is best for the RTL expression to show all the activity.
@cindex death notes
@findex PRESERVE_DEATH_INFO_REGNO_P
@item PRESERVE_DEATH_INFO_REGNO_P (@var{regno})
-If defined, this is a C expression whose value is nonzero if accurate
+If defined, this is a C expression whose value is nonzero if correct
@code{REG_DEAD} notes are needed for hard register number @var{regno}
-at the time of outputting the assembler code. When this is so, a few
-optimizations that take place after register allocation and could
-invalidate the death notes are not done when this register is
-involved.
+after reload.
You would arrange to preserve death info for a register when some of the
code in the machine description which is executed to write the assembler
@@ -1518,8 +1617,10 @@ hardware feature which GNU CC thinks of as a register is not actually a
register of the usual sort. (It might, for example, be a hardware
stack.)
+It is also useful for peepholes and linker relaxation.
+
If this macro is not defined, it means that no death notes need to be
-preserved. This is the usual situation.
+preserved, and some may even be incorrect. This is the usual situation.
@end table
@node Register Classes
@@ -1623,7 +1724,7 @@ Then the integers are replaced by sub-initializers, braced groupings containing
several integers. Each sub-initializer must be suitable as an initializer
for the type @code{HARD_REG_SET} which is defined in @file{hard-reg-set.h}.
-@findex REGNO_REG_CLASS
+@findex REGNO_REG_CLASS
@item REGNO_REG_CLASS (@var{regno})
A C expression whose value is a register class containing hard register
@var{regno}. In general there is more than one such class; choose a class
@@ -1659,6 +1760,15 @@ suitable for use as a base register in operand addresses. It may be
either a suitable hard register or a pseudo register that has been
allocated such a hard register.
+@findex REGNO_MODE_OK_FOR_BASE_P
+@item REGNO_MODE_OK_FOR_BASE_P (@var{num}, @var{mode})
+A C expression that is just like @code{REGNO_OK_FOR_BASE_P}, except that
+that expression may examine the mode of the memory reference in
+@var{mode}. You should define this macro if the mode of the memory
+reference affects whether a register may be used as a base register. If
+you define this macro, the compiler will use it instead of
+@code{REGNO_OK_FOR_BASE_P}.
+
@findex REGNO_OK_FOR_INDEX_P
@item REGNO_OK_FOR_INDEX_P (@var{num})
A C expression which is nonzero if register number @var{num} is
@@ -1681,7 +1791,7 @@ A C expression that places additional restrictions on the register class
to use when it is necessary to copy value @var{x} into a register in class
@var{class}. The value is a register class; perhaps @var{class}, or perhaps
another, smaller class. On many machines, the following definition is
-safe:
+safe:
@example
#define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
@@ -1763,7 +1873,7 @@ intermediate register), you should define patterns for
(@pxref{Standard Names}. These patterns, which will normally be
implemented with a @code{define_expand}, should be similar to the
@samp{mov@var{m}} patterns, except that operand 2 is the scratch
-register.
+register.
Define constraints for the reload register and scratch register that
contain a single register class. If the original reload register (whose
@@ -1794,7 +1904,7 @@ those machines to be a C expression that is non-zero if objects of mode
class @var{class2} by storing a register of @var{class1} into memory
and loading that memory location into a register of @var{class2}.
-Do not define this macro if its value would always be zero.
+Do not define this macro if its value would always be zero.
@findex SECONDARY_MEMORY_NEEDED_RTX
@item SECONDARY_MEMORY_NEEDED_RTX (@var{mode})
@@ -1839,16 +1949,17 @@ some machines have so few registers of certain classes that there
would not be enough registers to use as spill registers if this were
done.
-Define @code{SMALL_REGISTER_CLASSES} on these machines. When it is
-defined, the compiler allows registers explicitly used in the rtl to be
-used as spill registers but avoids extending the lifetime of these
-registers.
+Define @code{SMALL_REGISTER_CLASSES} to be an expression with a non-zero
+value on these machines. When this macro has a non-zero value, the
+compiler allows registers explicitly used in the rtl to be used as spill
+registers but avoids extending the lifetime of these registers.
-It is always safe to define this macro, but if you unnecessarily define
-it, you will reduce the amount of optimizations that can be performed in
-some cases. If you do not define this macro when it is required, the
-compiler will run out of spill registers and print a fatal error
-message. For most machines, you should not define this macro.
+It is always safe to define this macro with a non-zero value, but if you
+unnecessarily define it, you will reduce the amount of optimizations
+that can be performed in some cases. If you do not define this macro
+with a non-zero value when it is required, the compiler will run out of
+spill registers and print a fatal error message. For most machines, you
+should not define this macro at all.
@findex CLASS_LIKELY_SPILLED_P
@item CLASS_LIKELY_SPILLED_P (@var{class})
@@ -1900,16 +2011,19 @@ letters.
@table @code
@findex CONST_OK_FOR_LETTER_P
@item CONST_OK_FOR_LETTER_P (@var{value}, @var{c})
-A C expression that defines the machine-dependent operand constraint letters
-that specify particular ranges of integer values. If @var{c} is one
-of those letters, the expression should check that @var{value}, an integer,
-is in the appropriate range and return 1 if so, 0 otherwise. If @var{c} is
-not one of those letters, the value should be 0 regardless of @var{value}.
+A C expression that defines the machine-dependent operand constraint
+letters (@samp{I}, @samp{J}, @samp{K}, @dots{} @samp{P}) that specify
+particular ranges of integer values. If @var{c} is one of those
+letters, the expression should check that @var{value}, an integer, is in
+the appropriate range and return 1 if so, 0 otherwise. If @var{c} is
+not one of those letters, the value should be 0 regardless of
+@var{value}.
@findex CONST_DOUBLE_OK_FOR_LETTER_P
@item CONST_DOUBLE_OK_FOR_LETTER_P (@var{value}, @var{c})
A C expression that defines the machine-dependent operand constraint
-letters that specify particular ranges of @code{const_double} values.
+letters that specify particular ranges of @code{const_double} values
+(@samp{G} or @samp{H}).
If @var{c} is one of those letters, the expression should check that
@var{value}, an RTX of code @code{const_double}, is in the appropriate
@@ -1924,13 +2038,13 @@ between these kinds.
@findex EXTRA_CONSTRAINT
@item EXTRA_CONSTRAINT (@var{value}, @var{c})
A C expression that defines the optional machine-dependent constraint
-letters that can be used to segregate specific types of operands,
-usually memory references, for the target machine. Normally this macro
-will not be defined. If it is required for a particular target machine,
-it should return 1 if @var{value} corresponds to the operand type
-represented by the constraint letter @var{c}. If @var{c} is not defined
-as an extra constraint, the value returned should be 0 regardless of
-@var{value}.
+letters (@item @samp{Q}, @samp{R}, @samp{S}, @samp{T}, @samp{U}) that can
+be used to segregate specific types of operands, usually memory
+references, for the target machine. Normally this macro will not be
+defined. If it is required for a particular target machine, it should
+return 1 if @var{value} corresponds to the operand type represented by
+the constraint letter @var{c}. If @var{c} is not defined as an extra
+constraint, the value returned should be 0 regardless of @var{value}.
For example, on the ROMP, load instructions cannot have their output in r0 if
the memory reference contains a symbolic address. Constraint letter
@@ -1950,8 +2064,9 @@ This describes the stack layout and calling conventions.
@menu
* Frame Layout::
+* Stack Checking::
* Frame Registers::
-* Elimination::
+* Elimination::
* Stack Arguments::
* Register Arguments::
* Scalar Return::
@@ -2013,7 +2128,7 @@ the first location at which outgoing arguments are placed.
@item FIRST_PARM_OFFSET (@var{fundecl})
Offset from the argument pointer register to the first argument's
address. On some machines it may depend on the data type of the
-function.
+function.
If @code{ARGS_GROW_DOWNWARD}, this is the offset to the location above
the first argument's address.
@@ -2049,23 +2164,131 @@ This macro will seldom need to be defined.
@findex RETURN_ADDR_RTX
@item RETURN_ADDR_RTX (@var{count}, @var{frameaddr})
A C expression whose value is RTL representing the value of the return
-address for the frame @var{count} steps up from the current frame.
-@var{frameaddr} is the frame pointer of the @var{count} frame, or
-the frame pointer of the @var{count} @minus{} 1 frame if
+address for the frame @var{count} steps up from the current frame, after
+the prologue. @var{frameaddr} is the frame pointer of the @var{count}
+frame, or the frame pointer of the @var{count} @minus{} 1 frame if
@code{RETURN_ADDR_IN_PREVIOUS_FRAME} is defined.
+The value of the expression must always be the correct address when
+@var{count} is zero, but may be @code{NULL_RTX} if there is not way to
+determine the return address of other frames.
+
@findex RETURN_ADDR_IN_PREVIOUS_FRAME
@item RETURN_ADDR_IN_PREVIOUS_FRAME
Define this if the return address of a particular stack frame is accessed
from the frame pointer of the previous stack frame.
+
+@findex INCOMING_RETURN_ADDR_RTX
+@item INCOMING_RETURN_ADDR_RTX
+A C expression whose value is RTL representing the location of the
+incoming return address at the beginning of any function, before the
+prologue. This RTL is either a @code{REG}, indicating that the return
+value is saved in @samp{REG}, or a @code{MEM} representing a location in
+the stack.
+
+You only need to define this macro if you want to support call frame
+debugging information like that provided by DWARF 2.
+
+@findex INCOMING_FRAME_SP_OFFSET
+@item INCOMING_FRAME_SP_OFFSET
+A C expression whose value is an integer giving the offset, in bytes,
+from the value of the stack pointer register to the top of the stack
+frame at the beginning of any function, before the prologue. The top of
+the frame is defined to be the value of the stack pointer in the
+previous frame, just before the call instruction.
+
+You only need to define this macro if you want to support call frame
+debugging information like that provided by DWARF 2.
+@end table
+
+@node Stack Checking
+@subsection Specifying How Stack Checking is Done
+
+GNU CC will check that stack references are within the boundaries of
+the stack, if the @samp{-fstack-check} is specified, in one of three ways:
+
+@enumerate
+@item
+If the value of the @code{STACK_CHECK_BUILTIN} macro is nonzero, GNU CC
+will assume that you have arranged for stack checking to be done at
+appropriate places in the configuration files, e.g., in
+@code{FUNCTION_PROLOGUE}. GNU CC will do not other special processing.
+
+@item
+If @code{STACK_CHECK_BUILTIN} is zero and you defined a named pattern
+called @code{check_stack} in your @file{md} file, GNU CC will call that
+pattern with one argument which is the address to compare the stack
+value against. You must arrange for this pattern to report an error if
+the stack pointer is out of range.
+
+@item
+If neither of the above are true, GNU CC will generate code to periodically
+``probe'' the stack pointer using the values of the macros defined below.
+@end enumerate
+
+Normally, you will use the default values of these macros, so GNU CC
+will use the third approach.
+
+@table @code
+@findex STACK_CHECK_BUILTIN
+@item STACK_CHECK_BUILTIN
+A nonzero value if stack checking is done by the configuration files in a
+machine-dependent manner. You should define this macro if stack checking
+is require by the ABI of your machine or if you would like to have to stack
+checking in some more efficient way than GNU CC's portable approach.
+The default value of this macro is zero.
+
+@findex STACK_CHECK_PROBE_INTERVAL
+@item STACK_CHECK_PROBE_INTERVAL
+An integer representing the interval at which GNU CC must generate stack
+probe instructions. You will normally define this macro to be no larger
+than the size of the ``guard pages'' at the end of a stack area. The
+default value of 4096 is suitable for most systems.
+
+@findex STACK_CHECK_PROBE_LOAD
+@item STACK_CHECK_PROBE_LOAD
+A integer which is nonzero if GNU CC should perform the stack probe
+as a load instruction and zero if GNU CC should use a store instruction.
+The default is zero, which is the most efficient choice on most systems.
+
+@findex STACK_CHECK_PROTECT
+@item STACK_CHECK_PROTECT
+The number of bytes of stack needed to recover from a stack overflow,
+for languages where such a recovery is supported. The default value of
+75 words should be adequate for most machines.
+
+@findex STACK_CHECK_MAX_FRAME_SIZE
+@item STACK_CHECK_MAX_FRAME_SIZE
+The maximum size of a stack frame, in bytes. GNU CC will generate probe
+instructions in non-leaf functions to ensure at least this many bytes of
+stack are available. If a stack frame is larger than this size, stack
+checking will not be reliable and GNU CC will issue a warning. The
+default is chosen so that GNU CC only generates one instruction on most
+systems. You should normally not change the default value of this macro.
+
+@findex STACK_CHECK_FIXED_FRAME_SIZE
+@item STACK_CHECK_FIXED_FRAME_SIZE
+GNU CC uses this value to generate the above warning message. It
+represents the amount of fixed frame used by a function, not including
+space for any callee-saved registers, temporaries and user variables.
+You need only specify an upper bound for this amount and will normally
+use the default of four words.
+
+@findex STACK_CHECK_MAX_VAR_SIZE
+@item STACK_CHECK_MAX_VAR_SIZE
+The maximum size, in bytes, of an object that GNU CC will place in the
+fixed area of the stack frame when the user specifies
+@samp{-fstack-check}.
+GNU CC computed the default from the values of the above macros and you will
+normally not need to override that default.
@end table
@need 2000
@node Frame Registers
-@subsection Registers That Address the Stack Frame
+@subsection Registers That Address the Stack Frame
@c prevent bad page break with this line
-This discusses registers that address the stack frame.
+This discusses registers that address the stack frame.
@table @code
@findex STACK_POINTER_REGNUM
@@ -2114,6 +2337,18 @@ pointer register, then you must mark it as a fixed register according to
@code{FIXED_REGISTERS}, or arrange to be able to eliminate it
(@pxref{Elimination}).
+@findex RETURN_ADDRESS_POINTER_REGNUM
+@item RETURN_ADDRESS_POINTER_REGNUM
+The register number of the return address pointer register, which is used to
+access the current function's return address from the stack. On some
+machines, the return address is not at a fixed offset from the frame
+pointer or stack pointer or argument pointer. This register can be defined
+to point to the return address on the stack, and then be converted by
+@code{ELIMINABLE_REGS} into either the frame pointer or stack pointer.
+
+Do not define this macro unless there is no other way to get the return
+address from the stack.
+
@findex STATIC_CHAIN_REGNUM
@findex STATIC_CHAIN_INCOMING_REGNUM
@item STATIC_CHAIN_REGNUM
@@ -2371,11 +2606,10 @@ arguments that a function pops on returning, or 0 if the
function pops no arguments and the caller must therefore pop them all
after the function returns.
-@var{fundecl} is a C variable whose value is a tree node that
-describes the function in question. Normally it is a node of type
+@var{fundecl} is a C variable whose value is a tree node that describes
+the function in question. Normally it is a node of type
@code{FUNCTION_DECL} that describes the declaration of the function.
-From this it is possible to obtain the DECL_MACHINE_ATTRIBUTES of
-the function.
+From this you can obtain the DECL_MACHINE_ATTRIBUTES of the function.
@var{funtype} is a C variable whose value is a tree node that
describes the function in question. Normally it is a node of type
@@ -2383,7 +2617,7 @@ describes the function in question. Normally it is a node of type
From this it is possible to obtain the data types of the value and
arguments (if known).
-When a call to a library function is being considered, @var{funtype}
+When a call to a library function is being considered, @var{fundecl}
will contain an identifier node for the library function. Thus, if
you need to distinguish among various library functions, you can do so
by their names. Note that ``library function'' in this context means
@@ -2427,13 +2661,25 @@ the data type of the argument as a tree node or 0 if that is not known
which is 1 for an ordinary argument and 0 for nameless arguments that
correspond to @samp{@dots{}} in the called function's prototype.
-The value of the expression should either be a @code{reg} RTX for the
+The value of the expression is usually either a @code{reg} RTX for the
hard register in which to pass the argument, or zero to pass the
argument on the stack.
For machines like the Vax and 68000, where normally all arguments are
pushed, zero suffices as a definition.
+The value of the expression can also be a @code{parallel} RTX. This is
+used when an argument is passed in multiple locations. The mode of the
+of the @code{parallel} should be the mode of the entire argument. The
+@code{parallel} holds any number of @code{expr_list} pairs; each one
+describes where part of the argument is passed. In each @code{expr_list},
+the first operand can be either a @code{reg} RTX for the hard register
+in which to pass this part of the argument, or zero to pass the argument
+on the stack. If this operand is a @code{reg}, then the mode indicates
+how large this part of the argument is. The second operand of the
+@code{expr_list} is a @code{const_int} which gives the offset in bytes
+into the entire argument where this part starts.
+
@cindex @file{stdarg.h} and register arguments
The usual way to make the ANSI library @file{stdarg.h} work on a machine
where some arguments are usually passed in registers, is to cause
@@ -2500,7 +2746,7 @@ definition of this macro might be
(CUM, MODE, TYPE, NAMED) \
MUST_PASS_IN_STACK (MODE, TYPE)
@end smallexample
-@c this is *still* too long. --mew 5feb93
+@c this is *still* too long. --mew 5feb93
@findex FUNCTION_ARG_CALLEE_COPIES
@item FUNCTION_ARG_CALLEE_COPIES (@var{cum}, @var{mode}, @var{type}, @var{named})
@@ -2528,12 +2774,17 @@ arguments are passed on the stack, there is no need to store anything in
should not be empty, so use @code{int}.
@findex INIT_CUMULATIVE_ARGS
-@item INIT_CUMULATIVE_ARGS (@var{cum}, @var{fntype}, @var{libname})
+@item INIT_CUMULATIVE_ARGS (@var{cum}, @var{fntype}, @var{libname}, @var{indirect})
A C statement (sans semicolon) for initializing the variable @var{cum}
for the state at the beginning of the argument list. The variable has
type @code{CUMULATIVE_ARGS}. The value of @var{fntype} is the tree node
for the data type of the function which will receive the args, or 0
-if the args are to a compiler support library function.
+if the args are to a compiler support library function. The value of
+@var{indirect} is nonzero when processing an indirect call, for example
+a call through a function pointer. The value of @var{indirect} is zero
+for a call to an explicitly named function, a library function call, or when
+@code{INIT_CUMULATIVE_ARGS} is used to find arguments for the function
+being compiled.
When processing a call to a compiler support library function,
@var{libname} identifies which one. It is a @code{symbol_ref} rtx which
@@ -2586,7 +2837,7 @@ constant size shorter than an @code{int}, and upward otherwise.
@findex FUNCTION_ARG_BOUNDARY
@item FUNCTION_ARG_BOUNDARY (@var{mode}, @var{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,
+of an argument with the specified mode and type. If it is not defined,
@code{PARM_BOUNDARY} is used for all arguments.
@findex FUNCTION_ARG_REGNO_P
@@ -2611,7 +2862,7 @@ values---values that can fit in registers.
@table @code
@findex TRADITIONAL_RETURN_FLOAT
@item TRADITIONAL_RETURN_FLOAT
-Define this macro if @samp{-traditional} should not cause functions
+Define this macro if @samp{-traditional} should not cause functions
declared to return @code{float} to convert the value to @code{double}.
@findex FUNCTION_VALUE
@@ -2624,6 +2875,11 @@ On many machines, only the mode is relevant. (Actually, on most
machines, scalar values are returned in the same place regardless of
mode).@refill
+The value of the expression is usually a @code{reg} RTX for the hard
+register where the return value is stored. The value can also be a
+@code{parallel} RTX, if the return value is in multiple places. See
+@code{FUNCTION_ARG} for an explanation of the @code{parallel} form.
+
If @code{PROMOTE_FUNCTION_RETURN} is defined, you must apply the same
promotion rules specified in @code{PROMOTE_MODE} if @var{valtype} is a
scalar type.
@@ -2921,6 +3177,12 @@ frame pointers are maintained. It is never safe to delete a final
stack adjustment in a function that has no frame pointer, and the
compiler knows this regardless of @code{EXIT_IGNORE_STACK}.
+@findex EPILOGUE_USES
+@item EPILOGUE_USES (@var{regno})
+Define this macro as a C expression that is nonzero for registers are
+used by the epilogue or the @samp{return} pattern. The stack and frame
+pointer registers are already be assumed to be used as needed.
+
@findex FUNCTION_EPILOGUE
@item FUNCTION_EPILOGUE (@var{file}, @var{size})
A C compound statement that outputs the assembler code for exit from a
@@ -3000,6 +3262,40 @@ insns in this list, usually by calling @code{final_scan_insn}.
You need not define this macro if you did not define
@code{DELAY_SLOTS_FOR_EPILOGUE}.
+
+@findex ASM_OUTPUT_MI_THUNK
+@item ASM_OUTPUT_MI_THUNK (@var{file}, @var{thunk_fndecl}, @var{delta}, @var{function})
+A C compound statement that outputs the assembler code for a thunk
+function, used to implement C++ virtual function calls with multiple
+inheritance. The thunk acts as a wrapper around a virtual function,
+adjusting the implicit object parameter before handing control off to
+the real function.
+
+First, emit code to add the integer @var{delta} to the location that
+contains the incoming first argument. Assume that this argument
+contains a pointer, and is the one used to pass the @code{this} pointer
+in C++. This is the incoming argument @emph{before} the function prologue,
+e.g. @samp{%o0} on a sparc. The addition must preserve the values of
+all other incoming arguments.
+
+After the addition, emit code to jump to @var{function}, which is a
+@code{FUNCTION_DECL}. This is a direct pure jump, not a call, and does
+not touch the return address. Hence returning from @var{FUNCTION} will
+return to whoever called the current @samp{thunk}.
+
+The effect must be as if @var{function} had been called directly with
+the adjusted first argument. This macro is responsible for emitting all
+of the code for a thunk function; @code{FUNCTION_PROLOGUE} and
+@code{FUNCTION_EPILOGUE} are not invoked.
+
+The @var{thunk_fndecl} is redundant. (@var{delta} and @var{function}
+have already been extracted from it.) It might possibly be useful on
+some targets, but probably not.
+
+If you do not define this macro, the target-independent code in the C++
+frontend will generate a less efficient heavyweight thunk that calls
+@var{function} instead of jumping to it. The generic approach does
+not support varargs.
@end table
@node Profiling
@@ -3009,7 +3305,7 @@ You need not define this macro if you did not define
These macros will help you generate code for profiling.
@table @code
-@findex FUNCTION_PROFILER
+@findex FUNCTION_PROFILER
@item FUNCTION_PROFILER (@var{file}, @var{labelno})
A C statement or compound statement to output to @var{file} some
assembler code to call the profiling subroutine @code{mcount}.
@@ -3032,19 +3328,25 @@ Define this macro if the code for function profiling should come before
the function prologue. Normally, the profiling code comes after.
@findex FUNCTION_BLOCK_PROFILER
-@findex __bb_init_func
+@vindex profile_block_flag
@item FUNCTION_BLOCK_PROFILER (@var{file}, @var{labelno})
A C statement or compound statement to output to @var{file} some
assembler code to initialize basic-block profiling for the current
-object module. This code should call the subroutine
-@code{__bb_init_func} once per object module, passing it as its sole
-argument the address of a block allocated in the object module.
+object module. The global compile flag @code{profile_block_flag}
+distinguishes two profile modes.
+
+@table @code
+@findex __bb_init_func
+@item profile_block_flag != 2
+Output code to call the subroutine @code{__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:
-@example
+@smallexample
ASM_GENERATE_INTERNAL_LABEL (@var{buffer}, "LPBX", 0);
-@end example
+@end smallexample
Of course, since you are writing the definition of
@code{ASM_GENERATE_INTERNAL_LABEL} as well as that of this macro, you
@@ -3053,20 +3355,57 @@ that you know will result.
The first word of this block is a flag which will be nonzero if the
object module has already been initialized. So test this word first,
-and do not call @code{__bb_init_func} if the flag is nonzero.
+and do not call @code{__bb_init_func} if the flag is
+nonzero. BLOCK_OR_LABEL contains a unique number which may be used to
+generate a label as a branch destination when @code{__bb_init_func}
+will not be called.
+
+Described in assembler language, the code to be output looks like:
+
+@example
+ cmp (LPBX0),0
+ bne local_label
+ parameter1 <- LPBX0
+ call __bb_init_func
+local_label:
+@end example
+
+@findex __bb_init_trace_func
+@item profile_block_flag == 2
+Output code to call the subroutine @code{__bb_init_trace_func}
+and pass two parameters to it. The first parameter is the same as
+for @code{__bb_init_func}. The second parameter is the number of the
+first basic block of the function as given by BLOCK_OR_LABEL. Note
+that @code{__bb_init_trace_func} has to be called, even if the object
+module has been initialized already.
+
+Described in assembler language, the code to be output looks like:
+@example
+parameter1 <- LPBX0
+parameter2 <- BLOCK_OR_LABEL
+call __bb_init_trace_func
+@end example
+@end table
@findex BLOCK_PROFILER
+@vindex profile_block_flag
@item BLOCK_PROFILER (@var{file}, @var{blockno})
-A C statement or compound statement to increment the count associated
-with the basic block number @var{blockno}. Basic blocks are numbered
-separately from zero within each compilation. The count associated
-with block number @var{blockno} is at index @var{blockno} in a vector
-of words; the name of this array is a local symbol made with this
-statement:
+A C statement or compound statement to output to @var{file} some
+assembler code to increment the count associated with the basic
+block number @var{blockno}. The global compile flag
+@code{profile_block_flag} distinguishes two profile modes.
-@example
+@table @code
+@item profile_block_flag != 2
+Output code to increment the counter directly. Basic blocks are
+numbered separately from zero within each compilation. The count
+associated with block number @var{blockno} is at index
+@var{blockno} in a vector of words; the name of this array is a local
+symbol made with this statement:
+
+@smallexample
ASM_GENERATE_INTERNAL_LABEL (@var{buffer}, "LPBX", 2);
-@end example
+@end smallexample
@c This paragraph is the same as one a few paragraphs up.
@c That is not an error.
@@ -3075,6 +3414,82 @@ Of course, since you are writing the definition of
can take a short cut in the definition of this macro and use the name
that you know will result.
+Described in assembler language, the code to be output looks like:
+
+@smallexample
+inc (LPBX2+4*BLOCKNO)
+@end smallexample
+
+@vindex __bb
+@findex __bb_trace_func
+@item profile_block_flag == 2
+Output code to initialize the global structure @code{__bb} and
+call the function @code{__bb_trace_func}, which will increment the
+counter.
+
+@code{__bb} consists of two words. In the first word, the current
+basic block number, as given by BLOCKNO, has to be stored. In
+the second word, the address of a block allocated in the object
+module has to be stored. The address is given by the label created
+with this statement:
+
+@smallexample
+ASM_GENERATE_INTERNAL_LABEL (@var{buffer}, "LPBX", 0);
+@end smallexample
+
+Described in assembler language, the code to be output looks like:
+@example
+move BLOCKNO -> (__bb)
+move LPBX0 -> (__bb+4)
+call __bb_trace_func
+@end example
+@end table
+
+@findex FUNCTION_BLOCK_PROFILER_EXIT
+@findex __bb_trace_ret
+@vindex profile_block_flag
+@item FUNCTION_BLOCK_PROFILER_EXIT (@var{file})
+A C statement or compound statement to output to @var{file}
+assembler code to call function @code{__bb_trace_ret}. The
+assembler code should only be output
+if the global compile flag @code{profile_block_flag} == 2. This
+macro has to be used at every place where code for returning from
+a function is generated (e.g. @code{FUNCTION_EPILOGUE}). Although
+you have to write the definition of @code{FUNCTION_EPILOGUE}
+as well, you have to define this macro to tell the compiler, that
+the proper call to @code{__bb_trace_ret} is produced.
+
+@findex MACHINE_STATE_SAVE
+@findex __bb_init_trace_func
+@findex __bb_trace_func
+@findex __bb_trace_ret
+@item MACHINE_STATE_SAVE (@var{id})
+A C statement or compound statement to save all registers, which may
+be clobbered by a function call, including condition codes. The
+@code{asm} statement will be mostly likely needed to handle this
+task. Local labels in the assembler code can be concatenated with the
+string @var{id}, to obtain a unique lable name.
+
+Registers or condition codes clobbered by @code{FUNCTION_PROLOGUE} or
+@code{FUNCTION_EPILOGUE} must be saved in the macros
+@code{FUNCTION_BLOCK_PROFILER}, @code{FUNCTION_BLOCK_PROFILER_EXIT} and
+@code{BLOCK_PROFILER} prior calling @code{__bb_init_trace_func},
+@code{__bb_trace_ret} and @code{__bb_trace_func} respectively.
+
+@findex MACHINE_STATE_RESTORE
+@findex __bb_init_trace_func
+@findex __bb_trace_func
+@findex __bb_trace_ret
+@item MACHINE_STATE_RESTORE (@var{id})
+A C statement or compound statement to restore all registers, including
+condition codes, saved by @code{MACHINE_STATE_SAVE}.
+
+Registers or condition codes clobbered by @code{FUNCTION_PROLOGUE} or
+@code{FUNCTION_EPILOGUE} must be restored in the macros
+@code{FUNCTION_BLOCK_PROFILER}, @code{FUNCTION_BLOCK_PROFILER_EXIT} and
+@code{BLOCK_PROFILER} after calling @code{__bb_init_trace_func},
+@code{__bb_trace_ret} and @code{__bb_trace_func} respectively.
+
@findex BLOCK_PROFILER_CODE
@item BLOCK_PROFILER_CODE
A C function or functions which are needed in the library to
@@ -3121,7 +3536,7 @@ beginning of the function, as opposed to where the call to
This is because the registers must be saved before the function starts
to use them for its own purposes.
@c i rewrote the first sentence above to fix an overfull hbox. --mew
-@c 10feb93
+@c 10feb93
@findex __builtin_args_info
@item __builtin_args_info (@var{category})
@@ -3174,7 +3589,7 @@ The file @file{typeclass.h} defines an enumeration that you can use to
interpret the values of @code{__builtin_classify_type}.
@end table
-These machine description macros help implement varargs:
+These machine description macros help implement varargs:
@table @code
@findex EXPAND_BUILTIN_SAVEREGS
@@ -3195,7 +3610,7 @@ call to the library function @samp{__builtin_saveregs}.
@c more than one line of text... help... --mew 10feb93
@findex SETUP_INCOMING_VARARGS
@item SETUP_INCOMING_VARARGS (@var{args_so_far}, @var{mode}, @var{type},
-@var{pretend_args_size}, @var{second_time})
+@var{pretend_args_size}, @var{second_time})
This macro offers an alternative to using @code{__builtin_saveregs} and
defining the macro @code{EXPAND_BUILTIN_SAVEREGS}. Use it to store the
anonymous register arguments into the stack so that all the arguments
@@ -3276,12 +3691,17 @@ block of data that contains the constant parts of a trampoline. This
code should not include a label---the label is taken care of
automatically.
+If you do not define this macro, it means no template is needed
+for the target. Do not define this macro on systems where the block move
+code to copy the trampoline into place would be larger than the code
+to generate it on the spot.
+
@findex TRAMPOLINE_SECTION
@item TRAMPOLINE_SECTION
The name of a subroutine to switch to the section in which the
trampoline template is to be placed (@pxref{Sections}). The default is
a value of @samp{readonly_data_section}, which places the trampoline in
-the section containing read-only data.
+the section containing read-only data.
@findex TRAMPOLINE_SIZE
@item TRAMPOLINE_SIZE
@@ -3350,7 +3770,7 @@ The total size in bytes of the cache.
The length in bytes of each cache line. The cache is divided into cache
lines which are disjoint slots, each holding a contiguous chunk of data
fetched from memory. Each time data is brought into the cache, an
-entire line is read at once. The data loaded into a cache line is
+entire line is read at once. The data loaded into a cache line is
always aligned on a boundary equal to the line size.
@findex INSN_CACHE_DEPTH
@@ -3369,8 +3789,8 @@ If defined, expands to a C expression clearing the @emph{instruction
cache} in the specified interval. If it is not defined, and the macro
INSN_CACHE_SIZE is defined, some generic code is generated to clear the
cache. The definition of this macro would typically be a series of
-@code{asm} statements. Both @var{BEG} and @var{END} are both pointer
-expressions.
+@code{asm} statements. Both @var{BEG} and @var{END} are both pointer
+expressions.
@end table
To use a standard subroutine, define the following macro. In addition,
@@ -3558,7 +3978,7 @@ traditional C compilers gratuitously convert values declared as
@item INTIFY (@var{float-value})
Define this macro to override the way the value of a
@code{float}-returning library routine should be packaged in order to
-return it. These functions are actually declared to return type
+return it. These functions are actually declared to return type
@code{FLOAT_VALUE_TYPE} (normally @code{int}).
These values can't be returned as type @code{float} because traditional
@@ -3582,7 +4002,7 @@ is.
@findex nongcc_word_type
@item nongcc_word_type
-Define this macro as the name of the data type corresponding to the
+Define this macro as the name of the data type corresponding to the
word_mode in the system's own C compiler.
You need not define this macro if that type is @code{long int}, as it usually
@@ -3725,6 +4145,15 @@ controlled by @code{REG_OK_STRICT} as described above. This usually
requires two variant definitions, of which @code{REG_OK_STRICT}
controls the one actually used.
+@findex REG_MODE_OK_FOR_BASE_P
+@item REG_MODE_OK_FOR_BASE_P (@var{x}, @var{mode})
+A C expression that is just like @code{REG_OK_FOR_BASE_P}, except that
+that expression may examine the mode of the memory reference in
+@var{mode}. You should define this macro if the mode of the memory
+reference affects whether a register may be used as a base register. If
+you define this macro, the compiler will use it instead of
+@code{REG_OK_FOR_BASE_P}.
+
@findex REG_OK_FOR_INDEX_P
@item REG_OK_FOR_INDEX_P (@var{x})
A C expression that is nonzero if @var{x} (assumed to be a @code{reg}
@@ -3915,11 +4344,11 @@ On such machines, define this macro to be a C statement to do any
required conversions. @var{code} is the initial comparison code
and @var{op0} and @var{op1} are the left and right operands of the
comparison, respectively. You should modify @var{code}, @var{op0}, and
-@var{op1} as required.
+@var{op1} as required.
GNU CC will not assume that the comparison resulting from this macro is
valid but will see if the resulting insn matches a pattern in the
-@file{md} file.
+@file{md} file.
You need not define this macro if it would never change the comparison
code or operands.
@@ -3952,7 +4381,7 @@ These macros let you describe the relative speed of various operations
on the target machine.
@table @code
-@findex CONST_COSTS
+@findex CONST_COSTS
@item CONST_COSTS (@var{x}, @var{code}, @var{outer_code})
A part of a C @code{switch} statement that describes the relative costs
of constant RTL expressions. It must contain @code{case} labels for
@@ -3967,7 +4396,7 @@ found in @var{outer_code}.
@var{code} is the expression code---redundant, since it can be
obtained with @code{GET_CODE (@var{x})}.
-@findex RTX_COSTS
+@findex RTX_COSTS
@findex COSTS_N_INSNS
@item RTX_COSTS (@var{x}, @var{code}, @var{outer_code})
Like @code{CONST_COSTS} but applies to nonconstant RTL expressions.
@@ -4026,7 +4455,7 @@ constant.
@item REGISTER_MOVE_COST (@var{from}, @var{to})
A C expression for the cost of moving data from a register in class
@var{from} to one in class @var{to}. The classes are expressed using
-the enumeration values such as @code{GENERAL_REGS}. A value of 4 is the
+the enumeration values such as @code{GENERAL_REGS}. A value of 2 is the
default; other values are interpreted relative to that.
It is not required that the cost always equal 2 when @var{from} is the
@@ -4043,7 +4472,7 @@ if the @samp{mov@var{m}} pattern's constraints do not allow such copying.
@findex MEMORY_MOVE_COST
@item MEMORY_MOVE_COST (@var{m})
A C expression for the cost of moving data of mode @var{m} between a
-register and memory. A value of 2 is the default; this cost is relative
+register and memory. A value of 4 is the default; this cost is relative
to those in @code{REGISTER_MOVE_COST}.
If moving between registers and memory is more expensive than between
@@ -4138,6 +4567,14 @@ based on the relationship between @var{insn} that is dependent on
make no adjustment to @var{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.
+
+@findex ADJUST_PRIORITY
+@item ADJUST_PRIORITY (@var{insn})
+A C statement (sans semicolon) to update the integer scheduling
+priority @code{INSN_PRIORITY(@var{insn})}. Reduce the priority
+to execute the @var{insn} earlier, increase the priority to execute
+@var{insn} later. Do not define this macro if you do not need to
+adjust the scheduling priorities of insns.
@end table
@node Sections
@@ -4171,13 +4608,29 @@ Normally @code{".data"} is right.
@findex SHARED_SECTION_ASM_OP
@item SHARED_SECTION_ASM_OP
-if defined, a C expression whose value is a string containing the
+If defined, a C expression whose value is a string containing the
assembler operation to identify the following data as shared data. If
not defined, @code{DATA_SECTION_ASM_OP} will be used.
+@findex BSS_SECTION_ASM_OP
+@item BSS_SECTION_ASM_OP
+If defined, a C expression whose value is a string containing the
+assembler operation to identify the following data as uninitialized global
+data. If not defined, and neither @code{ASM_OUTPUT_BSS} nor
+@code{ASM_OUTPUT_ALIGNED_BSS} are defined, uninitialized global data will be
+output in the data section if @samp{-fno-common} is passed, otherwise
+@code{ASM_OUTPUT_COMMON} will be used.
+
+@findex SHARED_BSS_SECTION_ASM_OP
+@item SHARED_BSS_SECTION_ASM_OP
+If defined, a C expression whose value is a string containing the
+assembler operation to identify the following data as uninitialized global
+shared data. If not defined, and @code{BSS_SECTION_ASM_OP} is, the latter
+will be used.
+
@findex INIT_SECTION_ASM_OP
@item INIT_SECTION_ASM_OP
-if defined, a C expression whose value is a string containing the
+If defined, a C expression whose value is a string containing the
assembler operation to identify the following data as initialization
code. If not defined, GNU CC will assume such a section does not
exist.
@@ -4264,6 +4717,22 @@ information).
Decode @var{sym_name} and store the real name part in @var{var}, sans
the characters that encode section info. Define this macro if
@code{ENCODE_SECTION_INFO} alters the symbol's name string.
+
+@findex UNIQUE_SECTION_P
+@item UNIQUE_SECTION_P (@var{decl})
+A C expression which evaluates to true if @var{decl} should be placed
+into a unique section for some target-specific reason. If you do not
+define this macro, the default is @samp{0}. Note that the flag
+@samp{-ffunction-sections} will also cause functions to be placed into
+unique sections.
+
+@findex UNIQUE_SECTION
+@item UNIQUE_SECTION (@var{decl}, @var{reloc})
+A C statement to build up a unique section name, expressed as a
+STRING_CST node, and assign it to @samp{DECL_SECTION_NAME (@var{decl})}.
+@var{reloc} indicates whether the initial value of @var{exp} requires
+link-time relocations. If you do not define this macro, GNU CC will use
+the symbol name prefixed by @samp{.} as the section name.
@end table
@node PIC
@@ -4280,7 +4749,7 @@ well as @code{LEGITIMIZE_ADDRESS}. You must modify the definition of
contains a symbolic address. You may also need to alter the handling of
switch statements so that they use relative addresses.
@c i rearranged the order of the macros above to try to force one of
-@c them to the next line, to eliminate an overfull hbox. --mew 10feb93
+@c them to the next line, to eliminate an overfull hbox. --mew 10feb93
@table @code
@findex PIC_OFFSET_TABLE_REGNUM
@@ -4321,8 +4790,8 @@ A C expression that is nonzero if @var{x} is a legitimate immediate
operand on the target machine when generating position independent code.
You can assume that @var{x} satisfies @code{CONSTANT_P}, so you need not
check this. You can also assume @var{flag_pic} is true, so you need not
-check it either. You need not define this macro if all constants
-(including @code{SYMBOL_REF}) can be immediate operands when generating
+check it either. You need not define this macro if all constants
+(including @code{SYMBOL_REF}) can be immediate operands when generating
position independent code.
@end table
@@ -4341,20 +4810,21 @@ instructions do.
* Initialization:: General principles of initialization
and termination routines.
* Macros for Initialization::
- Specific macros that control the handling of
+ Specific macros that control the handling of
initialization and termination routines.
* Instruction Output:: Output of actual instructions.
* Dispatch Tables:: Output of jump tables.
+* Exception Region Output:: Output of exception region code.
* Alignment Output:: Pseudo ops for alignment and skipping data.
@end menu
@node File Framework
-@subsection The Overall Framework of an Assembler File
+@subsection The Overall Framework of an Assembler File
@cindex assembler format
@cindex output of assembler code
@c prevent bad page break with this line
-This describes the overall framework of an assembler file.
+This describes the overall framework of an assembler file.
@table @code
@findex ASM_FILE_START
@@ -4428,6 +4898,14 @@ the stdio stream @var{stream}.
This macro need not be defined if the standard form of output
for the file format in use is appropriate.
+@findex OUTPUT_QUOTED_STRING
+@item OUTPUT_QUOTED_STRING (@var{stream}, @var{name})
+A C statement to output the string @var{string} to the stdio stream
+@var{stream}. If you do not call the function @code{output_quoted_string}
+in your config files, GNU CC will only call it to output filenames to
+the assembler source. So you can use it to canonicalize the format
+of the filename using this macro.
+
@findex ASM_OUTPUT_SOURCE_LINE
@item ASM_OUTPUT_SOURCE_LINE (@var{stream}, @var{line})
A C statement to output DBX or SDB debugging information before code
@@ -4444,10 +4922,12 @@ A C statement to output something to the assembler file to handle a
macro is not defined, nothing is output for a @samp{#ident} directive.
@findex ASM_OUTPUT_SECTION_NAME
-@item ASM_OUTPUT_SECTION_NAME (@var{stream}, @var{decl}, @var{name})
+@item ASM_OUTPUT_SECTION_NAME (@var{stream}, @var{decl}, @var{name}, @var{reloc})
A C statement to output something to the assembler file to switch to section
@var{name} for object @var{decl} which is either a @code{FUNCTION_DECL}, a
-@code{VAR_DECL} or @code{NULL_TREE}. Some target formats do not support
+@code{VAR_DECL} or @code{NULL_TREE}. @var{reloc}
+indicates whether the initial value of @var{exp} requires link-time
+relocations. Some target formats do not support
arbitrary sections. Do not define this macro in such cases.
At present this macro is only used to support section attributes.
@@ -4530,6 +5010,15 @@ If the assembler has a @code{.ascii} pseudo-op as found in the
Berkeley Unix assembler, do not define the macro
@code{ASM_OUTPUT_ASCII}.
+@findex CONSTANT_POOL_BEFORE_FUNCTION
+@item CONSTANT_POOL_BEFORE_FUNCTION
+You may define this macro as a C expression. You should define the
+expression to have a non-zero value if GNU CC should output the constant
+pool for a function before the code for the function, or a zero value if
+GNU CC should output the constant pool after the function. If you do
+not define this macro, the usual case, GNU CC will output the constant
+pool before the function.
+
@findex ASM_OUTPUT_POOL_PROLOGUE
@item ASM_OUTPUT_POOL_PROLOGUE (@var{file} @var{funname} @var{fundecl} @var{size})
A C statement to output assembler commands to define the start of the
@@ -4570,6 +5059,24 @@ entry from being output a second time in the usual manner.
You need not define this macro if it would do nothing.
+@findex CONSTANT_AFTER_FUNCTION_P
+@item CONSTANT_AFTER_FUNCTION_P (@var{exp})
+Define this macro as a C expression which is nonzero if the constant
+@var{exp}, of type @code{tree}, should be output after the code for a
+function. The compiler will normally output all constants before the
+function; you need not define this macro if this is OK.
+
+@findex ASM_OUTPUT_POOL_EPILOGUE
+@item ASM_OUTPUT_POOL_EPILOGUE (@var{file} @var{funname} @var{fundecl} @var{size})
+A C statement to output assembler commands to at the end of the constant
+pool for a function. @var{funname} is a string giving the name of the
+function. Should the return type of the function be required, you can
+obtain it via @var{fundecl}. @var{size} is the size, in bytes, of the
+constant pool that GNU CC wrote immediately before this call.
+
+If no constant-pool epilogue is required, the usual case, you need not
+define this macro.
+
@findex IS_ASM_LOGICAL_LINE_SEPARATOR
@item IS_ASM_LOGICAL_LINE_SEPARATOR (@var{C})
Define this macro as a C expression which is nonzero if @var{C} is
@@ -4645,7 +5152,7 @@ output the name itself; before and after that, output the additional
assembler syntax for defining the name, and a newline.
This macro controls how the assembler definitions of uninitialized
-global variables are output.
+common global variables are output.
@findex ASM_OUTPUT_ALIGNED_COMMON
@item ASM_OUTPUT_ALIGNED_COMMON (@var{stream}, @var{name}, @var{size}, @var{alignment})
@@ -4655,12 +5162,59 @@ place of @code{ASM_OUTPUT_COMMON}, and gives you more flexibility in
handling the required alignment of the variable. The alignment is specified
as the number of bits.
+@findex ASM_OUTPUT_ALIGNED_DECL_COMMON
+@item ASM_OUTPUT_ALIGNED_DECL_COMMON (@var{stream}, @var{decl}, @var{name}, @var{size}, @var{alignment})
+Like @code{ASM_OUTPUT_ALIGNED_COMMON} except that @var{decl} of the
+variable to be output, if there is one, or @code{NULL_TREE} if there
+is not corresponding variable. If you define this macro, GNU CC wil use it
+in place of both @code{ASM_OUTPUT_COMMON} and
+@code{ASM_OUTPUT_ALIGNED_COMMON}. Define this macro when you need to see
+the variable's decl in order to chose what to output.
+
@findex ASM_OUTPUT_SHARED_COMMON
@item ASM_OUTPUT_SHARED_COMMON (@var{stream}, @var{name}, @var{size}, @var{rounded})
If defined, it is similar to @code{ASM_OUTPUT_COMMON}, except that it
is used when @var{name} is shared. If not defined, @code{ASM_OUTPUT_COMMON}
will be used.
+@findex ASM_OUTPUT_BSS
+@item ASM_OUTPUT_BSS (@var{stream}, @var{decl}, @var{name}, @var{size}, @var{rounded})
+A C statement (sans semicolon) to output to the stdio stream
+@var{stream} the assembler definition of uninitialized global @var{decl} named
+@var{name} whose size is @var{size} bytes. The variable @var{rounded}
+is the size rounded up to whatever alignment the caller wants.
+
+Try to use function @code{asm_output_bss} defined in @file{varasm.c} when
+defining this macro. If unable, use the expression
+@code{assemble_name (@var{stream}, @var{name})} to output the name itself;
+before and after that, output the additional assembler syntax for defining
+the name, and a newline.
+
+This macro controls how the assembler definitions of uninitialized global
+variables are output. This macro exists to properly support languages like
+@code{c++} which do not have @code{common} data. However, this macro currently
+is not defined for all targets. If this macro and
+@code{ASM_OUTPUT_ALIGNED_BSS} are not defined then @code{ASM_OUTPUT_COMMON}
+or @code{ASM_OUTPUT_ALIGNED_COMMON} or
+@code{ASM_OUTPUT_ALIGNED_DECL_COMMON} is used.
+
+@findex ASM_OUTPUT_ALIGNED_BSS
+@item ASM_OUTPUT_ALIGNED_BSS (@var{stream}, @var{decl}, @var{name}, @var{size}, @var{alignment})
+Like @code{ASM_OUTPUT_BSS} except takes the required alignment as a
+separate, explicit argument. If you define this macro, it is used in
+place of @code{ASM_OUTPUT_BSS}, and gives you more flexibility in
+handling the required alignment of the variable. The alignment is specified
+as the number of bits.
+
+Try to use function @code{asm_output_aligned_bss} defined in file
+@file{varasm.c} when defining this macro.
+
+@findex ASM_OUTPUT_SHARED_BSS
+@item ASM_OUTPUT_SHARED_BSS (@var{stream}, @var{decl}, @var{name}, @var{size}, @var{rounded})
+If defined, it is similar to @code{ASM_OUTPUT_BSS}, except that it
+is used when @var{name} is shared. If not defined, @code{ASM_OUTPUT_BSS}
+will be used.
+
@findex ASM_OUTPUT_LOCAL
@item ASM_OUTPUT_LOCAL (@var{stream}, @var{name}, @var{size}, @var{rounded})
A C statement (sans semicolon) to output to the stdio stream
@@ -4683,6 +5237,16 @@ place of @code{ASM_OUTPUT_LOCAL}, and gives you more flexibility in
handling the required alignment of the variable. The alignment is specified
as the number of bits.
+@findex ASM_OUTPUT_ALIGNED_DECL_LOCAL
+@item ASM_OUTPUT_ALIGNED_DECL_LOCAL (@var{stream}, @var{decl}, @var{name}, @var{size}, @var{alignment})
+Like @code{ASM_OUTPUT_ALIGNED_DECL} except that @var{decl} of the
+variable to be output, if there is one, or @code{NULL_TREE} if there
+is not corresponding variable. If you define this macro, GNU CC wil use it
+in place of both @code{ASM_OUTPUT_DECL} and
+@code{ASM_OUTPUT_ALIGNED_DECL}. Define this macro when you need to see
+the variable's decl in order to chose what to output.
+
+
@findex ASM_OUTPUT_SHARED_LOCAL
@item ASM_OUTPUT_SHARED_LOCAL (@var{stream}, @var{name}, @var{size}, @var{rounded})
If defined, it is similar to @code{ASM_OUTPUT_LOCAL}, except that it
@@ -4782,6 +5346,27 @@ definition is @samp{1}; otherwise, it is @samp{0}. Define this macro if
you want to control weak symbol support with a compiler flag such as
@samp{-melf}.
+@findex MAKE_DECL_ONE_ONLY (@var{decl})
+@item MAKE_DECL_ONE_ONLY
+A C statement (sans semicolon) to mark @var{decl} to be emitted as a
+public symbol such that extra copies in multiple translation units will
+be discarded by the linker. Define this macro if your object file
+format provides support for this concept, such as the @samp{COMDAT}
+section flags in the Microsoft Windows PE/COFF format, and this support
+requires changes to @var{decl}, such as putting it in a separate section.
+
+@findex SUPPORTS_ONE_ONLY
+@item SUPPORTS_ONE_ONLY
+A C expression which evaluates to true if the target supports one-only
+semantics.
+
+If you don't define this macro, @file{varasm.c} provides a default
+definition. If @code{MAKE_DECL_ONE_ONLY} is defined, the default
+definition is @samp{1}; otherwise, it is @samp{0}. Define this macro if
+you want to control one-only symbol support with a compiler flag, or if
+setting the @code{DECL_ONE_ONLY} flag is enough to mark a declaration to
+be emitted as one-only.
+
@findex ASM_OUTPUT_EXTERNAL
@item ASM_OUTPUT_EXTERNAL (@var{stream}, @var{decl}, @var{name})
A C statement (sans semicolon) to output to the stdio stream
@@ -4883,6 +5468,28 @@ which defines (equates) the symbol @var{name} to have the value @var{value}.
If SET_ASM_OP is defined, a default definition is provided which is
correct for most systems.
+
+@findex ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
+@item ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (@var{stream}, @var{symbol}, @var{high}, @var{low})
+A C statement to output to the stdio stream @var{stream} assembler code
+which defines (equates) the symbol @var{symbol} to have a value equal to
+the difference of the two symbols @var{high} and @var{low}, i.e.
+@var{high} minus @var{low}. GNU CC guarantees that the symbols @var{high}
+and @var{low} are already known by the assembler so that the difference
+resolves into a constant.
+
+If SET_ASM_OP is defined, a default definition is provided which is
+correct for most systems.
+
+@findex ASM_OUTPUT_WEAK_ALIAS
+@item ASM_OUTPUT_WEAK_ALIAS (@var{stream}, @var{name}, @var{value})
+A C statement to output to the stdio stream @var{stream} assembler code
+which defines (equates) the weak symbol @var{name} to have the value
+@var{value}.
+
+Define this macro if the target only supports weak aliases; define
+ASM_OUTPUT_DEF instead if possible.
+
@findex OBJC_GEN_METHOD_LABEL
@item OBJC_GEN_METHOD_LABEL (@var{buf}, @var{is_inst}, @var{class_name}, @var{cat_name}, @var{sel_name})
Define this macro to override the default assembler names used for
@@ -5233,6 +5840,12 @@ writing conditional output routines in those patterns.
If this macro is not defined, it is equivalent to a null statement.
+@findex FINAL_PRESCAN_LABEL
+@item FINAL_PRESCAN_LABEL
+If defined, @code{FINAL_PRESCAN_INSN} will be called on each
+@code{CODE_LABEL}. In that case, @var{opvec} will be a null pointer and
+@var{noperands} will be zero.
+
@findex PRINT_OPERAND
@item PRINT_OPERAND (@var{stream}, @var{x}, @var{code})
A C compound statement to output to stdio stream @var{stream} the
@@ -5321,8 +5934,8 @@ different opcodes), define this macro as a C expression that gives the
numeric index of the assembler language dialect to use, with zero as the
first variant.
-If this macro is defined, you may use
-@samp{@{option0|option1|option2@dots{}@}} constructs in the output
+If this macro is defined, you may use constructs of the form
+@samp{@{option0|option1|option2@dots{}@}} in the output
templates of patterns (@pxref{Output Template}) or in the first argument
of @code{asm_fprintf}. This construct outputs @samp{option0},
@samp{option1} or @samp{option2}, etc., if the value of
@@ -5365,13 +5978,10 @@ This concerns dispatch tables.
@cindex dispatch table
@findex ASM_OUTPUT_ADDR_DIFF_ELT
@item ASM_OUTPUT_ADDR_DIFF_ELT (@var{stream}, @var{value}, @var{rel})
-This macro should be provided on machines where the addresses
-in a dispatch table are relative to the table's own address.
-
-The definition should be a C statement to output to the stdio stream
-@var{stream} an assembler pseudo-instruction to generate a difference
-between two labels. @var{value} and @var{rel} are the numbers of two
-internal labels. The definitions of these labels are output using
+A C statement to output to the stdio stream @var{stream} an assembler
+pseudo-instruction to generate a difference between two labels.
+@var{value} and @var{rel} are the numbers of two internal labels. The
+definitions of these labels are output using
@code{ASM_OUTPUT_INTERNAL_LABEL}, and they must be printed in the same
way here. For example,
@@ -5380,6 +5990,10 @@ fprintf (@var{stream}, "\t.word L%d-L%d\n",
@var{value}, @var{rel})
@end example
+You must provide this macro on machines where the addresses in a
+dispatch table are relative to the table's own address. If defined, GNU
+CC will also use this macro on all machines when producing PIC.
+
@findex ASM_OUTPUT_ADDR_VEC_ELT
@item ASM_OUTPUT_ADDR_VEC_ELT (@var{stream}, @var{value})
This macro should be provided on machines where the addresses
@@ -5422,6 +6036,90 @@ If this macro is not defined, nothing special is output at the end of
the jump-table.
@end table
+@node Exception Region Output
+@subsection Assembler Commands for Exception Regions
+
+@c prevent bad page break with this line
+
+This describes commands marking the start and the end of an exception
+region.
+
+@table @code
+@findex ASM_OUTPUT_EH_REGION_BEG
+@item ASM_OUTPUT_EH_REGION_BEG ()
+A C expression to output text to mark the start of an exception region.
+
+This macro need not be defined on most platforms.
+
+@findex ASM_OUTPUT_EH_REGION_END
+@item ASM_OUTPUT_EH_REGION_END ()
+A C expression to output text to mark the end of an exception region.
+
+This macro need not be defined on most platforms.
+
+@findex EXCEPTION_SECTION
+@item EXCEPTION_SECTION ()
+A C expression to switch to the section in which the main
+exception table is to be placed (@pxref{Sections}). The default is a
+section named @code{.gcc_except_table} on machines that support named
+sections via @code{ASM_OUTPUT_SECTION_NAME}, otherwise if @samp{-fpic}
+or @samp{-fPIC} is in effect, the @code{data_section}, otherwise the
+@code{readonly_data_section}.
+
+@findex EH_FRAME_SECTION_ASM_OP
+@item EH_FRAME_SECTION_ASM_OP
+If defined, a C string constant for the assembler operation to switch to
+the section for exception handling frame unwind information. If not
+defined, GNU CC will provide a default definition if the target supports
+named sections. @file{crtstuff.c} uses this macro to switch to the
+appropriate section.
+
+You should define this symbol if your target supports DWARF 2 frame
+unwind information and the default definition does not work.
+
+@findex OMIT_EH_TABLE
+@item OMIT_EH_TABLE ()
+A C expression that is nonzero if the normal exception table output
+should be omitted.
+
+This macro need not be defined on most platforms.
+
+@findex EH_TABLE_LOOKUP
+@item EH_TABLE_LOOKUP ()
+Alternate runtime support for looking up an exception at runtime and
+finding the associated handler, if the default method won't work.
+
+This macro need not be defined on most platforms.
+
+@findex DOESNT_NEED_UNWINDER
+@item DOESNT_NEED_UNWINDER
+A C expression that decides whether or not the current function needs to
+have a function unwinder generated for it. See the file @code{except.c}
+for details on when to define this, and how.
+
+@findex MASK_RETURN_ADDR
+@item MASK_RETURN_ADDR
+An rtx used to mask the return address found via RETURN_ADDR_RTX, so
+that it does not contain any extraneous set bits in it.
+
+@findex DWARF2_UNWIND_INFO
+@item DWARF2_UNWIND_INFO
+Define this macro to 0 if your target supports DWARF 2 frame unwind
+information, but it does not yet work with exception handling.
+Otherwise, if your target supports this information (if it defines
+@samp{INCOMING_RETURN_ADDR_RTX} and either @samp{UNALIGNED_INT_ASM_OP}
+or @samp{OBJECT_FORMAT_ELF}), GCC will provide a default definition of
+1.
+
+If this macro is defined to 1, the DWARF 2 unwinder will be the default
+exception handling mechanism; otherwise, setjmp/longjmp will be used by
+default.
+
+If this macro is defined to anything, the DWARF 2 unwinder will be used
+instead of inline unwinders and __unwind_function in the non-setjmp case.
+
+@end table
+
@node Alignment Output
@subsection Assembler Commands for Alignment
@@ -5475,7 +6173,7 @@ command to advance the location counter to a multiple of 2 to the
@section Controlling Debugging Information Format
@c prevent bad page break with this line
-This describes how to specify debugging information.
+This describes how to specify debugging information.
@menu
* All Debuggers:: Macros that affect all debugging formats uniformly.
@@ -5533,11 +6231,12 @@ A C expression that returns the type of debugging output GNU CC produces
when the user specifies @samp{-g} or @samp{-ggdb}. Define this if you
have arranged for GNU CC to support more than one format of debugging
output. Currently, the allowable values are @code{DBX_DEBUG},
-@code{SDB_DEBUG}, @code{DWARF_DEBUG}, and @code{XCOFF_DEBUG}.
+@code{SDB_DEBUG}, @code{DWARF_DEBUG}, @code{DWARF2_DEBUG}, and
+@code{XCOFF_DEBUG}.
The value of this macro only affects the default debugging output; the
user can always get a specific type of output by using @samp{-gstabs},
-@samp{-gcoff}, @samp{-gdwarf}, or @samp{-gxcoff}.
+@samp{-gcoff}, @samp{-gdwarf-1}, @samp{-gdwarf-2}, or @samp{-gxcoff}.
@end table
@node DBX Options
@@ -5669,6 +6368,15 @@ first.
Define this macro if the value of a symbol describing the scope of a
block (@code{N_LBRAC} or @code{N_RBRAC}) should be relative to the start
of the enclosing function. Normally, GNU C uses an absolute address.
+
+@findex DBX_USE_BINCL
+@item DBX_USE_BINCL
+Define this macro if GNU C should generate @code{N_BINCL} and
+@code{N_EINCL} stabs for included header files, as on Sun systems. This
+macro also directs GNU C to output a type number as a pair of a file
+number and a type number within the file. Normally, GNU C does not
+generate @code{N_BINCL} or @code{N_EINCL} stabs, and it outputs a single
+number for a type number.
@end table
@node DBX Hooks
@@ -5762,6 +6470,14 @@ Here is another way of finding a particular type:
@}
@end group
@end smallexample
+
+@findex NO_DBX_FUNCTION_END
+@item NO_DBX_FUNCTION_END
+Some stabs encapsulation formats (in particular ECOFF), cannot handle the
+@code{.stabs "",N_FUN,,0,0,Lscope-function-1} gdb dbx extention construct.
+On those machines, define this macro to turn this feature off without
+disturbing the rest of the gdb extensions.
+
@end table
@node File Names and DBX
@@ -5833,9 +6549,20 @@ for SDB in response to the @samp{-g} option.
@findex DWARF_DEBUGGING_INFO
@item DWARF_DEBUGGING_INFO
-Define this macro if GNU CC should produce dwarf format debugging output
+Define this macro if GNU CC should produce dwarf format debugging output
in response to the @samp{-g} option.
+@findex DWARF2_DEBUGGING_INFO
+@item DWARF2_DEBUGGING_INFO
+Define this macro if GNU CC should produce dwarf version 2 format
+debugging output in response to the @samp{-g} option.
+
+To support optional call frame debugging information, you must also
+define @code{INCOMING_RETURN_ADDR_RTX} and either set
+@code{RTX_FRAME_RELATED_P} on the prologue insns if you use RTL for the
+prologue, or call @code{dwarf2out_def_cfa} and @code{dwarf2out_reg_save}
+as appropriate from @code{FUNCTION_PROLOGUE} if you don't.
+
@findex PUT_SDB_@dots{}
@item PUT_SDB_@dots{}
Define these macros to override the assembler syntax for the special
@@ -5873,7 +6600,7 @@ assemblers choke if forward tags are used, while some require it.
@node Cross-compilation
@section Cross Compilation and Floating Point
-@cindex cross compilation and floating point
+@cindex cross compilation and floating point
@cindex floating point and cross compilation
While all modern machines use 2's complement representation for integers,
@@ -6037,11 +6764,13 @@ A macro for a C expression which converts a floating point value
@var{x} into a double-precision integer which is then stored into
@var{low} and @var{high}, two variables of type @var{int}.
-@item REAL_VALUE_FROM_INT (@var{x}, @var{low}, @var{high})
+@item REAL_VALUE_FROM_INT (@var{x}, @var{low}, @var{high}, @var{mode})
@findex REAL_VALUE_FROM_INT
A macro for a C expression which converts a double-precision integer
found in @var{low} and @var{high}, two variables of type @var{int},
into a floating point value which is then stored into @var{x}.
+The value is in the target machine's representation for mode @var{mode}
+and has the type @code{REAL_VALUE_TYPE}.
@end table
@node Misc
@@ -6120,6 +6849,11 @@ value in this case. Do not define this macro if it would always return
@code{NIL}. On machines where this macro is defined, you will normally
define it as the constant @code{SIGN_EXTEND} or @code{ZERO_EXTEND}.
+@findex SHORT_IMMEDIATES_SIGN_EXTEND
+@item SHORT_IMMEDIATES_SIGN_EXTEND
+Define this macro if loading short immediate values into registers sign
+extends.
+
@findex IMPLICIT_FIX_EXPR
@item IMPLICIT_FIX_EXPR
An alias for a tree code that should be used by default for conversion
@@ -6145,14 +6879,15 @@ choice should be made on the basis of efficiency.@refill
@findex MOVE_MAX
@item MOVE_MAX
The maximum number of bytes that a single instruction can move quickly
-from memory to memory.
+between memory and registers or between two memory locations.
@findex MAX_MOVE_MAX
@item MAX_MOVE_MAX
The maximum number of bytes that a single instruction can move quickly
-from memory to memory. If this is undefined, the default is
-@code{MOVE_MAX}. Otherwise, it is the constant value that is the
-largest value that @code{MOVE_MAX} can have at run-time.
+between memory and registers or between two memory locations. If this
+is undefined, the default is @code{MOVE_MAX}. Otherwise, it is the
+constant value that is the largest value that @code{MOVE_MAX} can have
+at run-time.
@findex SHIFT_COUNT_TRUNCATED
@item SHIFT_COUNT_TRUNCATED
@@ -6290,7 +7025,7 @@ Some machines can also perform @code{and} or @code{plus} operations on
condition code values with less instructions than the corresponding
@samp{s@var{cond}} insn followed by @code{and} or @code{plus}. On those
machines, define the appropriate patterns. Use the names @code{incscc}
-and @code{decscc}, respectively, for the the patterns which perform
+and @code{decscc}, respectively, for the patterns which perform
@code{plus} or @code{minus} operations on condition code values. See
@file{rs6000.md} for some examples. The GNU Superoptizer can be used to
find such instruction sequences on other machines.
@@ -6350,11 +7085,12 @@ C++, which is to pretend that the file's contents are enclosed in
@findex HANDLE_PRAGMA
@findex #pragma
@findex pragma
-@item HANDLE_PRAGMA (@var{stream})
+@item HANDLE_PRAGMA (@var{stream}, @var{node})
Define this macro if you want to implement any pragmas. If defined, it
-should be a C statement to be executed when @code{#pragma} is seen. The
-argument @var{stream} is the stdio input stream from which the source
-text can be read.
+is a C expression whose value is 1 if the pragma was handled by the function.
+The argument @var{stream} is the stdio input stream from which the source text
+can be read. @var{node} is the tree node for the identifier after the
+@code{#pragma}.
It is generally a bad idea to implement new uses of @code{#pragma}. The
only reason to define this macro is for compatibility with other
@@ -6388,10 +7124,9 @@ newly defined @var{type}.
@findex DOLLARS_IN_IDENTIFIERS
@item DOLLARS_IN_IDENTIFIERS
Define this macro to control use of the character @samp{$} in identifier
-names. The value should be 0, 1, or 2. 0 means @samp{$} is not allowed
-by default; 1 means it is allowed by default if @samp{-traditional} is
-used; 2 means it is allowed by default provided @samp{-ansi} is not used.
+names. 0 means @samp{$} is not allowed by default; 1 means it is allowed.
1 is the default; there is no need to define this macro in that case.
+This macro controls the compiler proper; it does not affect the preprocessor.
@findex NO_DOLLAR_IN_LABEL
@item NO_DOLLAR_IN_LABEL
@@ -6429,7 +7164,7 @@ and @code{INIT_SECTION_ASM_OP} is not defined, a default
Define this if your @code{exit} function needs to do something
besides calling an external function @code{_cleanup} before
terminating with @code{_exit}. The @code{EXIT_BODY} macro is
-only needed if netiher @code{HAVE_ATEXIT} nor
+only needed if neither @code{HAVE_ATEXIT} nor
@code{INIT_SECTION_ASM_OP} are defined.
@findex INSN_SETS_ARE_DELAYED
@@ -6437,9 +7172,9 @@ only needed if netiher @code{HAVE_ATEXIT} nor
Define this macro as a C expression that is nonzero if it is safe for the
delay slot scheduler to place instructions in the delay slot of @var{insn},
even if they appear to use a resource set or clobbered in @var{insn}.
-@var{insn} is always a @code{jump_insn} or an @code{insn}; GNU CC knows that
-every @code{call_insn} has this behavior. On machines where some @code{insn}
-or @code{jump_insn} is really a function call and hence has this behavior,
+@var{insn} is always a @code{jump_insn} or an @code{insn}; GNU CC knows that
+every @code{call_insn} has this behavior. On machines where some @code{insn}
+or @code{jump_insn} is really a function call and hence has this behavior,
you should define this macro.
You need not define this macro if it would always return zero.
@@ -6448,20 +7183,37 @@ You need not define this macro if it would always return zero.
@item INSN_REFERENCES_ARE_DELAYED (@var{insn})
Define this macro as a C expression that is nonzero if it is safe for the
delay slot scheduler to place instructions in the delay slot of @var{insn},
-even if they appear to set or clobber a resource referenced in @var{insn}.
+even if they appear to set or clobber a resource referenced in @var{insn}.
@var{insn} is always a @code{jump_insn} or an @code{insn}. On machines where
some @code{insn} or @code{jump_insn} is really a function call and its operands
are registers whose use is actually in the subroutine it calls, you should
-define this macro. Doing so allows the delay slot scheduler to move
-instructions which copy arguments into the argument registers into the delay
+define this macro. Doing so allows the delay slot scheduler to move
+instructions which copy arguments into the argument registers into the delay
slot of @var{insn}.
You need not define this macro if it would always return zero.
-@findex MACHINE_DEPENDENT_REORG
-@item MACHINE_DEPENDENT_REORG (@var{insn})
+@findex MACHINE_DEPENDENT_REORG
+@item MACHINE_DEPENDENT_REORG (@var{insn})
In rare cases, correct code generation requires extra machine
dependent processing between the second jump optimization pass and
delayed branch scheduling. On those machines, define this macro as a C
statement to act on the code starting at @var{insn}.
+
+@findex MULTIPLE_SYMBOL_SPACES
+@item MULTIPLE_SYMBOL_SPACES
+Define this macro if in some cases global symbols from one translation
+unit may not be bound to undefined symbols in another translation unit
+without user intervention. For instance, under Microsoft Windows
+symbols must be explicitly imported from shared libraries (DLLs).
+
+@findex GIV_SORT_CRITERION
+@item GIV_SORT_CRITERION (@var{giv1}, @var{giv2})
+In some cases, the strength reduction optimization pass can produce better
+code if this is defined. This macro controls the order that induction
+variables are combined. This macro is particularly useful if the target has
+limited addressing modes. For instance, the SH target has only positive
+offsets in addresses. Thus sorting to put the smallest address first
+allows the most combinations to be found.
+
@end table
diff --git a/gnu/usr.bin/gcc/tree.def b/gnu/usr.bin/gcc/tree.def
index 82404477f2d..bd4b989e426 100644
--- a/gnu/usr.bin/gcc/tree.def
+++ b/gnu/usr.bin/gcc/tree.def
@@ -1,6 +1,6 @@
/* This file contains the definitions and documentation for the
tree codes used in the GNU C compiler.
- Copyright (C) 1987, 1988, 1993, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1993, 1995, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -208,7 +208,9 @@ DEFTREECODE (SET_TYPE, "set_type", "t", 0)
/* Struct in C, or record in Pascal. */
/* Special fields:
- TYPE_FIELDS chain of FIELD_DECLs for the fields of the struct.
+ TYPE_FIELDS chain of FIELD_DECLs for the fields of the struct,
+ and VAR_DECLs, TYPE_DECLs and CONST_DECLs for record-scope variables,
+ types and enumerators.
A few may need to be added for Pascal. */
/* See the comment above, before ENUMERAL_TYPE, for how
forward references to struct tags are handled in C. */
@@ -271,9 +273,9 @@ DEFTREECODE (STRING_CST, "string_cst", "c", 3)
this declaration has its scope. For FIELD_DECLs, this is the
RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node that the field
is a member of. For VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL,
- and CONST_DECL nodes, this points to the FUNCTION_DECL for the
- containing function, or else yields NULL_TREE if the given decl
- has "file scope".
+ and CONST_DECL nodes, this points to either the FUNCTION_DECL for the
+ containing function, the RECORD_TYPE or UNION_TYPE for the containing
+ type, or NULL_TREE if the given decl has "file scope".
DECL_ABSTRACT_ORIGIN, if non-NULL, points to the original (abstract)
..._DECL node of which this decl is an (inlined or template expanded)
instance.
@@ -349,12 +351,6 @@ DEFTREECODE (BIT_FIELD_REF, "bit_field_ref", "r", 3)
/* C unary `*' or Pascal `^'. One operand, an expression for a pointer. */
DEFTREECODE (INDIRECT_REF, "indirect_ref", "r", 1)
-/* 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. */
-DEFTREECODE (OFFSET_REF, "offset_ref", "r", 2)
-
/* Pascal `^` on a file. One operand, an expression for the file. */
DEFTREECODE (BUFFER_REF, "buffer_ref", "r", 1)
@@ -365,19 +361,36 @@ DEFTREECODE (ARRAY_REF, "array_ref", "r", 2)
/* Constructor: return an aggregate value made from specified components.
In C, this is used only for structure and array initializers.
+ Also used for SET_TYPE in Chill (and potentially Pascal).
The first "operand" is really a pointer to the RTL,
for constant constructors only.
The second operand is a list of component values
- made out of a chain of TREE_LIST nodes. */
+ made out of a chain of TREE_LIST nodes.
+
+ For ARRAY_TYPE:
+ The TREE_PURPOSE of each node is the corresponding index.
+ If the TREE_PURPOSE is a RANGE_EXPR, it is a short-hand for many nodes,
+ one for each index in the range. (If the corresponding TREE_VALUE
+ has side-effects, they are evaluated once for each element. Wrap the
+ value in a SAVE_EXPR if you want to evaluate side effects only once.)
+
+ For RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE:
+ The TREE_PURPOSE of each node is a FIELD_DECL.
+
+ For SET_TYPE:
+ The TREE_VALUE specifies a value (index) in the set that is true.
+ If TREE_PURPOSE is non-NULL, it specifies the lower limit of a
+ range of true values. Elements not listed are false (not in the set). */
DEFTREECODE (CONSTRUCTOR, "constructor", "e", 2)
-/* The expression types are mostly straightforward,
- with the fourth argument of DEFTREECODE saying
- how many operands there are.
- Unless otherwise specified, the operands are expressions. */
+/* The expression types are mostly straightforward, with the fourth argument
+ of DEFTREECODE saying how many operands there are.
+ Unless otherwise specified, the operands are expressions and the
+ types of all the operands and the expression must all be the same. */
/* Contains two expressions to compute, one followed by the other.
- the first value is ignored. The second one's value is used. */
+ the first value is ignored. The second one's value is used. The
+ type of the first expression need not agree with the other types. */
DEFTREECODE (COMPOUND_EXPR, "compound_expr", "e", 2)
/* Assignment expression. Operand 0 is the what to set; 1, the new value. */
@@ -389,13 +402,17 @@ DEFTREECODE (INIT_EXPR, "init_expr", "e", 2)
/* For TARGET_EXPR, operand 0 is the target of an initialization,
operand 1 is the initializer for the target,
- and operand 2 is the cleanup for this node, if any. */
-DEFTREECODE (TARGET_EXPR, "target_expr", "e", 3)
+ and operand 2 is the cleanup for this node, if any.
+ and operand 3 is the saved initializer after this node has been
+ expanded once, this is so we can re-expand the tree later. */
+DEFTREECODE (TARGET_EXPR, "target_expr", "e", 4)
/* Conditional expression ( ... ? ... : ... in C).
Operand 0 is the condition.
Operand 1 is the then-value.
- Operand 2 is the else-value. */
+ Operand 2 is the else-value.
+ Operand 0 may be of any types, but the types of operands 1 and 2
+ must be the same and the same as the the of this expression. */
DEFTREECODE (COND_EXPR, "cond_expr", "e", 3)
/* Declare local variables, including making RTL and allocating space.
@@ -441,7 +458,10 @@ DEFTREECODE (METHOD_CALL_EXPR, "method_call_expr", "e", 4)
manages to act on the proper value.
The cleanup is executed by the first enclosing CLEANUP_POINT_EXPR, if
it exists, otherwise it is the responsibility of the caller to manually
- call expand_cleanups_to, as needed. */
+ call expand_start_target_temps/expand_end_target_temps, as needed.
+
+ This differs from TRY_CATCH_EXPR in that operand 2 is always
+ evaluated when an exception isn't thrown when cleanups are run. */
DEFTREECODE (WITH_CLEANUP_EXPR, "with_cleanup_expr", "e", 3)
/* Specify a cleanup point.
@@ -507,17 +527,12 @@ DEFTREECODE (PLACEHOLDER_EXPR, "placeholder_expr", "x", 0)
operand 0. */
DEFTREECODE (WITH_RECORD_EXPR, "with_record_expr", "e", 2)
-/* Simple arithmetic. Operands must have the same machine mode
- and the value shares that mode. */
+/* Simple arithmetic. */
DEFTREECODE (PLUS_EXPR, "plus_expr", "2", 2)
DEFTREECODE (MINUS_EXPR, "minus_expr", "2", 2)
DEFTREECODE (MULT_EXPR, "mult_expr", "2", 2)
/* Division for integer result that rounds the quotient toward zero. */
-/* Operands must have the same machine mode.
- In principle they may be real, but that is not currently supported.
- The result is always fixed point, and it has the same type as the
- operands if they are fixed point. */
DEFTREECODE (TRUNC_DIV_EXPR, "trunc_div_expr", "2", 2)
/* Division for integer result that rounds the quotient toward infinity. */
@@ -535,10 +550,7 @@ DEFTREECODE (CEIL_MOD_EXPR, "ceil_mod_expr", "2", 2)
DEFTREECODE (FLOOR_MOD_EXPR, "floor_mod_expr", "2", 2)
DEFTREECODE (ROUND_MOD_EXPR, "round_mod_expr", "2", 2)
-/* Division for real result. The two operands must have the same type.
- In principle they could be integers, but currently only real
- operands are supported. The result must have the same type
- as the operands. */
+/* Division for real result. */
DEFTREECODE (RDIV_EXPR, "rdiv_expr", "2", 2)
/* Division which is not supposed to need rounding.
@@ -562,7 +574,7 @@ DEFTREECODE (FLOAT_EXPR, "float_expr", "1", 1)
constraints on value type are not known yet. */
DEFTREECODE (EXPON_EXPR, "expon_expr", "2", 2)
-/* Unary negation. Value has same type as operand. */
+/* Unary negation. */
DEFTREECODE (NEGATE_EXPR, "negate_expr", "1", 1)
DEFTREECODE (MIN_EXPR, "min_expr", "2", 2)
@@ -574,10 +586,9 @@ DEFTREECODE (FFS_EXPR, "ffs_expr", "1", 1)
Shift is supposed to mean logical shift if done on an
unsigned type, arithmetic shift on a signed type.
The second operand is the number of bits to
- shift by, and must always have mode SImode.
- The result has the same mode as the first operand. */
-DEFTREECODE (LSHIFT_EXPR, "alshift_expr", "2", 2)
-DEFTREECODE (RSHIFT_EXPR, "arshift_expr", "2", 2)
+ shift by; it need not be the same type as the first operand and result. */
+DEFTREECODE (LSHIFT_EXPR, "lshift_expr", "2", 2)
+DEFTREECODE (RSHIFT_EXPR, "rshift_expr", "2", 2)
DEFTREECODE (LROTATE_EXPR, "lrotate_expr", "2", 2)
DEFTREECODE (RROTATE_EXPR, "rrotate_expr", "2", 2)
@@ -621,7 +632,7 @@ DEFTREECODE (RANGE_EXPR, "range_expr", "2", 2)
/* Represents a conversion of type of a value.
All conversions, including implicit ones, must be
- represented by CONVERT_EXPR nodes. */
+ represented by CONVERT_EXPR or NOP_EXPR nodes. */
DEFTREECODE (CONVERT_EXPR, "convert_expr", "1", 1)
/* Represents a conversion expected to require no code to be generated. */
@@ -636,6 +647,15 @@ DEFTREECODE (NON_LVALUE_EXPR, "non_lvalue_expr", "1", 1)
nonzero only after the expression has been computed. */
DEFTREECODE (SAVE_EXPR, "save_expr", "e", 3)
+/* For a UNSAVE_EXPR, operand 0 is the value to unsave. By unsave, we
+ mean that all _EXPRs such as TARGET_EXPRs, SAVE_EXPRs,
+ CALL_EXPRs and RTL_EXPRs, that are protected
+ from being evaluated more than once should be reset so that a new
+ expand_expr call of this expr will cause those to be re-evaluated.
+ This is useful when we want to reuse a tree in different places,
+ but where we must re-expand. */
+DEFTREECODE (UNSAVE_EXPR, "unsave_expr", "e", 1)
+
/* Represents something whose RTL has already been expanded
as a sequence which should be emitted when this expression is expanded.
The first operand is the RTL to emit. It is the first of a chain of insns.
@@ -657,8 +677,7 @@ DEFTREECODE (ENTRY_VALUE_EXPR, "entry_value_expr", "e", 1)
returns a complex value of the corresponding complex type. */
DEFTREECODE (COMPLEX_EXPR, "complex_expr", "2", 2)
-/* Complex conjugate of operand. Used only on complex types.
- The value has the same type as the operand. */
+/* Complex conjugate of operand. Used only on complex types. */
DEFTREECODE (CONJ_EXPR, "conj_expr", "1", 1)
/* Used only on an operand of complex type, these return
@@ -673,6 +692,24 @@ DEFTREECODE (PREDECREMENT_EXPR, "predecrement_expr", "e", 2)
DEFTREECODE (PREINCREMENT_EXPR, "preincrement_expr", "e", 2)
DEFTREECODE (POSTDECREMENT_EXPR, "postdecrement_expr", "e", 2)
DEFTREECODE (POSTINCREMENT_EXPR, "postincrement_expr", "e", 2)
+
+/* Evaluate operand 1. If and only if an exception is thrown during
+ the evaluation of operand 1, evaluate operand 2.
+
+ This differs from WITH_CLEANUP_EXPR, in that operand 2 is never
+ evaluated unless an exception is throw. */
+DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", "e", 2)
+
+/* Pop the top element off the dynamic handler chain. Used in
+ conjunction with setjmp/longjmp based exception handling, see
+ except.c for more details. This is meant to be used only by the
+ exception handling backend, expand_dhc_cleanup specifically. */
+DEFTREECODE (POPDHC_EXPR, "popdhc_expr", "s", 0)
+
+/* Pop the top element off the dynamic cleanup chain. Used in
+ conjunction with the exception handling. This is meant to be used
+ only by the exception handling backend. */
+DEFTREECODE (POPDCC_EXPR, "popdcc_expr", "s", 0)
/* These types of expressions have no useful value,
and always have side effects. */
@@ -705,6 +742,5 @@ DEFTREECODE (LOOP_EXPR, "loop_expr", "s", 1)
/*
Local variables:
mode:c
-version-control: t
End:
*/
diff --git a/gnu/usr.bin/gcc/tree.h b/gnu/usr.bin/gcc/tree.h
index 1c4b4382354..87d563213b8 100644
--- a/gnu/usr.bin/gcc/tree.h
+++ b/gnu/usr.bin/gcc/tree.h
@@ -1,5 +1,5 @@
/* Front-end tree definitions for GNU compiler.
- Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1989, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -93,10 +93,24 @@ enum built_in_function
BUILT_IN_CONSTANT_P,
BUILT_IN_FRAME_ADDRESS,
BUILT_IN_RETURN_ADDRESS,
+ BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
BUILT_IN_CALLER_RETURN_ADDRESS,
BUILT_IN_APPLY_ARGS,
BUILT_IN_APPLY,
BUILT_IN_RETURN,
+ BUILT_IN_SETJMP,
+ BUILT_IN_LONGJMP,
+
+ /* Various hooks for the DWARF 2 __throw routine. */
+ BUILT_IN_FP, BUILT_IN_SP,
+ BUILT_IN_UNWIND_INIT,
+ BUILT_IN_DWARF_FP_REGNUM,
+ BUILT_IN_DWARF_REG_SIZE,
+ BUILT_IN_FROB_RETURN_ADDR,
+ BUILT_IN_EXTRACT_RETURN_ADDR,
+ BUILT_IN_SET_RETURN_ADDR_REG,
+ BUILT_IN_EH_STUB,
+ BUILT_IN_SET_EH_REGS,
/* C++ extensions */
BUILT_IN_NEW,
@@ -166,9 +180,112 @@ struct tree_common
unsigned lang_flag_4 : 1;
unsigned lang_flag_5 : 1;
unsigned lang_flag_6 : 1;
- /* There is room for two more flags. */
+ /* There is room for three more flags. */
};
+/* The following table lists the uses of each of the above flags and
+ for which types of nodes they are defined. Note that expressions
+ include decls.
+
+ addressable_flag:
+
+ TREE_ADDRESSABLE in
+ VAR_DECL, FUNCTION_DECL, CONSTRUCTOR, LABEL_DECL, ..._TYPE
+ IDENTIFIER_NODE
+
+ static_flag:
+
+ TREE_STATIC in
+ VAR_DECL, FUNCTION_DECL, CONSTRUCTOR
+ TREE_NO_UNUSED_WARNING in
+ CONVERT_EXPR, NOP_EXPR, COMPOUND_EXPR
+ TREE_VIA_VIRTUAL in
+ TREE_LIST or TREE_VEC
+ TREE_CONSTANT_OVERFLOW in
+ INTEGER_CST, REAL_CST, COMPLEX_CST
+ TREE_SYMBOL_REFERENCED in
+ IDENTIFIER_NODE
+
+ public_flag:
+
+ TREE_OVERFLOW in
+ INTEGER_CST, REAL_CST, COMPLEX_CST
+ TREE_PUBLIC in
+ VAR_DECL or FUNCTION_DECL
+ TREE_VIA_PUBLIC in
+ TREE_LIST or TREE_VEC
+
+ private_flag:
+
+ TREE_VIA_PRIVATE in
+ TREE_LIST or TREE_VEC
+ TREE_PRIVATE in
+ ??? unspecified nodes
+
+ protected_flag:
+
+ TREE_VIA_PROTECTED in
+ TREE_LIST
+ TREE_PROTECTED in
+ BLOCK
+ ??? unspecified nodes
+
+ side_effects_flag:
+
+ TREE_SIDE_EFFECTS in
+ all expressions
+
+ volatile_flag:
+
+ TREE_THIS_VOLATILE in
+ all expressions
+ TYPE_VOLATILE in
+ ..._TYPE
+
+ readonly_flag:
+
+ TREE_READONLY in
+ VAR_DECL, PARM_DECL, FIELD_DECL, ..._REF
+ ITERATOR_BOUND_P in
+ VAR_DECL if iterator (C)
+ TYPE_READONLY in
+ ..._TYPE
+
+ constant_flag:
+
+ TREE_CONSTANT in
+ all expressions
+
+ permanent_flag: TREE_PERMANENT in all nodes
+
+ unsigned_flag:
+
+ TREE_UNSIGNED in
+ INTEGER_TYPE, ENUMERAL_TYPE, FIELD_DECL
+ DECL_BUILT_IN_NONANSI in
+ FUNCTION_DECL
+ TREE_PARMLIST in
+ TREE_PARMLIST (C++)
+ SAVE_EXPR_NOPLACEHOLDER in
+ SAVE_EXPR
+
+ asm_written_flag:
+
+ TREE_ASM_WRITTEN in
+ VAR_DECL, FUNCTION_DECL, RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE
+ BLOCK
+
+ used_flag:
+
+ TREE_USED in
+ expressions, IDENTIFIER_NODE
+
+ raises_flag:
+
+ TREE_RAISES in
+ expressions
+
+ */
/* Define accessors for the fields that all tree nodes have
(though some fields are not used for all kinds of nodes). */
@@ -407,6 +524,8 @@ struct tree_common
struct tree_int_cst
{
char common[sizeof (struct tree_common)];
+ struct rtx_def *rtl; /* acts as link to register transfer language
+ (rtl) info */
HOST_WIDE_INT int_cst_low;
HOST_WIDE_INT int_cst_high;
};
@@ -500,6 +619,7 @@ struct tree_vec
/* In a SAVE_EXPR node. */
#define SAVE_EXPR_CONTEXT(NODE) TREE_OPERAND(NODE, 1)
#define SAVE_EXPR_RTL(NODE) (*(struct rtx_def **) &(NODE)->exp.operands[2])
+#define SAVE_EXPR_NOPLACEHOLDER(NODE) TREE_UNSIGNED (NODE)
/* In a RTL_EXPR node. */
#define RTL_EXPR_SEQUENCE(NODE) (*(struct rtx_def **) &(NODE)->exp.operands[0])
@@ -620,6 +740,10 @@ struct tree_block
If set in a SET_TYPE, indicates a bitstring type. */
#define TYPE_STRING_FLAG(NODE) ((NODE)->type.string_flag)
+/* If non-NULL, this is a upper bound of the size (in bytes) of an
+ object of the given ARRAY_TYPE. This allows temporaries to be allocated. */
+#define TYPE_ARRAY_MAX_SIZE(ARRAY_TYPE) TYPE_MAX_VALUE (ARRAY_TYPE)
+
/* Indicates that objects of this type must be initialized by calling a
function when they are created. */
#define TYPE_NEEDS_CONSTRUCTING(NODE) ((NODE)->type.needs_constructing_flag)
@@ -628,7 +752,7 @@ struct tree_block
the same way that the first union alternative would be passed. */
#define TYPE_TRANSPARENT_UNION(NODE) ((NODE)->type.transparent_union_flag)
-/* Indicated that objects of this type should be layed out in as
+/* Indicated that objects of this type should be laid out in as
compact a way as possible. */
#define TYPE_PACKED(NODE) ((NODE)->type.packed_flag)
@@ -771,8 +895,9 @@ struct tree_type
/* For FIELD_DECLs, this is the
RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node that the field is
a member of. For VAR_DECL, PARM_DECL, FUNCTION_DECL, LABEL_DECL,
- and CONST_DECL nodes, this points to the FUNCTION_DECL for the
- containing function, or else yields NULL_TREE if the given decl has "file scope". */
+ and CONST_DECL nodes, this points to either the FUNCTION_DECL for the
+ containing function, the RECORD_TYPE or UNION_TYPE for the containing
+ type, or NULL_TREE if the given decl has "file scope". */
#define DECL_CONTEXT(NODE) ((NODE)->decl.context)
#define DECL_FIELD_CONTEXT(NODE) ((NODE)->decl.context)
/* In a DECL this is the field where configuration dependent machine
@@ -791,6 +916,8 @@ struct tree_type
#define DECL_ARGUMENTS(NODE) ((NODE)->decl.arguments)
/* In FUNCTION_DECL, holds the decl for the return value. */
#define DECL_RESULT(NODE) ((NODE)->decl.result)
+/* For a TYPE_DECL, holds the "original" type. (TREE_TYPE has the copy.) */
+#define DECL_ORIGINAL_TYPE(NODE) ((NODE)->decl.result)
/* In PARM_DECL, holds the type as written (perhaps a function or array). */
#define DECL_ARG_TYPE_AS_WRITTEN(NODE) ((NODE)->decl.result)
/* For a FUNCTION_DECL, holds the tree of BINDINGs.
@@ -856,7 +983,9 @@ struct tree_type
/* For any sort of a ..._DECL node, this points to the original (abstract)
decl node which this decl is an instance of, or else it is NULL indicating
- that this decl is not an instance of some other decl. */
+ that this decl is not an instance of some other decl. For example,
+ in a nested declaration of an inline function, this points back to the
+ definition. */
#define DECL_ABSTRACT_ORIGIN(NODE) ((NODE)->decl.abstract_origin)
/* Nonzero for any sort of ..._DECL node means this decl node represents
@@ -900,12 +1029,16 @@ struct tree_type
#define TYPE_DECL_SUPPRESS_DEBUG(NODE) ((NODE)->decl.external_flag)
-/* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'.
- In LABEL_DECL nodes, nonzero means that an error message about
- jumping into such a binding contour has been printed for this label. */
+/* In VAR_DECL and PARM_DECL nodes, nonzero means declared `register'. */
#define DECL_REGISTER(NODE) ((NODE)->decl.regdecl_flag)
+/* In LABEL_DECL nodes, nonzero means that an error message about
+ jumping into such a binding contour has been printed for this label. */
+#define DECL_ERROR_ISSUED(NODE) ((NODE)->decl.regdecl_flag)
/* In a FIELD_DECL, indicates this field should be bit-packed. */
#define DECL_PACKED(NODE) ((NODE)->decl.regdecl_flag)
+/* In a FUNCTION_DECL with a non-zero DECL_CONTEXT, indicates that a
+ static chain is not needed. */
+#define DECL_NO_STATIC_CHAIN(NODE) ((NODE)->decl.regdecl_flag)
/* Nonzero in a ..._DECL means this variable is ref'd from a nested function.
For VAR_DECL nodes, PARM_DECL nodes, and FUNCTION_DECL nodes.
@@ -962,6 +1095,10 @@ struct tree_type
/* Used to indicate that this DECL has weak linkage. */
#define DECL_WEAK(NODE) ((NODE)->decl.weak_flag)
+/* Used in TREE_PUBLIC decls to indicate that copies of this DECL in
+ multiple translation units should be merged. */
+#define DECL_ONE_ONLY(NODE) ((NODE)->decl.transparent_union)
+
/* Additional flags for language-specific uses. */
#define DECL_LANG_FLAG_0(NODE) ((NODE)->decl.lang_flag_0)
#define DECL_LANG_FLAG_1(NODE) ((NODE)->decl.lang_flag_1)
@@ -977,8 +1114,8 @@ struct tree_decl
char common[sizeof (struct tree_common)];
char *filename;
int linenum;
- union tree_node *size;
unsigned int uid;
+ union tree_node *size;
#ifdef ONLY_INT_FIELDS
int mode : 8;
#else
@@ -1013,6 +1150,15 @@ struct tree_decl
unsigned lang_flag_6 : 1;
unsigned lang_flag_7 : 1;
+ /* For a FUNCTION_DECL, if inline, this is the size of frame needed.
+ If built-in, this is the code for which built-in function.
+ For other kinds of decls, this is DECL_ALIGN. */
+ union {
+ int i;
+ unsigned int u;
+ enum built_in_function f;
+ } frame_size;
+
union tree_node *name;
union tree_node *context;
union tree_node *arguments;
@@ -1024,20 +1170,12 @@ struct tree_decl
union tree_node *machine_attributes;
struct rtx_def *rtl; /* acts as link to register transfer language
(rtl) info */
- /* For a FUNCTION_DECL, if inline, this is the size of frame needed.
- If built-in, this is the code for which built-in function.
- For other kinds of decls, this is DECL_ALIGN. */
- union {
- int i;
- unsigned int u;
- enum built_in_function f;
- } frame_size;
/* For FUNCTION_DECLs: points to insn that constitutes its definition
on the permanent obstack. For any other kind of decl, this is the
alignment. */
union {
struct rtx_def *r;
- int i;
+ HOST_WIDE_INT i;
} saved_insns;
union tree_node *vindex;
/* Points to a structure whose details depend on the language in use. */
@@ -1063,56 +1201,11 @@ union tree_node
struct tree_exp exp;
struct tree_block block;
};
-
-/* Add prototype support. */
-#ifndef PROTO
-#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
-#define PROTO(ARGS) ARGS
-#else
-#define PROTO(ARGS) ()
-#endif
-#endif
-
-#ifndef VPROTO
-#ifdef __STDC__
-#define PVPROTO(ARGS) ARGS
-#define VPROTO(ARGS) ARGS
-#define VA_START(va_list,var) va_start(va_list,var)
-#else
-#define PVPROTO(ARGS) ()
-#define VPROTO(ARGS) (va_alist) va_dcl
-#define VA_START(va_list,var) va_start(va_list)
-#endif
-#endif
-
-#ifndef STDIO_PROTO
-#ifdef BUFSIZ
-#define STDIO_PROTO(ARGS) PROTO(ARGS)
-#else
-#define STDIO_PROTO(ARGS) ()
-#endif
-#endif
+
+#include "gansidecl.h"
#define NULL_TREE (tree) NULL
-/* 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
-#endif
-
-#ifndef NULL_PTR
-#define NULL_PTR ((GENERIC_PTR)0)
-#endif
-
/* The following functions accept a wide integer argument. Rather than
having to cast on every function call, we use a macro instead, that is
defined here and in rtl.h. */
@@ -1133,10 +1226,15 @@ extern char *xmalloc ();
extern char *xrealloc ();
#endif
+extern char *xstrdup PROTO((char *));
+
extern char *oballoc PROTO((int));
extern char *permalloc PROTO((int));
extern char *savealloc PROTO((int));
+extern char *expralloc PROTO((int));
+#ifdef NEED_DECLARATION_FREE
extern void free PROTO((void *));
+#endif
/* Lowest level primitive for allocating a node.
The TREE_CODE is the only argument. Contents are initialized
@@ -1163,6 +1261,12 @@ extern tree make_tree_vec PROTO((int));
extern tree get_identifier PROTO((char *));
+/* If an identifier with the name TEXT (a null-terminated string) has
+ previously been referred to, return that node; otherwise return
+ NULL_TREE. */
+
+extern tree maybe_get_identifier PROTO((char *));
+
/* Construct various types of nodes. */
#define build_int_2(LO,HI) \
@@ -1175,11 +1279,12 @@ extern tree build_parse_node PVPROTO((enum tree_code, ...));
extern tree build_int_2_wide PROTO((HOST_WIDE_INT, HOST_WIDE_INT));
extern tree build_real PROTO((tree, REAL_VALUE_TYPE));
extern tree build_real_from_int_cst PROTO((tree, tree));
-extern tree build_complex PROTO((tree, tree));
+extern tree build_complex PROTO((tree, tree, tree));
extern tree build_string PROTO((int, char *));
extern tree build1 PROTO((enum tree_code, tree, tree));
extern tree build_tree_list PROTO((tree, tree));
extern tree build_decl_list PROTO((tree, tree));
+extern tree build_expr_list PROTO((tree, tree));
extern tree build_decl PROTO((enum tree_code, tree, tree));
extern tree build_block PROTO((tree, tree, tree, tree, tree));
@@ -1228,17 +1333,21 @@ extern tree build_decl_attribute_variant PROTO((tree, tree));
/* Return 1 if an attribute and its arguments are valid for a decl or type. */
-int valid_machine_attribute PROTO((tree, tree, tree, tree));
+extern int valid_machine_attribute PROTO((tree, tree, tree, tree));
/* Given a tree node and a string, return non-zero if the tree node is
a valid attribute name for the string. */
-int is_attribute_p PROTO((char *, tree));
+extern int is_attribute_p PROTO((char *, tree));
/* Given an attribute name and a list of attributes, return the list element
of the attribute or NULL_TREE if not found. */
-tree lookup_attribute PROTO((char *, tree));
+extern tree lookup_attribute PROTO((char *, tree));
+
+/* Given two attributes lists, return a list of their union. */
+
+extern tree merge_attributes PROTO((tree, tree));
/* Given a type node TYPE, and CONSTP and VOLATILEP, return a type
for the same kind of data as TYPE describes.
@@ -1314,6 +1423,7 @@ extern tree perm_tree_cons PROTO((tree, tree, tree));
extern tree temp_tree_cons PROTO((tree, tree, tree));
extern tree saveable_tree_cons PROTO((tree, tree, tree));
extern tree decl_tree_cons PROTO((tree, tree, tree));
+extern tree expr_tree_cons PROTO((tree, tree, tree));
/* Return the last tree node in a chain. */
@@ -1362,6 +1472,17 @@ extern int lvalue_or_else PROTO((tree, char *));
extern tree save_expr PROTO((tree));
+/* unsave_expr (EXP) returns an expression equivalent to EXP but it
+ can be used multiple times and will evaluate EXP, in it's entirety
+ each time. */
+
+extern tree unsave_expr PROTO((tree));
+
+/* unsave_expr_now (EXP) resets EXP in place, so that it can be
+ expanded again. */
+
+extern tree unsave_expr_now PROTO((tree));
+
/* Return 1 if EXP contains a PLACEHOLDER_EXPR; i.e., if it represents a size
or offset that depends on a field within a record.
@@ -1377,12 +1498,6 @@ extern int contains_placeholder_p PROTO((tree));
extern tree substitute_in_expr PROTO((tree, tree, tree));
-/* Given a type T, a FIELD_DECL F, and a replacement value R,
- return a new type with all size expressions that contain F
- updated by replacing the reference to F with R. */
-
-extern tree substitute_in_type PROTO((tree, tree, tree));
-
/* variable_size (EXP) is like save_expr (EXP) except that it
is for the special case of something that is part of a
variable size for a data type. It makes special arrangements
@@ -1455,7 +1570,9 @@ extern tree maybe_build_cleanup PROTO((tree));
look for nested component-refs or array-refs at constant positions
and find the ultimate containing object, which is returned. */
-extern tree get_inner_reference PROTO((tree, int *, int *, tree *, enum machine_mode *, int *, int *));
+extern tree get_inner_reference PROTO((tree, int *, int *, tree *,
+ enum machine_mode *, int *,
+ int *, int *));
/* Return the FUNCTION_DECL which provides this _DECL with its context,
or zero if none. */
@@ -1544,9 +1661,15 @@ extern int current_function_calls_longjmp;
extern int all_types_permanent;
-/* Pointer to function to compute the name to use to print a declaration. */
+/* Pointer to function to compute the name to use to print a declaration.
+ DECL is the declaration in question.
+ VERBOSITY determines what information will be printed:
+ 0: DECL_NAME, demangled as necessary.
+ 1: and scope information.
+ 2: and any other information that might be interesting, such as function
+ parameter types in C++. */
-extern char *(*decl_printable_name) ();
+extern char *(*decl_printable_name) (/* tree decl, int verbosity */);
/* Pointer to function to finish handling an incomplete decl at the
end of compilation. */
@@ -1555,9 +1678,10 @@ extern void (*incomplete_decl_finalize_hook) ();
/* In tree.c */
extern char *perm_calloc PROTO((int, long));
-extern tree get_set_constructor_bits PROTO((tree, char*, int));
+extern tree get_file_function_name PROTO((int));
+extern tree get_set_constructor_bits PROTO((tree, char *, int));
extern tree get_set_constructor_bytes PROTO((tree,
- unsigned char*, int));
+ unsigned char *, int));
/* In stmt.c */
@@ -1589,7 +1713,15 @@ extern void expand_null_return PROTO((void));
extern void expand_return PROTO((tree));
extern void expand_start_bindings PROTO((int));
extern void expand_end_bindings PROTO((tree, int, int));
+extern void start_cleanup_deferral PROTO((void));
+extern void end_cleanup_deferral PROTO((void));
+extern void mark_block_as_eh_region PROTO((void));
+extern void mark_block_as_not_eh_region PROTO((void));
+extern int is_eh_region PROTO((void));
+extern int conditional_context PROTO((void));
extern tree last_cleanup_this_contour PROTO((void));
+extern int expand_dhc_cleanup PROTO((tree));
+extern int expand_dcc_cleanup PROTO((tree));
extern void expand_start_case PROTO((int, tree, tree,
char *));
extern void expand_end_case PROTO((tree));
@@ -1634,6 +1766,52 @@ extern void rrotate_double PROTO((HOST_WIDE_INT, HOST_WIDE_INT,
extern int operand_equal_p PROTO((tree, tree, int));
extern tree invert_truthvalue PROTO((tree));
+/* Interface of the DWARF2 unwind info support. */
+
+/* Decide whether we want to emit frame unwind information for the current
+ translation unit. */
+
+extern int dwarf2out_do_frame PROTO((void));
+
+/* Generate a new label for the CFI info to refer to. */
+
+extern char *dwarf2out_cfi_label PROTO((void));
+
+/* Entry point to update the canonical frame address (CFA). */
+
+extern void dwarf2out_def_cfa PROTO((char *, unsigned, long));
+
+/* Add the CFI for saving a register window. */
+
+extern void dwarf2out_window_save PROTO((char *));
+
+/* Add a CFI to update the running total of the size of arguments pushed
+ onto the stack. */
+
+extern void dwarf2out_args_size PROTO((char *, long));
+
+/* Entry point for saving a register to the stack. */
+
+extern void dwarf2out_reg_save PROTO((char *, unsigned, long));
+
+/* Entry point for saving the return address in the stack. */
+
+extern void dwarf2out_return_save PROTO((char *, long));
+
+/* Entry point for saving the return address in a register. */
+
+extern void dwarf2out_return_reg PROTO((char *, unsigned));
+
+/* Output a marker (i.e. a label) for the beginning of a function, before
+ the prologue. */
+
+extern void dwarf2out_begin_prologue PROTO((void));
+
+/* Output a marker (i.e. a label) for the absolute end of the generated
+ code for a function definition. */
+
+extern void dwarf2out_end_epilogue PROTO((void));
+
/* The language front-end must define these functions. */
/* Function of no arguments for initializing lexical scanning. */
diff --git a/gnu/usr.bin/gcc/varasm.c b/gnu/usr.bin/gcc/varasm.c
index 42b81fa4d86..7f2970fa770 100644
--- a/gnu/usr.bin/gcc/varasm.c
+++ b/gnu/usr.bin/gcc/varasm.c
@@ -1,5 +1,5 @@
/* Output variables, constants and external declarations, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-6, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -26,13 +26,14 @@ Boston, MA 02111-1307, USA. */
We also output the assembler code for constants stored in memory
and are responsible for combining constants with the same value. */
+#include "config.h"
#include <stdio.h>
#include <setjmp.h>
/* #include <stab.h> */
-#include "config.h"
#include "rtl.h"
#include "tree.h"
#include "flags.h"
+#include "except.h"
#include "function.h"
#include "expr.h"
#include "output.h"
@@ -51,10 +52,26 @@ Boston, MA 02111-1307, USA. */
#include <ctype.h>
+#ifndef TRAMPOLINE_ALIGNMENT
+#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
+#endif
+
#ifndef ASM_STABS_OP
#define ASM_STABS_OP ".stabs"
#endif
+/* Define the prefix to use when check_memory_usage_flag is enable. */
+#ifdef NO_DOLLAR_IN_LABEL
+#ifdef NO_DOT_IN_LABEL
+#define CHKR_PREFIX "chkr_prefix_"
+#else /* !NO_DOT_IN_LABEL */
+#define CHKR_PREFIX "chkr."
+#endif
+#else /* !NO_DOLLAR_IN_LABEL */
+#define CHKR_PREFIX "chkr$"
+#endif
+#define CHKR_PREFIX_SIZE (sizeof (CHKR_PREFIX) - 1)
+
/* This macro gets just the user-specified name
out of the string in a SYMBOL_REF. On most machines,
we discard the * if any and that's all. */
@@ -142,17 +159,24 @@ static int compare_constant_rtx PROTO((enum machine_mode, rtx,
static struct constant_descriptor *record_constant_rtx PROTO((enum machine_mode,
rtx));
static struct pool_constant *find_pool_constant PROTO((rtx));
+static void mark_constant_pool PROTO((void));
+static void mark_constants PROTO((rtx));
static int output_addressed_constants PROTO((tree));
+static void output_after_function_constants PROTO((void));
static void bc_assemble_integer PROTO((tree, int));
static void output_constructor PROTO((tree, int));
+static enum in_section { no_section, in_text, in_data, in_named
+#ifdef BSS_SECTION_ASM_OP
+ , in_bss
+#endif
+#ifdef EH_FRAME_SECTION_ASM_OP
+ , in_eh_frame
+#endif
#ifdef EXTRA_SECTIONS
-static enum in_section {no_section, in_text, in_data, in_named, EXTRA_SECTIONS} in_section
- = no_section;
-#else
-static enum in_section {no_section, in_text, in_data, in_named} in_section
- = no_section;
+ , EXTRA_SECTIONS
#endif
+} in_section = no_section;
/* Return a non-zero value if DECL has a section attribute. */
#define IN_NAMED_SECTION(DECL) \
@@ -223,7 +247,7 @@ readonly_data_section ()
#endif
}
-/* Determine if we're in the text section. */
+/* Determine if we're in the text section. */
int
in_text_section ()
@@ -231,37 +255,167 @@ in_text_section ()
return in_section == in_text;
}
+/* Determine if we're in the data section. */
+
+int
+in_data_section ()
+{
+ return in_section == in_data;
+}
+
/* Tell assembler to change to section NAME for DECL.
If DECL is NULL, just switch to section NAME.
- If NAME is NULL, get the name from DECL. */
+ If NAME is NULL, get the name from DECL.
+ If RELOC is 1, the initializer for DECL contains relocs. */
void
-named_section (decl, name)
+named_section (decl, name, reloc)
tree decl;
char *name;
+ int reloc;
{
if (decl != NULL_TREE
- && (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL))
+ && TREE_CODE_CLASS (TREE_CODE (decl)) != 'd')
abort ();
if (name == NULL)
name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
if (in_section != in_named || strcmp (name, in_named_name))
{
- in_named_name = name;
- in_section = in_named;
-
#ifdef ASM_OUTPUT_SECTION_NAME
- ASM_OUTPUT_SECTION_NAME (asm_out_file, decl, name);
+ ASM_OUTPUT_SECTION_NAME (asm_out_file, decl, name, reloc);
#else
/* Section attributes are not supported if this macro isn't provided -
some host formats don't support them at all. The front-end should
already have flagged this as an error. */
abort ();
#endif
+
+ in_named_name = obstack_alloc (&permanent_obstack, strlen (name) + 1);
+ strcpy (in_named_name, name);
+ in_section = in_named;
}
}
+#ifdef ASM_OUTPUT_SECTION_NAME
+#ifndef UNIQUE_SECTION
+#define UNIQUE_SECTION(DECL,RELOC) \
+do { \
+ int len; \
+ char *name, *string; \
+ \
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
+ /* Strip off any encoding in name. */ \
+ STRIP_NAME_ENCODING (name, name); \
+ \
+ len = strlen (name) + 1; \
+ string = alloca (len + 1); \
+ sprintf (string, ".%s", name); \
+ \
+ DECL_SECTION_NAME (DECL) = build_string (len, string); \
+} while (0)
+#endif
+#ifndef UNIQUE_SECTION_P
+#define UNIQUE_SECTION_P(DECL) 0
+#endif
+#endif
+
+#ifdef BSS_SECTION_ASM_OP
+
+/* Tell the assembler to switch to the bss section. */
+
+void
+bss_section ()
+{
+ if (in_section != in_bss)
+ {
+ if (output_bytecode)
+ bc_data ();
+ else
+ {
+#ifdef SHARED_BSS_SECTION_ASM_OP
+ if (flag_shared_data)
+ fprintf (asm_out_file, "%s\n", SHARED_BSS_SECTION_ASM_OP);
+ else
+#endif
+ fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP);
+ }
+
+ in_section = in_bss;
+ }
+}
+
+#ifdef ASM_OUTPUT_BSS
+
+/* Utility function for ASM_OUTPUT_BSS for targets to use if
+ they don't support alignments in .bss.
+ ??? It is believed that this function will work in most cases so such
+ support is localized here. */
+
+static void
+asm_output_bss (file, decl, name, size, rounded)
+ FILE *file;
+ tree decl;
+ char *name;
+ int size, rounded;
+{
+ ASM_GLOBALIZE_LABEL (file, name);
+ bss_section ();
+#ifdef ASM_DECLARE_OBJECT_NAME
+ last_assemble_variable_decl = decl;
+ ASM_DECLARE_OBJECT_NAME (file, name, decl);
+#else
+ /* Standard thing is just output label for the object. */
+ ASM_OUTPUT_LABEL (file, name);
+#endif /* ASM_DECLARE_OBJECT_NAME */
+ ASM_OUTPUT_SKIP (file, rounded);
+}
+
+#endif
+
+#ifdef ASM_OUTPUT_ALIGNED_BSS
+
+/* Utility function for targets to use in implementing
+ ASM_OUTPUT_ALIGNED_BSS.
+ ??? It is believed that this function will work in most cases so such
+ support is localized here. */
+
+static void
+asm_output_aligned_bss (file, decl, name, size, align)
+ FILE *file;
+ tree decl;
+ char *name;
+ int size, align;
+{
+ ASM_GLOBALIZE_LABEL (file, name);
+ bss_section ();
+ ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
+#ifdef ASM_DECLARE_OBJECT_NAME
+ last_assemble_variable_decl = decl;
+ ASM_DECLARE_OBJECT_NAME (file, name, decl);
+#else
+ /* Standard thing is just output label for the object. */
+ ASM_OUTPUT_LABEL (file, name);
+#endif /* ASM_DECLARE_OBJECT_NAME */
+ ASM_OUTPUT_SKIP (file, size ? size : 1);
+}
+
+#endif
+
+#endif /* BSS_SECTION_ASM_OP */
+
+#ifdef EH_FRAME_SECTION_ASM_OP
+void
+eh_frame_section ()
+{
+ if (in_section != in_eh_frame)
+ {
+ fprintf (asm_out_file, "%s\n", EH_FRAME_SECTION_ASM_OP);
+ in_section = in_eh_frame;
+ }
+}
+#endif
+
/* Switch to the section for function DECL.
If DECL is NULL_TREE, switch to the text section.
@@ -274,9 +428,66 @@ function_section (decl)
{
if (decl != NULL_TREE
&& DECL_SECTION_NAME (decl) != NULL_TREE)
- named_section (decl, (char *) 0);
- else
- text_section ();
+ named_section (decl, (char *) 0, 0);
+ else
+ text_section ();
+}
+
+/* Switch to section for variable DECL.
+
+ RELOC is the `reloc' argument to SELECT_SECTION. */
+
+void
+variable_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ if (IN_NAMED_SECTION (decl))
+ named_section (decl, NULL, reloc);
+ else
+ {
+ /* C++ can have const variables that get initialized from constructors,
+ and thus can not be in a readonly section. We prevent this by
+ verifying that the initial value is constant for objects put in a
+ readonly section.
+
+ error_mark_node is used by the C front end to indicate that the
+ initializer has not been seen yet. In this case, we assume that
+ the initializer must be constant.
+
+ C++ uses error_mark_node for variables that have complicated
+ initializers, but these variables go in BSS so we won't be called
+ for them. */
+
+#ifdef SELECT_SECTION
+ SELECT_SECTION (decl, reloc);
+#else
+ if (DECL_READONLY_SECTION (decl, reloc))
+ readonly_data_section ();
+ else
+ data_section ();
+#endif
+ }
+}
+
+/* Tell assembler to switch to the section for the exception handling
+ table. */
+
+void
+exception_section ()
+{
+#if defined (EXCEPTION_SECTION)
+ EXCEPTION_SECTION ();
+#else
+#ifdef ASM_OUTPUT_SECTION_NAME
+ named_section (NULL_TREE, ".gcc_except_table", 0);
+#else
+ if (flag_pic)
+ data_section ();
+ else
+ readonly_data_section ();
+#endif
+#endif
}
/* Create the rtl to represent a function, for a function definition.
@@ -288,6 +499,7 @@ make_function_rtl (decl)
tree decl;
{
char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ char *new_name = name;
if (output_bytecode)
{
@@ -311,6 +523,20 @@ make_function_rtl (decl)
name = obstack_copy0 (saveable_obstack, label, strlen (label));
var_labelno++;
}
+ else
+ {
+ /* When -fprefix-function-name is used, every function name is
+ prefixed. Even static functions are prefixed because they
+ could be declared latter. Note that a nested function name
+ is not prefixed. */
+ if (flag_prefix_function_name)
+ {
+ new_name = (char *) alloca (strlen (name) + CHKR_PREFIX_SIZE + 1);
+ strcpy (new_name, CHKR_PREFIX);
+ strcpy (new_name + CHKR_PREFIX_SIZE, name);
+ name = obstack_copy0 (saveable_obstack, new_name, strlen (new_name));
+ }
+ }
if (DECL_RTL (decl) == 0)
{
@@ -348,9 +574,7 @@ bc_make_decl_rtl (decl, asmspec, top_level)
if (DECL_RTL (decl) == 0)
{
/* Print an error message for register variables. */
- if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL)
- error ("function declared `register'");
- else if (DECL_REGISTER (decl))
+ if (DECL_REGISTER (decl))
error ("global register variables not supported in the interpreter");
/* Handle ordinary static variables and functions. */
@@ -359,7 +583,7 @@ bc_make_decl_rtl (decl, asmspec, top_level)
/* Can't use just the variable's own name for a variable
whose scope is less than the whole file.
Concatenate a distinguishing number. */
- if (!top_level && !DECL_EXTERNAL (decl) && asmspec == 0)
+ if (!top_level && !TREE_PUBLIC (decl) && asmspec == 0)
{
char *label;
@@ -492,30 +716,34 @@ make_decl_rtl (decl, asmspec, top_level)
DECL_RTL (decl) = 0;
/* First detect errors in declaring global registers. */
- if (DECL_REGISTER (decl) && reg_number == -1)
+ if (TREE_CODE (decl) != FUNCTION_DECL
+ && DECL_REGISTER (decl) && reg_number == -1)
error_with_decl (decl,
"register name not specified for `%s'");
- else if (DECL_REGISTER (decl) && reg_number < 0)
+ else if (TREE_CODE (decl) != FUNCTION_DECL
+ && DECL_REGISTER (decl) && reg_number < 0)
error_with_decl (decl,
"invalid register name for `%s'");
- else if ((reg_number >= 0 || reg_number == -3) && ! DECL_REGISTER (decl))
+ else if ((reg_number >= 0 || reg_number == -3)
+ && (TREE_CODE (decl) == FUNCTION_DECL
+ && ! DECL_REGISTER (decl)))
error_with_decl (decl,
"register name given for non-register variable `%s'");
- else if (DECL_REGISTER (decl) && TREE_CODE (decl) == FUNCTION_DECL)
- error ("function declared `register'");
- else if (DECL_REGISTER (decl) && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
- error_with_decl (decl, "data type of `%s' isn't suitable for a register");
- else if (DECL_REGISTER (decl)
- && ! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
- error_with_decl (decl, "register number for `%s' isn't suitable for the data type");
+ else if (TREE_CODE (decl) != FUNCTION_DECL
+ && DECL_REGISTER (decl)
+ && TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
+ error_with_decl (decl,
+ "data type of `%s' isn't suitable for a register");
+ else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)
+ && ! HARD_REGNO_MODE_OK (reg_number,
+ TYPE_MODE (TREE_TYPE (decl))))
+ error_with_decl (decl,
+ "register number for `%s' isn't suitable for data type");
/* Now handle properly declared static register variables. */
- else if (DECL_REGISTER (decl))
+ else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
{
int nregs;
-#if 0 /* yylex should print the warning for this */
- if (pedantic)
- pedwarn ("ANSI C forbids global register variables");
-#endif
+
if (DECL_INITIAL (decl) != 0 && top_level)
{
DECL_INITIAL (decl) = 0;
@@ -547,24 +775,13 @@ make_decl_rtl (decl, asmspec, top_level)
globalize_reg (reg_number + --nregs);
}
}
- /* Specifying a section attribute on an uninitialized variable does not
- (and cannot) cause it to be put in the given section. The linker
- can only put initialized objects in specific sections, everything
- else goes in bss for the linker to sort out later (otherwise the
- linker would give a duplicate definition error for each compilation
- unit that behaved thusly). So warn the user. */
+ /* Specifying a section attribute on a variable forces it into a
+ non-.bss section, and thus it cannot be common. */
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_SECTION_NAME (decl) != NULL_TREE
&& DECL_INITIAL (decl) == NULL_TREE
- && DECL_COMMON (decl)
- && ! flag_no_common)
- {
- warning_with_decl (decl,
- "section attribute ignored for uninitialized variable `%s'");
- /* Remove the section name so subsequent declarations won't see it.
- We are ignoring it, remember. */
- DECL_SECTION_NAME (decl) = NULL_TREE;
- }
+ && DECL_COMMON (decl))
+ DECL_COMMON (decl) = 0;
/* Now handle ordinary static variables and functions (in memory).
Also handle vars declared register invalidly. */
@@ -573,7 +790,7 @@ make_decl_rtl (decl, asmspec, top_level)
/* Can't use just the variable's own name for a variable
whose scope is less than the whole file.
Concatenate a distinguishing number. */
- if (!top_level && !DECL_EXTERNAL (decl) && asmspec == 0)
+ if (!top_level && !TREE_PUBLIC (decl) && asmspec == 0)
{
char *label;
@@ -585,6 +802,20 @@ make_decl_rtl (decl, asmspec, top_level)
if (name == 0)
abort ();
+ /* When -fprefix-function-name is used, the functions
+ names are prefixed. Only nested function names are not
+ prefixed. */
+ if (flag_prefix_function_name && TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ char *new_name;
+ new_name = (char *) alloca (strlen (name) + CHKR_PREFIX_SIZE
+ + 1);
+ strcpy (new_name, CHKR_PREFIX);
+ strcpy (new_name + CHKR_PREFIX_SIZE, name);
+ name = obstack_copy0 (saveable_obstack,
+ new_name, strlen (new_name));
+ }
+
DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl),
gen_rtx (SYMBOL_REF, Pmode, name));
@@ -751,6 +982,16 @@ assemble_gc_entry (name)
#endif
}
+/* CONSTANT_POOL_BEFORE_FUNCTION may be defined as an expression with
+ a non-zero value if the constant pool should be output before the
+ start of the function, or a zero value if the pool should output
+ after the end of the function. The default is to put it before the
+ start. */
+
+#ifndef CONSTANT_POOL_BEFORE_FUNCTION
+#define CONSTANT_POOL_BEFORE_FUNCTION 1
+#endif
+
/* Output assembler code for the constant pool of a function and associated
with defining the name of the function. DECL describes the function.
NAME is the function's name. For the constant pool, we use the current
@@ -767,7 +1008,17 @@ assemble_start_function (decl, fnname)
app_disable ();
- output_constant_pool (fnname, decl);
+ if (CONSTANT_POOL_BEFORE_FUNCTION)
+ output_constant_pool (fnname, decl);
+
+#ifdef ASM_OUTPUT_SECTION_NAME
+ /* If the function is to be put in its own section and it's not in a section
+ already, indicate so. */
+ if ((flag_function_sections
+ && DECL_SECTION_NAME (decl) == NULL_TREE)
+ || UNIQUE_SECTION_P (decl))
+ UNIQUE_SECTION (decl, 0);
+#endif
function_section (decl);
@@ -801,7 +1052,8 @@ assemble_start_function (decl, fnname)
if (TREE_PUBLIC (decl))
{
- if (!first_global_object_name)
+ if (!first_global_object_name && ! DECL_WEAK (decl)
+ && ! DECL_ONE_ONLY (decl))
{
char *p;
@@ -822,15 +1074,17 @@ assemble_start_function (decl, fnname)
}
/* Do any machine/system dependent processing of the function name */
-#ifdef ASM_DECLARE_FUNCTION_NAME
- ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
-#else
- /* Standard thing is just output label for the function. */
if (output_bytecode)
BC_OUTPUT_LABEL (asm_out_file, fnname);
else
- ASM_OUTPUT_LABEL (asm_out_file, fnname);
+ {
+#ifdef ASM_DECLARE_FUNCTION_NAME
+ ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
+#else
+ /* Standard thing is just output label for the function. */
+ ASM_OUTPUT_LABEL (asm_out_file, fnname);
#endif /* ASM_DECLARE_FUNCTION_NAME */
+ }
}
/* Output assembler code associated with defining the size of the
@@ -844,6 +1098,14 @@ assemble_end_function (decl, fnname)
#ifdef ASM_DECLARE_FUNCTION_SIZE
ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
#endif
+ if (! CONSTANT_POOL_BEFORE_FUNCTION)
+ {
+ output_constant_pool (fnname, decl);
+ function_section (decl); /* need to switch back */
+ }
+
+ /* Output any constants which should appear after the function. */
+ output_after_function_constants ();
}
/* Assemble code to leave SIZE bytes of zeros. */
@@ -1066,14 +1328,18 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
if (! dont_output_data)
{
+ int size;
+
if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
goto finish;
/* This is better than explicit arithmetic, since it avoids overflow. */
size_tree = size_binop (CEIL_DIV_EXPR,
- DECL_SIZE (decl), size_int (BITS_PER_UNIT));
+ DECL_SIZE (decl), size_int (BITS_PER_UNIT));
- if (TREE_INT_CST_HIGH (size_tree) != 0)
+ size = TREE_INT_CST_LOW (size_tree);
+ if (TREE_INT_CST_HIGH (size_tree) != 0
+ || size != TREE_INT_CST_LOW (size_tree))
{
error_with_decl (decl, "size of variable `%s' is too large");
goto finish;
@@ -1082,23 +1348,33 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ if (TREE_PUBLIC (decl) && DECL_NAME (decl)
+ && ! first_global_object_name
+ && ! (DECL_COMMON (decl) && (DECL_INITIAL (decl) == 0
+ || DECL_INITIAL (decl) == error_mark_node))
+ && ! DECL_WEAK (decl)
+ && ! DECL_ONE_ONLY (decl))
+ {
+ char *p;
+
+ STRIP_NAME_ENCODING (p, name);
+ first_global_object_name = permalloc (strlen (p) + 1);
+ strcpy (first_global_object_name, p);
+ }
+
/* Handle uninitialized definitions. */
- /* 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))
+ if ((DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
+ /* If the target can't output uninitialized but not common global data
+ in .bss, then we have to use .data. */
+#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
&& DECL_COMMON (decl)
- && ! dont_output_data
- && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+#endif
+ && ! dont_output_data)
{
int size = TREE_INT_CST_LOW (size_tree);
int rounded = size;
- if (TREE_INT_CST_HIGH (size_tree) != 0)
- error_with_decl (decl, "size of variable `%s' is too large");
/* Don't allocate zero bytes of common,
since that means "undefined external" in the linker. */
if (size == 0) rounded = 1;
@@ -1129,11 +1405,17 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
while we are doing our final traversal of the chain of file-scope
declarations. */
-#if 0
+#if 0 /* ??? We should either delete this or add a comment describing what
+ it was intended to do and why we shouldn't delete it. */
if (flag_shared_data)
data_section ();
#endif
- if (TREE_PUBLIC (decl))
+
+ if (TREE_PUBLIC (decl)
+#if defined (ASM_OUTPUT_BSS) || defined (ASM_OUTPUT_ALIGNED_BSS)
+ && DECL_COMMON (decl)
+#endif
+ )
{
#ifdef ASM_OUTPUT_SHARED_COMMON
if (flag_shared_data)
@@ -1146,14 +1428,42 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
}
else
{
+#ifdef ASM_OUTPUT_ALIGNED_DECL_COMMON
+ ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name, size,
+ DECL_ALIGN (decl));
+#else
#ifdef ASM_OUTPUT_ALIGNED_COMMON
ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
DECL_ALIGN (decl));
#else
ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
#endif
+#endif
+ }
+ }
+#if defined (ASM_OUTPUT_BSS) || defined (ASM_OUTPUT_ALIGNED_BSS)
+ else if (TREE_PUBLIC (decl))
+ {
+#ifdef ASM_OUTPUT_SHARED_BSS
+ if (flag_shared_data)
+ ASM_OUTPUT_SHARED_BSS (asm_out_file, decl, name, size, rounded);
+ else
+#endif
+ if (output_bytecode)
+ {
+ BC_OUTPUT_BSS (asm_out_file, name, size, rounded);
+ }
+ else
+ {
+#ifdef ASM_OUTPUT_ALIGNED_BSS
+ ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size,
+ DECL_ALIGN (decl));
+#else
+ ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded);
+#endif
}
}
+#endif /* ASM_OUTPUT_BSS || ASM_OUTPUT_ALIGNED_BSS */
else
{
#ifdef ASM_OUTPUT_SHARED_LOCAL
@@ -1167,31 +1477,29 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
}
else
{
+#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
+ ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, decl, name, size,
+ DECL_ALIGN (decl));
+#else
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
DECL_ALIGN (decl));
#else
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
#endif
+#endif
}
}
goto finish;
}
- /* Handle initialized definitions. */
+ /* Handle initialized definitions.
+ Also handle uninitialized global definitions if -fno-common and the
+ target doesn't support ASM_OUTPUT_BSS. */
/* First make the assembler name(s) global if appropriate. */
if (TREE_PUBLIC (decl) && DECL_NAME (decl))
{
- if (!first_global_object_name)
- {
- char *p;
-
- STRIP_NAME_ENCODING (p, name);
- first_global_object_name = permalloc (strlen (p) + 1);
- strcpy (first_global_object_name, p);
- }
-
#ifdef ASM_WEAKEN_LABEL
if (DECL_WEAK (decl))
ASM_WEAKEN_LABEL (asm_out_file, name);
@@ -1215,33 +1523,13 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
else if (DECL_INITIAL (decl))
reloc = output_addressed_constants (DECL_INITIAL (decl));
- /* Switch to the proper section for this data. */
- if (IN_NAMED_SECTION (decl))
- named_section (decl, NULL);
- else
- {
- /* C++ can have const variables that get initialized from constructors,
- and thus can not be in a readonly section. We prevent this by
- verifying that the initial value is constant for objects put in a
- readonly section.
-
- error_mark_node is used by the C front end to indicate that the
- initializer has not been seen yet. In this case, we assume that
- the initializer must be constant. */
-#ifdef SELECT_SECTION
- SELECT_SECTION (decl, reloc);
-#else
- if (TREE_READONLY (decl)
- && ! TREE_THIS_VOLATILE (decl)
- && DECL_INITIAL (decl)
- && (DECL_INITIAL (decl) == error_mark_node
- || TREE_CONSTANT (DECL_INITIAL (decl)))
- && ! (flag_pic && reloc))
- readonly_data_section ();
- else
- data_section ();
+#ifdef ASM_OUTPUT_SECTION_NAME
+ if (UNIQUE_SECTION_P (decl))
+ UNIQUE_SECTION (decl, reloc);
#endif
- }
+
+ /* Switch to the appropriate section. */
+ variable_section (decl, reloc);
/* dbxout.c needs to know this. */
if (in_text_section ())
@@ -1276,22 +1564,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
/* If the debugging output changed sections, reselect the section
that's supposed to be selected. */
if (in_section != saved_in_section)
- {
- /* Switch to the proper section for this data. */
-#ifdef SELECT_SECTION
- SELECT_SECTION (decl, reloc);
-#else
- if (TREE_READONLY (decl)
- && ! TREE_THIS_VOLATILE (decl)
- && DECL_INITIAL (decl)
- && (DECL_INITIAL (decl) == error_mark_node
- || TREE_CONSTANT (DECL_INITIAL (decl)))
- && ! (flag_pic && reloc))
- readonly_data_section ();
- else
- data_section ();
-#endif
- }
+ variable_section (decl, reloc);
/* Compute and output the alignment of this data. */
@@ -1336,16 +1609,18 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
}
/* Do any machine/system dependent processing of the object. */
-#ifdef ASM_DECLARE_OBJECT_NAME
- last_assemble_variable_decl = decl;
- ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
-#else
- /* Standard thing is just output label for the object. */
if (output_bytecode)
BC_OUTPUT_LABEL (asm_out_file, name);
else
- ASM_OUTPUT_LABEL (asm_out_file, name);
+ {
+#ifdef ASM_DECLARE_OBJECT_NAME
+ last_assemble_variable_decl = decl;
+ ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
+#else
+ /* Standard thing is just output label for the object. */
+ ASM_OUTPUT_LABEL (asm_out_file, name);
#endif /* ASM_DECLARE_OBJECT_NAME */
+ }
if (!dont_output_data)
{
@@ -1373,22 +1648,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
dbxout_symbol (decl, 0);
if (in_section != saved_in_section)
- {
- /* Switch to the proper section for this data. */
-#ifdef SELECT_SECTION
- SELECT_SECTION (decl, reloc);
-#else
- if (TREE_READONLY (decl)
- && ! TREE_THIS_VOLATILE (decl)
- && DECL_INITIAL (decl)
- && (DECL_INITIAL (decl) == error_mark_node
- || TREE_CONSTANT (DECL_INITIAL (decl)))
- && ! (flag_pic && reloc))
- readonly_data_section ();
- else
- data_section ();
-#endif
- }
+ variable_section (decl, reloc);
}
#else
/* There must be a statement after a label. */
@@ -1433,7 +1693,7 @@ contains_pointers_p (type)
}
}
-/* Output text storage for constructor CONSTR. */
+/* Output text storage for constructor CONSTR. */
void
bc_output_constructor (constr, size)
@@ -1443,7 +1703,7 @@ bc_output_constructor (constr, size)
int i;
/* Must always be a literal; non-literal constructors are handled
- differently. */
+ differently. */
if (!TREE_CONSTANT (constr))
abort ();
@@ -1462,7 +1722,7 @@ bc_output_constructor (constr, size)
output_constant (constr, size);
}
-/* Create storage for constructor CONSTR. */
+/* Create storage for constructor CONSTR. */
void
bc_output_data_constructor (constr)
@@ -1478,7 +1738,7 @@ bc_output_data_constructor (constr)
if (i > 0)
BC_OUTPUT_ALIGN (asm_out_file, i);
- /* The constructor is filled in at runtime. */
+ /* The constructor is filled in at runtime. */
BC_OUTPUT_SKIP (asm_out_file, int_size_in_bytes (TREE_TYPE (constr)));
}
@@ -1562,15 +1822,16 @@ assemble_name (file, name)
char *name;
{
char *real_name;
- int save_warn_id_clash = warn_id_clash;
+ tree id;
STRIP_NAME_ENCODING (real_name, name);
+ if (flag_prefix_function_name
+ && ! bcmp (real_name, CHKR_PREFIX, CHKR_PREFIX_SIZE))
+ real_name = real_name + CHKR_PREFIX_SIZE;
- /* Don't warn about an identifier name length clash on this name, since
- it can be a user symbol suffixed by a number. */
- warn_id_clash = 0;
- TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
- warn_id_clash = save_warn_id_clash;
+ id = maybe_get_identifier (real_name);
+ if (id)
+ TREE_SYMBOL_REFERENCED (id) = 1;
if (name[0] == '*')
{
@@ -1627,11 +1888,16 @@ assemble_static_space (size)
}
else
{
+#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
+ ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, size,
+ BIGGEST_ALIGNMENT);
+#else
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
#else
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
#endif
+#endif
}
return x;
}
@@ -1640,6 +1906,7 @@ assemble_static_space (size)
This is done at most once per compilation.
Returns an RTX for the address of the template. */
+#ifdef TRAMPOLINE_TEMPLATE
rtx
assemble_trampoline_template ()
{
@@ -1660,7 +1927,7 @@ assemble_trampoline_template ()
#endif
/* Write the assembler code to define one. */
- align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
if (align > 0)
ASM_OUTPUT_ALIGN (asm_out_file, align);
@@ -1673,6 +1940,7 @@ assemble_trampoline_template ()
= (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
return gen_rtx (SYMBOL_REF, Pmode, name);
}
+#endif
/* Assemble the integer constant X into an object of SIZE bytes.
X must be either a CONST_INT or CONST_DOUBLE.
@@ -1687,7 +1955,7 @@ assemble_integer (x, size, force)
int force;
{
/* First try to use the standard 1, 2, 4, 8, and 16 byte
- ASM_OUTPUT... macros. */
+ ASM_OUTPUT... macros. */
switch (size)
{
@@ -1939,7 +2207,7 @@ immed_double_const (i0, i1, mode)
push_obstacks_nochange ();
rtl_in_saveable_obstack ();
- r = gen_rtx (CONST_DOUBLE, mode, 0, i0, i1);
+ r = gen_rtx (CONST_DOUBLE, mode, NULL_RTX, i0, i1);
pop_obstacks ();
/* Don't touch const_double_chain in nested function; see force_const_mem.
@@ -1977,8 +2245,7 @@ immed_real_const_1 (d, mode)
/* Detect special cases. */
- /* Avoid REAL_VALUES_EQUAL here in order to distinguish minus zero. */
- if (!bcmp ((char *) &dconst0, (char *) &d, sizeof d))
+ if (REAL_VALUES_IDENTICAL (dconst0, d))
return CONST0_RTX (mode);
/* Check for NaN first, because some ports (specifically the i386) do not
emit correct ieee-fp code by default, and thus will generate a core
@@ -2131,6 +2398,7 @@ decode_addr_const (exp, value)
case STRING_CST:
case COMPLEX_CST:
case CONSTRUCTOR:
+ case INTEGER_CST:
x = TREE_CST_RTL (target);
break;
@@ -2179,80 +2447,103 @@ const_hash (exp)
register int len, hi, i;
register enum tree_code code = TREE_CODE (exp);
- if (code == INTEGER_CST)
+ /* Either set P and LEN to the address and len of something to hash and
+ exit the switch or return a value. */
+
+ switch (code)
{
+ case INTEGER_CST:
p = (char *) &TREE_INT_CST_LOW (exp);
len = 2 * sizeof TREE_INT_CST_LOW (exp);
- }
- else if (code == REAL_CST)
- {
+ break;
+
+ case REAL_CST:
p = (char *) &TREE_REAL_CST (exp);
len = sizeof TREE_REAL_CST (exp);
- }
- else if (code == STRING_CST)
- p = TREE_STRING_POINTER (exp), len = TREE_STRING_LENGTH (exp);
- else if (code == COMPLEX_CST)
- return const_hash (TREE_REALPART (exp)) * 5
- + const_hash (TREE_IMAGPART (exp));
- else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
- {
- len = int_size_in_bytes (TREE_TYPE (exp));
- p = (char*) alloca (len);
- get_set_constructor_bytes (exp, (unsigned char *) p, len);
- }
- else if (code == CONSTRUCTOR)
- {
- register tree link;
-
- /* For record type, include the type in the hashing.
- We do not do so for array types
- because (1) the sizes of the elements are sufficient
- and (2) distinct array types can have the same constructor.
- Instead, we include the array size because the constructor could
- be shorter. */
- if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
- hi = ((HOST_WIDE_INT) TREE_TYPE (exp) & ((1 << HASHBITS) - 1))
- % MAX_HASH_TABLE;
- else
- hi = ((5 + int_size_in_bytes (TREE_TYPE (exp)))
- & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE;
+ break;
- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
- if (TREE_VALUE (link))
- hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
+ case STRING_CST:
+ p = TREE_STRING_POINTER (exp);
+ len = TREE_STRING_LENGTH (exp);
+ break;
- return hi;
- }
- else if (code == ADDR_EXPR)
- {
- struct addr_const value;
- decode_addr_const (exp, &value);
- if (GET_CODE (value.base) == SYMBOL_REF)
+ case COMPLEX_CST:
+ return (const_hash (TREE_REALPART (exp)) * 5
+ + const_hash (TREE_IMAGPART (exp)));
+
+ case CONSTRUCTOR:
+ if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
+ {
+ len = int_size_in_bytes (TREE_TYPE (exp));
+ p = (char *) alloca (len);
+ get_set_constructor_bytes (exp, (unsigned char *) p, len);
+ break;
+ }
+ else
{
- /* Don't hash the address of the SYMBOL_REF;
- only use the offset and the symbol name. */
- hi = value.offset;
- p = XSTR (value.base, 0);
- for (i = 0; p[i] != 0; i++)
- hi = ((hi * 613) + (unsigned)(p[i]));
+ register tree link;
+
+ /* For record type, include the type in the hashing.
+ We do not do so for array types
+ because (1) the sizes of the elements are sufficient
+ and (2) distinct array types can have the same constructor.
+ Instead, we include the array size because the constructor could
+ be shorter. */
+ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
+ hi = ((HOST_WIDE_INT) TREE_TYPE (exp) & ((1 << HASHBITS) - 1))
+ % MAX_HASH_TABLE;
+ else
+ hi = ((5 + int_size_in_bytes (TREE_TYPE (exp)))
+ & ((1 << HASHBITS) - 1)) % MAX_HASH_TABLE;
+
+ for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+ if (TREE_VALUE (link))
+ hi
+ = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
+
+ return hi;
}
- else if (GET_CODE (value.base) == LABEL_REF)
- hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
- hi &= (1 << HASHBITS) - 1;
- hi %= MAX_HASH_TABLE;
+ case ADDR_EXPR:
+ {
+ struct addr_const value;
+
+ decode_addr_const (exp, &value);
+ if (GET_CODE (value.base) == SYMBOL_REF)
+ {
+ /* Don't hash the address of the SYMBOL_REF;
+ only use the offset and the symbol name. */
+ hi = value.offset;
+ p = XSTR (value.base, 0);
+ for (i = 0; p[i] != 0; i++)
+ hi = ((hi * 613) + (unsigned) (p[i]));
+ }
+ else if (GET_CODE (value.base) == LABEL_REF)
+ hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
+
+ hi &= (1 << HASHBITS) - 1;
+ hi %= MAX_HASH_TABLE;
+ }
return hi;
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ return (const_hash (TREE_OPERAND (exp, 0)) * 9
+ + const_hash (TREE_OPERAND (exp, 1)));
+
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
+
+ default:
+ abort ();
}
- else if (code == PLUS_EXPR || code == MINUS_EXPR)
- return const_hash (TREE_OPERAND (exp, 0)) * 9
- + const_hash (TREE_OPERAND (exp, 1));
- else if (code == NOP_EXPR || code == CONVERT_EXPR)
- return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
/* Compute hashing function */
hi = len;
for (i = 0; i < len; i++)
- hi = ((hi * 613) + (unsigned)(p[i]));
+ hi = ((hi * 613) + (unsigned) (p[i]));
hi &= (1 << HASHBITS) - 1;
hi %= MAX_HASH_TABLE;
@@ -2291,119 +2582,152 @@ compare_constant_1 (exp, p)
if (code != (enum tree_code) *p++)
return 0;
- if (code == INTEGER_CST)
+ /* Either set STRP, P and LEN to pointers and length to compare and exit the
+ switch, or return the result of the comparison. */
+
+ switch (code)
{
+ case INTEGER_CST:
/* Integer constants are the same only if the same width of type. */
if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
return 0;
+
strp = (char *) &TREE_INT_CST_LOW (exp);
len = 2 * sizeof TREE_INT_CST_LOW (exp);
- }
- else if (code == REAL_CST)
- {
+ break;
+
+ case REAL_CST:
/* Real constants are the same only if the same width of type. */
if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
return 0;
+
strp = (char *) &TREE_REAL_CST (exp);
len = sizeof TREE_REAL_CST (exp);
- }
- else if (code == STRING_CST)
- {
+ break;
+
+ case STRING_CST:
if (flag_writable_strings)
return 0;
+
+ if (*p++ != TYPE_MODE (TREE_TYPE (exp)))
+ return 0;
+
strp = TREE_STRING_POINTER (exp);
len = TREE_STRING_LENGTH (exp);
if (bcmp ((char *) &TREE_STRING_LENGTH (exp), p,
sizeof TREE_STRING_LENGTH (exp)))
return 0;
+
p += sizeof TREE_STRING_LENGTH (exp);
- }
- else if (code == COMPLEX_CST)
- {
- p = compare_constant_1 (TREE_REALPART (exp), p);
- if (p == 0) return 0;
- p = compare_constant_1 (TREE_IMAGPART (exp), p);
- return p;
- }
- else if (code == CONSTRUCTOR && TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
- {
- len = int_size_in_bytes (TREE_TYPE (exp));
- strp = (char*) alloca (len);
- get_set_constructor_bytes (exp, (unsigned char *) strp, len);
- }
- else if (code == CONSTRUCTOR)
- {
- register tree link;
- int length = list_length (CONSTRUCTOR_ELTS (exp));
- tree type;
+ break;
- if (bcmp ((char *) &length, p, sizeof length))
+ case COMPLEX_CST:
+ p = compare_constant_1 (TREE_REALPART (exp), p);
+ if (p == 0)
return 0;
- p += sizeof length;
- /* For record constructors, insist that the types match.
- For arrays, just verify both constructors are for arrays. */
- if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
- type = TREE_TYPE (exp);
- else
- type = 0;
- if (bcmp ((char *) &type, p, sizeof type))
- return 0;
- p += sizeof type;
+ return compare_constant_1 (TREE_IMAGPART (exp), p);
- /* For arrays, insist that the size in bytes match. */
- if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ case CONSTRUCTOR:
+ if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
{
- int size = int_size_in_bytes (TREE_TYPE (exp));
- if (bcmp ((char *) &size, p, sizeof size))
+ int xlen = len = int_size_in_bytes (TREE_TYPE (exp));
+
+ strp = (char *) alloca (len);
+ get_set_constructor_bytes (exp, (unsigned char *) strp, len);
+ if (bcmp ((char *) &xlen, p, sizeof xlen))
return 0;
- p += sizeof size;
- }
- for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
+ p += sizeof xlen;
+ break;
+ }
+ else
{
- if (TREE_VALUE (link))
+ register tree link;
+ int length = list_length (CONSTRUCTOR_ELTS (exp));
+ tree type;
+
+ if (bcmp ((char *) &length, p, sizeof length))
+ return 0;
+
+ p += sizeof length;
+
+ /* For record constructors, insist that the types match.
+ For arrays, just verify both constructors are for arrays. */
+ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
+ type = TREE_TYPE (exp);
+ else
+ type = 0;
+
+ if (bcmp ((char *) &type, p, sizeof type))
+ return 0;
+
+ p += sizeof type;
+
+ /* For arrays, insist that the size in bytes match. */
+ if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
{
- if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
+ int size = int_size_in_bytes (TREE_TYPE (exp));
+ if (bcmp ((char *) &size, p, sizeof size))
return 0;
+
+ p += sizeof size;
}
- else
+
+ for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
{
- tree zero = 0;
+ if (TREE_VALUE (link))
+ {
+ if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
+ return 0;
+ }
+ else
+ {
+ tree zero = 0;
- if (bcmp ((char *) &zero, p, sizeof zero))
- return 0;
- p += sizeof zero;
+ if (bcmp ((char *) &zero, p, sizeof zero))
+ return 0;
+
+ p += sizeof zero;
+ }
}
+
+ return p;
}
- return p;
- }
- else if (code == ADDR_EXPR)
- {
- struct addr_const value;
- decode_addr_const (exp, &value);
- strp = (char *) &value.offset;
- len = sizeof value.offset;
- /* Compare the offset. */
- while (--len >= 0)
- if (*p++ != *strp++)
- return 0;
- /* Compare symbol name. */
- strp = XSTR (value.base, 0);
- len = strlen (strp) + 1;
- }
- else if (code == PLUS_EXPR || code == MINUS_EXPR)
- {
- p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
- if (p == 0) return 0;
- p = compare_constant_1 (TREE_OPERAND (exp, 1), p);
- return p;
- }
- else if (code == NOP_EXPR || code == CONVERT_EXPR)
- {
+ case ADDR_EXPR:
+ {
+ struct addr_const value;
+
+ decode_addr_const (exp, &value);
+ strp = (char *) &value.offset;
+ len = sizeof value.offset;
+ /* Compare the offset. */
+ while (--len >= 0)
+ if (*p++ != *strp++)
+ return 0;
+
+ /* Compare symbol name. */
+ strp = XSTR (value.base, 0);
+ len = strlen (strp) + 1;
+ }
+ break;
+
+ case PLUS_EXPR:
+ case MINUS_EXPR:
p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
- return p;
+ if (p == 0)
+ return 0;
+
+ return compare_constant_1 (TREE_OPERAND (exp, 1), p);
+
+ case NOP_EXPR:
+ case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ return compare_constant_1 (TREE_OPERAND (exp, 0), p);
+
+ default:
+ abort ();
}
/* Compare constant contents. */
@@ -2466,6 +2790,7 @@ record_constant_1 (exp)
if (flag_writable_strings)
return;
+ obstack_1grow (&permanent_obstack, TYPE_MODE (TREE_TYPE (exp)));
strp = TREE_STRING_POINTER (exp);
len = TREE_STRING_LENGTH (exp);
obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
@@ -2484,7 +2809,8 @@ record_constant_1 (exp)
obstack_grow (&permanent_obstack, &nbytes, sizeof (nbytes));
obstack_blank (&permanent_obstack, nbytes);
get_set_constructor_bytes
- (exp, (unsigned char *) permanent_obstack.next_free, nbytes);
+ (exp, (unsigned char *) permanent_obstack.next_free-nbytes,
+ nbytes);
return;
}
else
@@ -2572,6 +2898,10 @@ struct deferred_constant
static struct deferred_constant *deferred_constants;
+/* Another list of constants which should be output after the
+ function. */
+static struct deferred_constant *after_function_constants;
+
/* Nonzero means defer output of addressed subconstants
(i.e., those for which output_constant_def is called.) */
static int defer_addressed_constants_flag;
@@ -2607,6 +2937,23 @@ output_deferred_addressed_constants ()
deferred_constants = 0;
}
+/* Output any constants which should appear after a function. */
+
+static void
+output_after_function_constants ()
+{
+ struct deferred_constant *p, *next;
+
+ for (p = after_function_constants; p; p = next)
+ {
+ output_constant_def_contents (p->exp, p->reloc, p->labelno);
+ next = p->next;
+ free (p);
+ }
+
+ after_function_constants = 0;
+}
+
/* Make a copy of the whole tree structure for a constant.
This handles the same types of nodes that compare_constant
and record_constant handle. */
@@ -2632,7 +2979,8 @@ copy_constant (exp)
return copy_node (exp);
case COMPLEX_CST:
- return build_complex (copy_constant (TREE_REALPART (exp)),
+ return build_complex (TREE_TYPE (exp),
+ copy_constant (TREE_REALPART (exp)),
copy_constant (TREE_IMAGPART (exp)));
case PLUS_EXPR:
@@ -2643,6 +2991,7 @@ copy_constant (exp)
case NOP_EXPR:
case CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
return build1 (TREE_CODE (exp), TREE_TYPE (exp),
copy_constant (TREE_OPERAND (exp, 0)));
@@ -2689,9 +3038,6 @@ output_constant_def (exp)
int reloc;
register rtx def;
- if (TREE_CODE (exp) == INTEGER_CST)
- abort (); /* No TREE_CST_RTL slot in these. */
-
if (TREE_CST_RTL (exp))
return TREE_CST_RTL (exp);
@@ -2762,7 +3108,15 @@ output_constant_def (exp)
output it (or defer its output for later). */
if (found == 0)
{
- if (defer_addressed_constants_flag)
+ int after_function = 0;
+
+#ifdef CONSTANT_AFTER_FUNCTION_P
+ if (current_function_decl != 0
+ && CONSTANT_AFTER_FUNCTION_P (exp))
+ after_function = 1;
+#endif
+
+ if (defer_addressed_constants_flag || after_function)
{
struct deferred_constant *p;
p = (struct deferred_constant *) xmalloc (sizeof (struct deferred_constant));
@@ -2773,8 +3127,16 @@ output_constant_def (exp)
pop_obstacks ();
p->reloc = reloc;
p->labelno = const_labelno++;
- p->next = deferred_constants;
- deferred_constants = p;
+ if (after_function)
+ {
+ p->next = after_function_constants;
+ after_function_constants = p;
+ }
+ else
+ {
+ p->next = deferred_constants;
+ deferred_constants = p;
+ }
}
else
output_constant_def_contents (exp, reloc, const_labelno++);
@@ -2795,7 +3157,7 @@ output_constant_def_contents (exp, reloc, labelno)
int align;
if (IN_NAMED_SECTION (exp))
- named_section (exp, NULL);
+ named_section (exp, NULL, reloc);
else
{
/* First switch to text section, except for writable strings. */
@@ -2867,6 +3229,7 @@ struct pool_constant
int labelno;
int align;
int offset;
+ int mark;
};
/* Pointers to first and last constant in pool. */
@@ -2919,14 +3282,20 @@ init_const_rtx_hash_table ()
/* Save and restore status for a nested function. */
void
-save_varasm_status (p)
+save_varasm_status (p, context)
struct function *p;
+ tree context;
{
p->const_rtx_hash_table = const_rtx_hash_table;
p->const_rtx_sym_hash_table = const_rtx_sym_hash_table;
p->first_pool = first_pool;
p->last_pool = last_pool;
p->pool_offset = pool_offset;
+ p->const_double_chain = const_double_chain;
+
+ /* If we are pushing to toplevel, we can't reuse const_double_chain. */
+ if (context == NULL_TREE)
+ const_double_chain = 0;
}
void
@@ -2938,6 +3307,7 @@ restore_varasm_status (p)
first_pool = p->first_pool;
last_pool = p->last_pool;
pool_offset = p->pool_offset;
+ const_double_chain = p->const_double_chain;
}
enum kind { RTX_DOUBLE, RTX_INT };
@@ -2977,7 +3347,7 @@ decode_rtx_const (mode, x, value)
*p++ = 0;
}
- value->kind = RTX_INT; /* Most usual kind. */
+ value->kind = RTX_INT; /* Most usual kind. */
value->mode = mode;
switch (GET_CODE (x))
@@ -3040,6 +3410,9 @@ decode_rtx_const (mode, x, value)
for the sake of addresses of library routines.
For a LABEL_REF, compare labels. */
value->un.addr.base = XEXP (value->un.addr.base, 0);
+
+ default:
+ break;
}
}
@@ -3203,19 +3576,25 @@ force_const_mem (mode, x)
pool_offset &= ~ (align - 1);
/* If RTL is not being placed into the saveable obstack, make a
- copy of X that is in the saveable obstack in case we are being
- called from combine or some other phase that discards memory
- it allocates. We need only do this if it is a CONST, since
- no other RTX should be allocated in this situation. */
+ copy of X that is in the saveable obstack in case we are
+ being called from combine or some other phase that discards
+ memory it allocates. We used to only do this if it is a
+ CONST; however, reload can allocate a CONST_INT when
+ eliminating registers. */
if (rtl_obstack != saveable_obstack
- && GET_CODE (x) == CONST)
+ && (GET_CODE (x) == CONST || GET_CODE (x) == CONST_INT))
{
push_obstacks_nochange ();
rtl_in_saveable_obstack ();
- x = gen_rtx (CONST, GET_MODE (x),
- gen_rtx (PLUS, GET_MODE (x),
- XEXP (XEXP (x, 0), 0), XEXP (XEXP (x, 0), 1)));
+ if (GET_CODE (x) == CONST)
+ x = gen_rtx (CONST, GET_MODE (x),
+ gen_rtx (PLUS, GET_MODE (x),
+ XEXP (XEXP (x, 0), 0),
+ XEXP (XEXP (x, 0), 1)));
+ else
+ x = GEN_INT (INTVAL (x));
+
pop_obstacks ();
}
@@ -3228,6 +3607,7 @@ force_const_mem (mode, x)
pool->labelno = const_labelno;
pool->align = align;
pool->offset = pool_offset;
+ pool->mark = 1;
pool->next = 0;
if (last_pool == 0)
@@ -3341,6 +3721,12 @@ output_constant_pool (fnname, fndecl)
rtx x;
union real_extract u;
+ /* It is possible for gcc to call force_const_mem and then to later
+ discard the instructions which refer to the constant. In such a
+ case we do not need to output the constant. */
+ if (optimize >= 0 && flag_expensive_optimizations)
+ mark_constant_pool ();
+
#ifdef ASM_OUTPUT_POOL_PROLOGUE
ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset);
#endif
@@ -3349,6 +3735,9 @@ output_constant_pool (fnname, fndecl)
{
x = pool->constant;
+ if (! pool->mark)
+ continue;
+
/* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF)
whose CODE_LABEL has been deleted. This can occur if a jump table
is eliminated by optimization. If so, write a constant of zero
@@ -3404,9 +3793,107 @@ output_constant_pool (fnname, fndecl)
done: ;
}
+#ifdef ASM_OUTPUT_POOL_EPILOGUE
+ ASM_OUTPUT_POOL_EPILOGUE (asm_out_file, fnname, fndecl, pool_offset);
+#endif
+
/* Done with this pool. */
first_pool = last_pool = 0;
}
+
+/* Look through the instructions for this function, and mark all the
+ entries in the constant pool which are actually being used. */
+
+static void
+mark_constant_pool ()
+{
+ register rtx insn;
+ struct pool_constant *pool;
+
+ if (first_pool == 0)
+ return;
+
+ for (pool = first_pool; pool; pool = pool->next)
+ pool->mark = 0;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ mark_constants (PATTERN (insn));
+
+ for (insn = current_function_epilogue_delay_list;
+ insn;
+ insn = XEXP (insn, 1))
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+ mark_constants (PATTERN (insn));
+}
+
+static void
+mark_constants (x)
+ register rtx x;
+{
+ register int i;
+ register char *format_ptr;
+
+ if (x == 0)
+ return;
+
+ if (GET_CODE (x) == SYMBOL_REF)
+ {
+ if (CONSTANT_POOL_ADDRESS_P (x))
+ find_pool_constant (x)->mark = 1;
+ return;
+ }
+ /* Never search inside a CONST_DOUBLE, because CONST_DOUBLE_MEM may be
+ a MEM, but does not constitute a use of that MEM. This is particularly
+ important inside a nested function, because CONST_DOUBLE_MEM may be
+ a reference to a MEM in the parent's constant pool. See the comment
+ in force_const_mem. */
+ else if (GET_CODE (x) == CONST_DOUBLE)
+ return;
+
+ /* Insns may appear inside a SEQUENCE. Only check the patterns of
+ insns, not any notes that may be attached. We don't want to mark
+ a constant just because it happens to appear in a REG_EQUIV note. */
+ if (GET_RTX_CLASS (GET_CODE (x)) == 'i')
+ {
+ mark_constants (PATTERN (x));
+ return;
+ }
+
+ format_ptr = GET_RTX_FORMAT (GET_CODE (x));
+
+ for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
+ {
+ switch (*format_ptr++)
+ {
+ case 'e':
+ mark_constants (XEXP (x, i));
+ break;
+
+ case 'E':
+ if (XVEC (x, i) != 0)
+ {
+ register int j;
+
+ for (j = 0; j < XVECLEN (x, i); j++)
+ mark_constants (XVECEXP (x, i, j));
+ }
+ break;
+
+ case 'S':
+ case 's':
+ case '0':
+ case 'i':
+ case 'w':
+ case 'n':
+ case 'u':
+ break;
+
+ default:
+ abort ();
+ }
+ }
+}
/* Find all the constants whose addresses are referenced inside of EXP,
and make sure assembler code with a label has been output for each one.
@@ -3459,7 +3946,7 @@ output_addressed_constants (exp)
}
break;
- case ERROR_MARK:
+ default:
break;
}
return reloc;
@@ -3595,13 +4082,16 @@ output_constant (exp, size)
else
error ("unknown set constructor type");
return;
+
+ default:
+ break; /* ??? */
}
if (size > 0)
assemble_zeros (size);
}
-/* Bytecode specific code to output assembler for integer. */
+/* Bytecode specific code to output assembler for integer. */
static void
bc_assemble_integer (exp, size)
@@ -3619,7 +4109,8 @@ bc_assemble_integer (exp, size)
exp = fold (exp);
- while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR)
+ while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
+ || TREE_CODE (exp) == NON_LVALUE_EXPR)
exp = TREE_OPERAND (exp, 0);
if (TREE_CODE (exp) == INTEGER_CST)
{
@@ -3630,11 +4121,13 @@ bc_assemble_integer (exp, size)
{
const_part = TREE_OPERAND (exp, 0);
while (TREE_CODE (const_part) == NOP_EXPR
- || TREE_CODE (const_part) == CONVERT_EXPR)
+ || TREE_CODE (const_part) == CONVERT_EXPR
+ || TREE_CODE (const_part) == NON_LVALUE_EXPR)
const_part = TREE_OPERAND (const_part, 0);
addr_part = TREE_OPERAND (exp, 1);
while (TREE_CODE (addr_part) == NOP_EXPR
- || TREE_CODE (addr_part) == CONVERT_EXPR)
+ || TREE_CODE (addr_part) == CONVERT_EXPR
+ || TREE_CODE (addr_part) == NON_LVALUE_EXPR)
addr_part = TREE_OPERAND (addr_part, 0);
if (TREE_CODE (const_part) != INTEGER_CST)
tmp = const_part, const_part = addr_part, addr_part = tmp;
@@ -3759,7 +4252,26 @@ output_constructor (exp, size)
if (val != 0)
STRIP_NOPS (val);
- if (field == 0 || !DECL_BIT_FIELD (field))
+ if (index && TREE_CODE (index) == RANGE_EXPR)
+ {
+ register int fieldsize
+ = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
+ HOST_WIDE_INT lo_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 0));
+ HOST_WIDE_INT hi_index = TREE_INT_CST_LOW (TREE_OPERAND (index, 1));
+ HOST_WIDE_INT index;
+ for (index = lo_index; index <= hi_index; index++)
+ {
+ /* Output the element's initial value. */
+ if (val == 0)
+ assemble_zeros (fieldsize);
+ else
+ output_constant (val, fieldsize);
+
+ /* Count its size. */
+ total_bytes += fieldsize;
+ }
+ }
+ else if (field == 0 || !DECL_BIT_FIELD (field))
{
/* An element that is not a bit-field. */
@@ -3940,7 +4452,7 @@ output_constructor (exp, size)
}
/* Now get the bits from the appropriate constant word. */
- if (shift < HOST_BITS_PER_INT)
+ if (shift < HOST_BITS_PER_WIDE_INT)
value = TREE_INT_CST_LOW (val);
else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
{
@@ -3968,6 +4480,7 @@ output_constructor (exp, size)
}
/* Output asm to handle ``#pragma weak'' */
+
void
handle_pragma_weak (what, name, value)
enum pragma_state what;
@@ -4035,12 +4548,12 @@ void
assemble_alias (decl, target)
tree decl, target;
{
-#ifdef ASM_OUTPUT_DEF
char *name;
- make_decl_rtl (decl, (char*)0, 1);
+ make_decl_rtl (decl, (char *) 0, 1);
name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+#ifdef ASM_OUTPUT_DEF
/* Make name accessible from other files, if appropriate. */
if (TREE_PUBLIC (decl))
@@ -4059,6 +4572,64 @@ assemble_alias (decl, target)
ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target));
TREE_ASM_WRITTEN (decl) = 1;
#else
- warning ("alias definitions not supported in this configuration");
+#ifdef ASM_OUTPUT_WEAK_ALIAS
+ if (! DECL_WEAK (decl))
+ warning ("only weak aliases are supported in this configuration");
+
+ ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
+ TREE_ASM_WRITTEN (decl) = 1;
+#else
+ warning ("alias definitions not supported in this configuration; ignored");
+#endif
+#endif
+}
+
+/* This determines whether or not we support link-once semantics. */
+#ifndef SUPPORTS_ONE_ONLY
+#ifdef MAKE_DECL_ONE_ONLY
+#define SUPPORTS_ONE_ONLY 1
+#else
+#define SUPPORTS_ONE_ONLY 0
+#endif
#endif
+
+/* Returns 1 if the target configuration supports defining public symbols
+ so that one of them will be chosen at link time instead of generating a
+ multiply-defined symbol error, whether through the use of weak symbols or
+ a target-specific mechanism for having duplicates discarded. */
+
+int
+supports_one_only ()
+{
+ if (SUPPORTS_ONE_ONLY)
+ return 1;
+ return SUPPORTS_WEAK;
+}
+
+/* Set up DECL as a public symbol that can be defined in multiple
+ translation units without generating a linker error. */
+
+void
+make_decl_one_only (decl)
+ tree decl;
+{
+ if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
+ abort ();
+
+ TREE_PUBLIC (decl) = 1;
+
+ if (TREE_CODE (decl) == VAR_DECL
+ && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+ DECL_COMMON (decl) = 1;
+ else if (SUPPORTS_ONE_ONLY)
+ {
+#ifdef MAKE_DECL_ONE_ONLY
+ MAKE_DECL_ONE_ONLY (decl);
+#endif
+ DECL_ONE_ONLY (decl) = 1;
+ }
+ else if (SUPPORTS_WEAK)
+ DECL_WEAK (decl) = 1;
+ else
+ abort ();
}
diff --git a/gnu/usr.bin/gcc/vmsconfig.com b/gnu/usr.bin/gcc/vmsconfig.com
index 0b58b2d4e30..f4ebf0e2d1f 100644
--- a/gnu/usr.bin/gcc/vmsconfig.com
+++ b/gnu/usr.bin/gcc/vmsconfig.com
@@ -1,5 +1,5 @@
$ !
-$ ! Set up to compile GCC on VAX/VMS
+$ ! Set up to compile GCC on VMS.
$ !
$! Set the def dir to proper place for use in batch. Works for interactive too.
$flnm = f$enviroment("PROCEDURE") ! get current procedure name
@@ -10,9 +10,12 @@ $if f$trnlnm("IFILE$").nes."" then close/noLog ifile$
$ !
$ echo = "write sys$output"
$ !
+$ arch_indx = 1 + ((f$getsyi("CPU").ge.128).and.1) ! vax==1, alpha==2
+$ arch = f$element(arch_indx,"|","|vax|alpha|")
+$ !
$ if f$search("config.h") .nes. "" then delete config.h.*
-$ copy [.config.vax]xm-vms.h []config.h
-$ echo "Linked `config.h' to `[.config.vax]xm-vms.h'.
+$ copy [.config.'arch']xm-vms.h []config.h
+$ echo "Linked `config.h' to `[.config.''arch']xm-vms.h'."
$ !
$ if f$search("tconfig.h") .nes. "" then delete tconfig.h.*
$ create []tconfig.h
@@ -31,18 +34,21 @@ $EOD
$ echo "Created `hconfig.h'.
$ !
$ if f$search("tm.h") .nes. "" then delete tm.h.*
-$!! copy [.config.vax]vms.h []tm.h
+$!! copy [.config.'arch']vms.h []tm.h
$ edit/tpu/nojournal/nosection/nodisplay/command=sys$input -
- [.config.vax]vms.h /output=[]tm.h
+ [.config.'arch']vms.h /output=[]tm.h
$DECK
!
! Copy file, changing lines of the form
! #include "vax/*"
+! or
+! #include "alpha/*"
! into
! #include "config-*"
!
file := CREATE_BUFFER("file", GET_INFO(COMMAND_LINE, "file_name"));
- targ := LINE_BEGIN & '#include' & SPAN(ASCII(32)+ASCII(9)) & '"vax/';
+ targ := LINE_BEGIN & '#include' & SPAN(ASCII(32)+ASCII(9))
+ & '"' & ('vax' | 'alpha') & '/';
rang := CREATE_RANGE(BEGINNING_OF(file), END_OF(file));
LOOP
incl := SEARCH_QUIETLY(targ, FORWARD, EXACT, rang);
@@ -55,24 +61,24 @@ $DECK
WRITE_FILE(file, GET_INFO(COMMAND_LINE, "output_file"));
QUIT
$EOD
-$ echo "Generated `tm.h' from `[.config.vax]vms.h'.
+$ echo "Generated `tm.h' from `[.config.''arch']vms.h'."
$ !
$ !crude hack to allow compiling from [.cp] subdirectory
-$ if f$search("config-vax.h") .nes. "" then delete config-vax.h;*
-$ copy [.config.vax]vax.h []config-vax.h
-$ echo "Linked `config-vax.h' to `[.config.vax]vax.h' for `tm.h'."
+$ if f$search("config-''arch'.h") .nes. "" then delete config-'arch'.h;*
+$ copy [.config.'arch']'arch'.h []config-'arch'.h
+$ echo "Linked `config-''arch'.h' to `[.config.''arch']''arch'.h' for `tm.h'."
$ !
$ call make_lang_incl "options.h"
$ !
$ call make_lang_incl "specs.h"
$ !
-$ if f$search("vax.md") .nes. "" then delete vax.md;*
-$ copy [.config.vax]vax.md []vax.md
-$ echo "Copied `vax.md' from `[.config.vax]vax.md'."
+$ if f$search("''arch'.md") .nes. "" then delete 'arch'.md;*
+$ copy [.config.'arch']'arch'.md []'arch'.md
+$ echo "Copied `''arch'.md' from `[.config.''arch']''arch'.md'."
$ !
$ if f$search("aux-output.c") .nes. "" then delete aux-output.c.*
-$ copy [.config.vax]vax.c []aux-output.c
-$ echo "Linked `aux-output.c' to `[.config.vax]vax.c'.
+$ copy [.config.'arch']'arch'.c []aux-output.c
+$ echo "Linked `aux-output.c' to `[.config.''arch']''arch'.c'.
$ !
$!
$!
@@ -83,28 +89,17 @@ $open ifile$ t.tmp
$read ifile$ line
$close ifile$
$delete t.tmp;
-$ijk=f$locate("""",line)+1
-$line=f$extract(ijk,f$length(line)-ijk,line)
-$ijk=f$locate("""",line)
-$line=f$extract(0,ijk,line)
-$ijk=f$locate("\n",line)
-$line=f$extract(0,ijk,line)
-$!
-$i=0
-$loop:
-$elm=f$element(i," ",line)
-$if elm.eqs."" then goto no_ident
-$if (elm.les."9").and.(elm.ges."0") then goto write_ident
-$i=i+1
-$goto loop
-$!
-$no_ident:
-$elm="?.??"
-$!
+$line=f$element(1,"""",line) !extract the portion between 1st & 2nd quotes
+$! Format of 'line' is "name-nn.nn.nn[.nn] [date text]" (without the quotes).
+$! We want "name-nn.nn.nn[.nn][-date]"; "-date" suffix is optional.
+$id = f$element(1,"-",line) !strip "name-" prefix
+$if id.eqs."-" then id = line !no prefix found?
+$id = f$element(0," ",id) + "-" + f$element(1," ",id) !first two tokens
+$id = id - "- " !in case 2nd token was empty
+$if f$length(id).gt.15 then id = f$extract(0,15,id) !length limitation
$!
-$write_ident:
-$open ifile$ version.opt/write
-$write ifile$ "ident="+""""+elm+""""
+$open/write ifile$ version.opt
+$write ifile$ "ident="+""""+id+""""
$close ifile$
$purge version.opt
$!
@@ -125,9 +120,11 @@ $if f$search("[.cp]Makefile.in").eqs."" .and. f$search("[.cp]$M$akefile.in").nes
$!
$!
$echo "Now processing Makefile.in to generate linker option files."
-$edit/TPU/noJournal/noSection/noDisplay/Command=sys$input: Makefile.in
+$edit/TPU/noJournal/noSection/noDisplay/Command=sys$input: Makefile.in -
+ /Start_Position=('arch_indx') ! 1 for vax, 2 for alpha
!!
VARIABLE makefile_buf, opt_file_buf, complist_buf, extra_compilers; ! Globals.
+VARIABLE arch; ! String 'vax' or 'alpha', set in configure_makefile().
!!
PROCEDURE process_makefile( )
@@ -165,10 +162,11 @@ PROCEDURE process_makefile( )
! The contents are assumed to be a list of object files, and from this
! list a VMS linker options file is generated.
!
- generate_option_file ("OBJS", "=", "independent.opt");
- generate_option_file ("LIB2FUNCS", "=", "libgcc2.list");
- generate_option_file ("BC_ALL", "=", "bc_all.list");
- generate_option_file ("BI_OBJ", "=", "bi_all.opt");
+ generate_option_file ("OBJS", "=", "independent.opt");
+ generate_option_file ("LIB2FUNCS", "=", "libgcc2.list");
+ generate_option_file ("CXX_LIB2FUNCS", "=", "libgcc2-cxx.list");
+ generate_option_file ("BC_ALL", "=", "bc_all.list");
+ generate_option_file ("BI_OBJ", "=", "bi_all.opt");
!
! Now change OBJS in the Makefile, so each language specific options file
! does not pick up all of the language independent files.
@@ -204,7 +202,7 @@ PROCEDURE process_objc_lib( )
ERASE (makefile_buf); !discard top Makefile
POSITION (END_OF (makefile_buf));
- READ_FILE ("[.objc]Makefile"); !load objc one
+ READ_FILE ("[.objc]Make-lang.in"); !load objc one
MESSAGE ("objclib");
pat_replace (ASCII(9), " "); !change any <tab> to <space>
generate_option_file ("OBJC_O", "=", "objc-objs.opt");
@@ -220,12 +218,20 @@ PROCEDURE configure_makefile( )
! Plug in some values normally handled by `configure'. Rather than
! replacing the dummy entries, insert the real entries before them.
!
+ IF (GET_INFO (COMMAND_LINE, 'START_RECORD') <> 2) THEN
+ arch := 'vax';
+ ELSE
+ arch := 'alpha';
+ ENDIF;
POSITION (BEGINNING_OF (makefile_buf));
- COPY_TEXT ("target=vax-vms"); SPLIT_LINE;
- COPY_TEXT ("out_file=aux-output.c"); SPLIT_LINE; ! vax/vax.c
+ COPY_TEXT ("target=" + arch + "-vms"); SPLIT_LINE;
+ COPY_TEXT ("out_file=aux-output.c"); SPLIT_LINE; ! 'arch'/'arch'.c
COPY_TEXT ("out_object_file=aux-output.o"); SPLIT_LINE; ! aux-output.obj
- COPY_TEXT ("md_file=vax.md"); SPLIT_LINE; ! vax/vax.md
- COPY_TEXT ("tm_file=tm.h"); SPLIT_LINE; ! vax/tm-vms.h
+ COPY_TEXT ("md_file=" + arch + ".md"); SPLIT_LINE; ! 'arch'/'arch'.md
+ COPY_TEXT ("tm_file=tm.h"); SPLIT_LINE; ! 'arch'/tm-vms.h
+ pat_replace ("@" &
+ SPAN("abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ#~0123456789")
+ & "@", ); ! strip `configure' dummy values
ENDPROCEDURE; !configure_makefile
!!
@@ -275,6 +281,12 @@ PROCEDURE additional_compiler( cname, subdir )
pat_replace ("_OTH_SRCS)", "_OTH_SRCS_dummy_)");
! Convert subdirectory references into VMS syntax.
pat_replace ("$(srcdir)/" + subdir + "/", "[." + subdir + "]");
+
+ ! Temporary? hack for cp/Make-lang.in's mishandling of "input.c".
+ IF (subdir = 'cp') THEN
+ pat_replace ("[.cp]input.c", ); ! Discard this text.
+ ENDIF;
+
! Add this name to compilers.list.
POSITION (END_OF (complist_buf));
COPY_TEXT (cname);
@@ -444,7 +456,9 @@ $!
$!
$ if f$search("config.status") .nes. "" then delete config.status.*
$ create config.status
-Links are now set up for use with a vax running VMS.
+$ open/append ifile$ config.status
+$ write ifile$ "Links are now set up for use with a ''arch' running VMS."
+$ close ifile$
$ type config.status
$ echo ""
$!
diff --git a/gnu/usr.bin/gcc/xcoffout.c b/gnu/usr.bin/gcc/xcoffout.c
index 14ebce8e259..323eb069f5a 100644
--- a/gnu/usr.bin/gcc/xcoffout.c
+++ b/gnu/usr.bin/gcc/xcoffout.c
@@ -1,5 +1,5 @@
/* Output xcoff-format symbol table information from GNU compiler.
- Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1994, 1995, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -24,10 +24,8 @@ Boston, MA 02111-1307, USA. */
interface. Many functions are very similar to their counterparts in
sdbout.c. */
-/* Include this first, because it may define MIN and MAX. */
-#include <stdio.h>
-
#include "config.h"
+#include <stdio.h>
#include "tree.h"
#include "rtl.h"
#include "flags.h"
@@ -53,8 +51,8 @@ Boston, MA 02111-1307, USA. */
/* Line number of beginning of current function, minus one.
Negative means not in a function or not using xcoff. */
-int xcoff_begin_function_line = -1;
-int xcoff_inlining = 0;
+static int xcoff_begin_function_line = -1;
+static int xcoff_inlining = 0;
/* Name of the current include file. */
@@ -65,7 +63,7 @@ char *xcoff_current_include_file;
(by including that file of course), then the line number will be
absolute. */
-char *xcoff_current_function_file;
+static char *xcoff_current_function_file;
/* Names of bss and data sections. These should be unique names for each
compilation unit. */
@@ -113,6 +111,9 @@ char *xcoff_lastfile;
#define ASM_OUTPUT_LBE(FILE,LINENUM,BLOCKNUM) \
fprintf (FILE, "\t.eb\t%d\n", ABS_OR_RELATIVE_LINENO (LINENUM))
+
+static void assign_type_number PROTO((tree, char *, int));
+static void xcoffout_block PROTO((tree, int, tree));
/* Support routines for XCOFF debugging info. */
@@ -145,14 +146,14 @@ xcoff_output_standard_types (syms)
{
/* Handle built-in C types here. */
- assign_type_number (syms, "int", (TARGET_64BIT ? -31 : -1));
+ assign_type_number (syms, "int", -1);
assign_type_number (syms, "char", -2);
assign_type_number (syms, "short int", -3);
assign_type_number (syms, "long int", (TARGET_64BIT ? -31 : -4));
assign_type_number (syms, "unsigned char", -5);
assign_type_number (syms, "signed char", -6);
assign_type_number (syms, "short unsigned int", -7);
- assign_type_number (syms, "unsigned int", (TARGET_64BIT ? -32 : -8));
+ assign_type_number (syms, "unsigned int", -8);
/* No such type "unsigned". */
assign_type_number (syms, "long unsigned int", (TARGET_64BIT ? -32 : -10));
assign_type_number (syms, "void", -11);
diff --git a/gnu/usr.bin/gcc/xcoffout.h b/gnu/usr.bin/gcc/xcoffout.h
index 432a5de9f74..8a97eaff3bd 100644
--- a/gnu/usr.bin/gcc/xcoffout.h
+++ b/gnu/usr.bin/gcc/xcoffout.h
@@ -58,8 +58,8 @@
#define DBX_STATIC_BLOCK_END(ASMFILE,CODE) \
{ \
- if (current_sym_code == N_STSYM || current_sym_code == N_LCSYM) \
- fprintf (asmfile, "\t.es\n"); \
+ if ((CODE) == N_STSYM || (CODE) == N_LCSYM) \
+ fputs ("\t.es\n", (ASMFILE)); \
}
/* We must use N_RPYSM instead of N_RSYM for register parameters. */
@@ -115,22 +115,10 @@
#define N_RPSYM 0x8e
#endif
-/* The line number of the beginning of the current function.
- xcoffout.c needs this so that it can output relative linenumbers. */
-
-extern int xcoff_begin_function_line;
-
/* Name of the current include file. */
extern char *xcoff_current_include_file;
-/* Name of the current function file. This is the file the `.bf' is
- emitted from. In case a line is emitted from a different file,
- (by including that file of course), then the line number will be
- absolute. */
-
-extern char *xcoff_current_function_file;
-
/* Names of bss and data sections. These should be unique names for each
compilation unit. */
@@ -151,16 +139,16 @@ extern char *xcoff_lastfile;
is already emitting a .file directory, so we don't output one here also.
Initialize xcoff_lastfile. */
#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(FILE,FILENAME) \
- xcoff_lastfile = input_file_name
+ xcoff_lastfile = (FILENAME)
/* If we are still in an include file, its end must be marked. */
#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
{ \
if (xcoff_current_include_file) \
{ \
- fprintf (FILE, "\t.ei\t"); \
- output_quoted_string (FILE, xcoff_current_include_file); \
- fprintf (FILE, "\n"); \
+ fputs ("\t.ei\t", (FILE)); \
+ output_quoted_string ((FILE), xcoff_current_include_file); \
+ putc ('\n', (FILE)); \
xcoff_current_include_file = NULL; \
} \
}